1010import software .coley .recaf .path .PathNode ;
1111import software .coley .recaf .util .StringUtil ;
1212
13+ import java .util .List ;
14+
1315/**
1416 * Tree item subtype for more convenience tree building operations.
1517 *
@@ -201,7 +203,6 @@ public static WorkspaceTreeNode getOrInsertIntoTree(@Nonnull WorkspaceTreeNode n
201203 * @return Inserted node.
202204 */
203205 @ Nonnull
204- @ SuppressWarnings ("deprecation" )
205206 public static WorkspaceTreeNode getOrInsertIntoTree (@ Nonnull WorkspaceTreeNode node , @ Nonnull PathNode <?> path , boolean sorted ) {
206207 // Edge case handling for directory nodes.
207208 if (path instanceof DirectoryPathNode directoryPath ) {
@@ -234,24 +235,17 @@ public static WorkspaceTreeNode getOrInsertIntoTree(@Nonnull WorkspaceTreeNode n
234235 DirectoryPathNode localPathNode = directoryPath .withDirectory (directoryName );
235236
236237 // Get existing tree node, or create child if non-existent
237- WorkspaceTreeNode childNode = null ;
238- ObservableList <TreeItem <PathNode <?>>> children ;
239- if (node instanceof FilterableTreeItem <?> filterableNode )
240- children = Unchecked .cast (filterableNode .getSourceChildren ());
241- else
242- children = node .getChildren ();
243- for (TreeItem <PathNode <?>> child : children )
244- if (child .getValue ().equals (localPathNode )) {
245- childNode = (WorkspaceTreeNode ) child ;
246- break ;
247- }
248- if (childNode == null ) {
238+ WorkspaceTreeNode childNode ;
239+ ObservableList <WorkspaceTreeNode > children = Unchecked .cast (node .getSourceChildren ());
240+ int index = binaryUnboxingSearch (children , localPathNode );
241+ if (index >= 0 )
242+ childNode = children .get (index );
243+ else {
249244 childNode = new WorkspaceTreeNode (localPathNode );
250- if (sorted ) {
245+ if (sorted )
251246 node .addPreSortedChild (childNode );
252- } else {
253- node .addAndSortChild (childNode );
254- }
247+ else
248+ node .addPreSortedChild (childNode , -(index + 1 ));
255249 }
256250
257251 // Prepare for next directory path entry.
@@ -272,22 +266,39 @@ else if (path.typeIdMatch(node.getValue())) {
272266 }
273267
274268 // Check if already inserted.
275- ObservableList <TreeItem <PathNode <?>>> children ;
276- if (node instanceof FilterableTreeItem <?> filterableNode )
277- children = Unchecked .cast (filterableNode .getSourceChildren ());
278- else
279- children = node .getChildren ();
280- for (TreeItem <PathNode <?>> child : children )
281- if (path .equals (child .getValue ()))
282- return (WorkspaceTreeNode ) child ;
269+ ObservableList <WorkspaceTreeNode > children = Unchecked .cast (node .getSourceChildren ());
270+ WorkspaceTreeNode inserted ;//= new WorkspaceTreeNode(path);
271+ int index = binaryUnboxingSearch (children , path );
272+ if (index >= 0 )
273+ return children .get (index );
274+ inserted = new WorkspaceTreeNode (path );
283275
284276 // Not already inserted, create a new node and insert it.
285- WorkspaceTreeNode inserted = new WorkspaceTreeNode (path );
286- if (sorted ) {
277+ if (sorted )
287278 node .addPreSortedChild (inserted );
288- } else {
289- node .addAndSortChild (inserted );
290- }
279+ else
280+ node .addPreSortedChild (inserted , -( index + 1 ) );
281+
291282 return inserted ;
292283 }
284+
285+ /**
286+ * Binary search but using {@link PathNode#localCompare(software.coley.recaf.path.PathNode)}
287+ * rather than the standard {@link java.lang.Comparable#compareTo(java.lang.Object)}.
288+ */
289+ private static int binaryUnboxingSearch (@ Nonnull List <WorkspaceTreeNode > items , @ Nonnull PathNode <?> target ) {
290+ int first = 0 ;
291+ int last = items .size () - 1 ;
292+ while (first <= last ) {
293+ int middle = (first + last ) >>> 1 ;
294+ int compResult = items .get (middle ).getValue ().localCompare (target );
295+ if (compResult < 0 )
296+ first = middle + 1 ;
297+ else if (compResult > 0 )
298+ last = middle - 1 ;
299+ else
300+ return middle ;
301+ }
302+ return -(first + 1 );
303+ }
293304}
0 commit comments