Improve background indexing
emmanue1
5 years ago
17 | 17 | import java.nio.file.Path; |
18 | 18 | import java.util.Collection; |
19 | 19 | import java.util.Map; |
20 | import java.util.concurrent.Future; | |
20 | 21 | |
21 | 22 | public interface API { |
22 | 23 | boolean openURI(URI uri); |
47 | 48 | |
48 | 49 | Map<String, String> getPreferences(); |
49 | 50 | |
50 | Collection<Indexes> getCollectionOfIndexes(); | |
51 | Collection<Future<Indexes>> getCollectionOfFutureIndexes(); | |
51 | 52 | } |
9 | 9 | import org.jd.gui.api.model.Indexes; |
10 | 10 | |
11 | 11 | import java.util.Collection; |
12 | import java.util.concurrent.Future; | |
12 | 13 | |
13 | 14 | public interface IndexesChangeListener { |
14 | void indexesChanged(Collection<Indexes> collectionOfIndexes); | |
15 | void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes); | |
15 | 16 | } |
63 | 63 | * </ul> |
64 | 64 | */ |
65 | 65 | public interface Indexes { |
66 | void waitIndexers(); | |
67 | ||
68 | 66 | Map<String, Collection> getIndex(String name); |
69 | 67 | } |
66 | 66 | |
67 | 67 | protected History history = new History(); |
68 | 68 | protected JComponent currentPage = null; |
69 | protected ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); | |
69 | protected ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); | |
70 | 70 | protected ArrayList<IndexesChangeListener> containerChangeListeners = new ArrayList<>(); |
71 | 71 | |
72 | 72 | @SuppressWarnings("unchecked") |
110 | 110 | file -> openFile((File)file)); |
111 | 111 | }); |
112 | 112 | } |
113 | ||
113 | ||
114 | 114 | // --- Show GUI --- // |
115 | 115 | @SuppressWarnings("unchecked") |
116 | 116 | public void show(List<File> files) { |
131 | 131 | IndexerService.getInstance(); |
132 | 132 | TreeNodeFactoryService.getInstance(); |
133 | 133 | TypeFactoryService.getInstance(); |
134 | PasteHandlerService.getInstance(); | |
135 | PreferencesPanelService.getInstance(); | |
136 | ContextualActionsFactoryService.getInstance(); | |
137 | 134 | |
138 | 135 | SwingUtil.invokeLater(() -> { |
139 | 136 | // Populate recent files menu |
158 | 155 | new JLayer(); |
159 | 156 | }); |
160 | 157 | }, 400, TimeUnit.MILLISECONDS); |
158 | ||
159 | PasteHandlerService.getInstance(); | |
160 | PreferencesPanelService.getInstance(); | |
161 | ContextualActionsFactoryService.getInstance(); | |
162 | SourceSaverService.getInstance(); | |
161 | 163 | } |
162 | 164 | |
163 | 165 | // --- Actions --- // |
311 | 313 | } |
312 | 314 | |
313 | 315 | protected void onOpenType() { |
314 | openTypeController.show(getCollectionOfIndexes(), uri -> openURI(uri)); | |
316 | openTypeController.show(getCollectionOfFutureIndexes(), uri -> openURI(uri)); | |
315 | 317 | } |
316 | 318 | |
317 | 319 | protected void onOpenTypeHierarchy() { |
318 | 320 | if (currentPage instanceof FocusedTypeGettable) { |
319 | 321 | FocusedTypeGettable ftg = (FocusedTypeGettable)currentPage; |
320 | openTypeHierarchyController.show(getCollectionOfIndexes(), ftg.getEntry(), ftg.getFocusedTypeName(), uri -> openURI(uri)); | |
322 | openTypeHierarchyController.show(getCollectionOfFutureIndexes(), ftg.getEntry(), ftg.getFocusedTypeName(), uri -> openURI(uri)); | |
321 | 323 | } |
322 | 324 | } |
323 | 325 | |
329 | 331 | } |
330 | 332 | |
331 | 333 | protected void onSearch() { |
332 | searchInConstantPoolsController.show(getCollectionOfIndexes(), uri -> openURI(uri)); | |
334 | searchInConstantPoolsController.show(getCollectionOfFutureIndexes(), uri -> openURI(uri)); | |
333 | 335 | } |
334 | 336 | |
335 | 337 | protected void onFindPrevious() { |
379 | 381 | |
380 | 382 | protected void onCurrentPageChanged(JComponent page) { |
381 | 383 | currentPage = page; |
384 | checkPreferencesChange(page); | |
382 | 385 | checkIndexesChange(page); |
383 | checkPreferencesChange(page); | |
384 | } | |
385 | ||
386 | protected void checkIndexesChange(JComponent page) { | |
387 | if (page instanceof IndexesChangeListener) { | |
388 | Collection<Indexes> collectionOfIndexes = getCollectionOfIndexes(); | |
389 | Integer currentHashcode = Integer.valueOf(collectionOfIndexes.hashCode()); | |
390 | Integer lastHashcode = (Integer)page.getClientProperty("collectionOfIndexes-stamp"); | |
391 | ||
392 | if (!currentHashcode.equals(lastHashcode)) { | |
393 | ((IndexesChangeListener)page).indexesChanged(collectionOfIndexes); | |
394 | page.putClientProperty("collectionOfIndexes-stamp", currentHashcode); | |
395 | } | |
396 | } | |
397 | 386 | } |
398 | 387 | |
399 | 388 | protected void checkPreferencesChange(JComponent page) { |
400 | 389 | if (page instanceof PreferencesChangeListener) { |
401 | 390 | Map<String, String> preferences = configuration.getPreferences(); |
402 | 391 | Integer currentHashcode = Integer.valueOf(preferences.hashCode()); |
403 | Integer lastHashcode = (Integer)page.getClientProperty("preferences-stamp"); | |
392 | Integer lastHashcode = (Integer)page.getClientProperty("preferences-hashCode"); | |
404 | 393 | |
405 | 394 | if (!currentHashcode.equals(lastHashcode)) { |
406 | 395 | ((PreferencesChangeListener)page).preferencesChanged(preferences); |
407 | page.putClientProperty("preferences-stamp", currentHashcode); | |
396 | page.putClientProperty("preferences-hashCode", currentHashcode); | |
397 | } | |
398 | } | |
399 | } | |
400 | ||
401 | protected void checkIndexesChange(JComponent page) { | |
402 | if (page instanceof IndexesChangeListener) { | |
403 | Collection<Future<Indexes>> collectionOfFutureIndexes = getCollectionOfFutureIndexes(); | |
404 | Integer currentHashcode = Integer.valueOf(collectionOfFutureIndexes.hashCode()); | |
405 | Integer lastHashcode = (Integer)page.getClientProperty("collectionOfFutureIndexes-hashCode"); | |
406 | ||
407 | if (!currentHashcode.equals(lastHashcode)) { | |
408 | ((IndexesChangeListener)page).indexesChanged(collectionOfFutureIndexes); | |
409 | page.putClientProperty("collectionOfFutureIndexes-hashCode", currentHashcode); | |
408 | 410 | } |
409 | 411 | } |
410 | 412 | } |
515 | 517 | protected void panelClosed() { |
516 | 518 | SwingUtil.invokeLater(() -> { |
517 | 519 | // Fire 'indexesChanged' event |
518 | Collection<Indexes> collectionOfIndexes = getCollectionOfIndexes(); | |
520 | Collection<Future<Indexes>> collectionOfFutureIndexes = getCollectionOfFutureIndexes(); | |
519 | 521 | for (IndexesChangeListener listener : containerChangeListeners) { |
520 | listener.indexesChanged(collectionOfIndexes); | |
522 | listener.indexesChanged(collectionOfFutureIndexes); | |
521 | 523 | } |
522 | 524 | if (currentPage instanceof IndexesChangeListener) { |
523 | ((IndexesChangeListener)currentPage).indexesChanged(collectionOfIndexes); | |
525 | ((IndexesChangeListener)currentPage).indexesChanged(collectionOfFutureIndexes); | |
524 | 526 | } |
525 | 527 | }); |
526 | 528 | } |
555 | 557 | if (entries.size() == 1) { |
556 | 558 | // Open the single entry uri |
557 | 559 | Container.Entry entry = entries.iterator().next(); |
558 | return openURI(UriUtil.createURI(this, getCollectionOfIndexes(), entry, query, fragment)); | |
560 | return openURI(UriUtil.createURI(this, getCollectionOfFutureIndexes(), entry, query, fragment)); | |
559 | 561 | } else { |
560 | 562 | // Multiple entries -> Open a "Select location" popup |
561 | Collection<Indexes> collectionOfIndexes = getCollectionOfIndexes(); | |
563 | Collection<Future<Indexes>> collectionOfFutureIndexes = getCollectionOfFutureIndexes(); | |
562 | 564 | selectLocationController.show( |
563 | 565 | new Point(x+(16+2), y+2), |
564 | 566 | entries, |
565 | entry -> openURI(UriUtil.createURI(this, collectionOfIndexes, entry, query, fragment)), // entry selected closure | |
566 | () -> {}); // popup close closure | |
567 | entry -> openURI(UriUtil.createURI(this, collectionOfFutureIndexes, entry, query, fragment)), // entry selected closure | |
568 | () -> {}); // popup close closure | |
567 | 569 | return true; |
568 | 570 | } |
569 | 571 | } |
585 | 587 | mainView.addMainPanel(title, icon, tip, component); |
586 | 588 | |
587 | 589 | if (component instanceof ContentIndexable) { |
588 | Future<Indexes> futureIndexes = executor.submit(() -> ((ContentIndexable)component).index(this)); | |
589 | Indexes indexes = new Indexes() { | |
590 | @Override public void waitIndexers() { | |
591 | try { | |
592 | futureIndexes.get(); | |
593 | } catch (Exception e) { | |
594 | assert ExceptionUtil.printStackTrace(e); | |
590 | Future<Indexes> futureIndexes = executor.submit(() -> { | |
591 | Indexes indexes = ((ContentIndexable)component).index(this); | |
592 | ||
593 | SwingUtil.invokeLater(() -> { | |
594 | // Fire 'indexesChanged' event | |
595 | Collection<Future<Indexes>> collectionOfFutureIndexes = getCollectionOfFutureIndexes(); | |
596 | for (IndexesChangeListener listener : containerChangeListeners) { | |
597 | listener.indexesChanged(collectionOfFutureIndexes); | |
595 | 598 | } |
596 | } | |
597 | @Override public Map<String, Collection> getIndex(String name) { | |
598 | try { | |
599 | return futureIndexes.get().getIndex(name); | |
600 | } catch (Exception e) { | |
601 | assert ExceptionUtil.printStackTrace(e); | |
602 | return null; | |
599 | if (currentPage instanceof IndexesChangeListener) { | |
600 | ((IndexesChangeListener) currentPage).indexesChanged(collectionOfFutureIndexes); | |
603 | 601 | } |
604 | } | |
605 | }; | |
606 | ||
607 | component.putClientProperty("indexes", indexes); | |
608 | ||
609 | SwingUtil.invokeLater(() -> { | |
610 | // Fire 'indexesChanged' event | |
611 | Collection<Indexes> collectionOfIndexes = getCollectionOfIndexes(); | |
612 | for (IndexesChangeListener listener : containerChangeListeners) { | |
613 | listener.indexesChanged(collectionOfIndexes); | |
614 | } | |
615 | if (currentPage instanceof IndexesChangeListener) { | |
616 | ((IndexesChangeListener)currentPage).indexesChanged(collectionOfIndexes); | |
617 | } | |
602 | }); | |
603 | ||
604 | return indexes; | |
618 | 605 | }); |
619 | } | |
620 | ||
621 | checkIndexesChange(currentPage); | |
606 | ||
607 | component.putClientProperty("indexes", futureIndexes); | |
608 | } | |
622 | 609 | } |
623 | 610 | |
624 | 611 | @Override public Collection<Action> getContextualActions(Container.Entry entry, String fragment) { return ContextualActionsFactoryService.getInstance().get(this, entry, fragment); } |
641 | 628 | |
642 | 629 | @Override public Map<String, String> getPreferences() { return configuration.getPreferences(); } |
643 | 630 | |
631 | @Override | |
644 | 632 | @SuppressWarnings("unchecked") |
645 | public Collection<Indexes> getCollectionOfIndexes() { | |
633 | public Collection<Future<Indexes>> getCollectionOfFutureIndexes() { | |
646 | 634 | List<JComponent> mainPanels = mainView.getMainPanels(); |
647 | ArrayList<Indexes> list = new ArrayList<>(mainPanels.size()); | |
635 | ArrayList<Future<Indexes>> list = new ArrayList<Future<Indexes>>(mainPanels.size()) { | |
636 | @Override | |
637 | public int hashCode() { | |
638 | int hashCode = 1; | |
639 | ||
640 | try { | |
641 | for (Future<Indexes> futureIndexes : this) { | |
642 | hashCode *= 31; | |
643 | ||
644 | if (futureIndexes.isDone()) { | |
645 | hashCode += futureIndexes.get().hashCode(); | |
646 | } | |
647 | } | |
648 | } catch (Exception e) { | |
649 | assert ExceptionUtil.printStackTrace(e); | |
650 | } | |
651 | ||
652 | return hashCode; | |
653 | } | |
654 | }; | |
648 | 655 | |
649 | 656 | for (JComponent panel : mainPanels) { |
650 | Indexes indexes = (Indexes)panel.getClientProperty("indexes"); | |
651 | ||
652 | if (indexes != null) { | |
653 | list.add(indexes); | |
657 | Future<Indexes> futureIndexes = (Future<Indexes>)panel.getClientProperty("indexes"); | |
658 | if (futureIndexes != null) { | |
659 | list.add(futureIndexes); | |
654 | 660 | } |
655 | 661 | } |
656 | 662 |
10 | 10 | import org.jd.gui.api.feature.IndexesChangeListener; |
11 | 11 | import org.jd.gui.api.model.Container; |
12 | 12 | import org.jd.gui.api.model.Indexes; |
13 | import org.jd.gui.util.exception.ExceptionUtil; | |
13 | 14 | import org.jd.gui.util.net.UriUtil; |
14 | 15 | import org.jd.gui.view.OpenTypeView; |
15 | 16 | |
17 | 18 | import java.awt.*; |
18 | 19 | import java.net.URI; |
19 | 20 | import java.util.*; |
21 | import java.util.concurrent.Future; | |
20 | 22 | import java.util.concurrent.ScheduledExecutorService; |
21 | 23 | import java.util.function.Consumer; |
22 | 24 | import java.util.regex.Pattern; |
26 | 28 | |
27 | 29 | protected API api; |
28 | 30 | protected ScheduledExecutorService executor; |
29 | protected Collection<Indexes> collectionOfIndexes; | |
31 | protected Collection<Future<Indexes>> collectionOfFutureIndexes; | |
30 | 32 | protected Consumer<URI> openCallback; |
31 | 33 | |
32 | 34 | protected JFrame mainFrame; |
52 | 54 | }; |
53 | 55 | } |
54 | 56 | |
55 | public void show(Collection<Indexes> collectionOfIndexes, Consumer<URI> openCallback) { | |
57 | public void show(Collection<Future<Indexes>> collectionOfFutureIndexes, Consumer<URI> openCallback) { | |
56 | 58 | // Init attributes |
57 | this.collectionOfIndexes = collectionOfIndexes; | |
59 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
58 | 60 | this.openCallback = openCallback; |
59 | 61 | // Refresh view |
60 | long hashCode = collectionOfIndexes.hashCode(); | |
62 | long hashCode = collectionOfFutureIndexes.hashCode(); | |
61 | 63 | if (hashCode != indexesHashCode) { |
62 | 64 | // List of indexes has changed -> Refresh result list |
63 | 65 | updateList(openTypeView.getPattern()); |
79 | 81 | // Waiting the end of indexation... |
80 | 82 | openTypeView.showWaitCursor(); |
81 | 83 | |
82 | for (Indexes indexes : collectionOfIndexes) { | |
83 | indexes.waitIndexers(); | |
84 | } | |
85 | ||
86 | 84 | Pattern regExpPattern = createRegExpPattern(pattern); |
87 | 85 | Map<String, Collection<Container.Entry>> result = new HashMap<>(); |
88 | 86 | |
89 | for (Indexes indexes : collectionOfIndexes) { | |
90 | String key = String.valueOf(indexes.hashCode()) + "***" + pattern; | |
91 | Map<String, Collection> matchingEntries = cache.get(key); | |
92 | ||
93 | if (matchingEntries != null) { | |
94 | // Merge 'result' and 'matchingEntries' | |
95 | for (Map.Entry<String, Collection> mapEntry : matchingEntries.entrySet()) { | |
96 | Collection<Container.Entry> collection = result.get(mapEntry.getKey()); | |
97 | if (collection == null) { | |
98 | result.put(mapEntry.getKey(), collection = new HashSet<>()); | |
99 | } | |
100 | collection.addAll(mapEntry.getValue()); | |
101 | } | |
102 | } else { | |
103 | // Waiting the end of indexation... | |
104 | Map<String, Collection> index = indexes.getIndex("typeDeclarations"); | |
105 | ||
106 | if ((index != null) && !index.isEmpty()) { | |
107 | matchingEntries = new HashMap<>(); | |
108 | ||
109 | // Filter | |
110 | if (patternLength == 1) { | |
111 | match(pattern.charAt(0), index, matchingEntries); | |
87 | try { | |
88 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
89 | if (futureIndexes.isDone()) { | |
90 | Indexes indexes = futureIndexes.get(); | |
91 | String key = String.valueOf(indexes.hashCode()) + "***" + pattern; | |
92 | Map<String, Collection> matchingEntries = cache.get(key); | |
93 | ||
94 | if (matchingEntries != null) { | |
95 | // Merge 'result' and 'matchingEntries' | |
96 | for (Map.Entry<String, Collection> mapEntry : matchingEntries.entrySet()) { | |
97 | Collection<Container.Entry> collection = result.get(mapEntry.getKey()); | |
98 | if (collection == null) { | |
99 | result.put(mapEntry.getKey(), collection = new HashSet<>()); | |
100 | } | |
101 | collection.addAll(mapEntry.getValue()); | |
102 | } | |
112 | 103 | } else { |
113 | String lastKey = key.substring(0, patternLength - 1); | |
114 | Map<String, Collection> lastResult = cache.get(lastKey); | |
115 | ||
116 | if (lastResult != null) { | |
117 | match(regExpPattern, lastResult, matchingEntries); | |
118 | } else { | |
119 | match(regExpPattern, index, matchingEntries); | |
104 | // Waiting the end of indexation... | |
105 | Map<String, Collection> index = indexes.getIndex("typeDeclarations"); | |
106 | ||
107 | if ((index != null) && !index.isEmpty()) { | |
108 | matchingEntries = new HashMap<>(); | |
109 | ||
110 | // Filter | |
111 | if (patternLength == 1) { | |
112 | match(pattern.charAt(0), index, matchingEntries); | |
113 | } else { | |
114 | String lastKey = key.substring(0, patternLength - 1); | |
115 | Map<String, Collection> lastResult = cache.get(lastKey); | |
116 | ||
117 | if (lastResult != null) { | |
118 | match(regExpPattern, lastResult, matchingEntries); | |
119 | } else { | |
120 | match(regExpPattern, index, matchingEntries); | |
121 | } | |
122 | } | |
123 | ||
124 | // Store 'matchingEntries' | |
125 | cache.put(key, matchingEntries); | |
126 | ||
127 | // Merge 'result' and 'matchingEntries' | |
128 | for (Map.Entry<String, Collection> mapEntry : matchingEntries.entrySet()) { | |
129 | Collection<Container.Entry> collection = result.get(mapEntry.getKey()); | |
130 | if (collection == null) { | |
131 | result.put(mapEntry.getKey(), collection = new HashSet<>()); | |
132 | } | |
133 | collection.addAll(mapEntry.getValue()); | |
134 | } | |
120 | 135 | } |
121 | } | |
122 | ||
123 | // Store 'matchingEntries' | |
124 | cache.put(key, matchingEntries); | |
125 | ||
126 | // Merge 'result' and 'matchingEntries' | |
127 | for (Map.Entry<String, Collection> mapEntry : matchingEntries.entrySet()) { | |
128 | Collection<Container.Entry> collection = result.get(mapEntry.getKey()); | |
129 | if (collection == null) { | |
130 | result.put(mapEntry.getKey(), collection = new HashSet<>()); | |
131 | } | |
132 | collection.addAll(mapEntry.getValue()); | |
133 | 136 | } |
134 | 137 | } |
135 | 138 | } |
139 | } catch (Exception e) { | |
140 | assert ExceptionUtil.printStackTrace(e); | |
136 | 141 | } |
137 | 142 | |
138 | 143 | SwingUtilities.invokeLater(() -> { |
250 | 255 | protected void onTypeSelected(Point leftBottom, Collection<Container.Entry> entries, String typeName) { |
251 | 256 | if (entries.size() == 1) { |
252 | 257 | // Open the single entry uri |
253 | openCallback.accept(UriUtil.createURI(api, collectionOfIndexes, entries.iterator().next(), null, typeName)); | |
258 | openCallback.accept(UriUtil.createURI(api, collectionOfFutureIndexes, entries.iterator().next(), null, typeName)); | |
254 | 259 | } else { |
255 | 260 | // Multiple entries -> Open a "Select location" popup |
256 | 261 | selectLocationController.show( |
257 | 262 | new Point(leftBottom.x+(16+2), leftBottom.y+2), |
258 | 263 | entries, |
259 | (entry) -> openCallback.accept(UriUtil.createURI(api, collectionOfIndexes, entry, null, typeName)), // entry selected callback | |
260 | () -> openTypeView.focus()); // popup close callback | |
264 | (entry) -> openCallback.accept(UriUtil.createURI(api, collectionOfFutureIndexes, entry, null, typeName)), // entry selected callback | |
265 | () -> openTypeView.focus()); // popup close callback | |
261 | 266 | } |
262 | 267 | } |
263 | 268 | |
264 | 269 | // --- IndexesChangeListener --- // |
265 | public void indexesChanged(Collection<Indexes> collectionOfIndexes) { | |
270 | public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
266 | 271 | if (openTypeView.isVisible()) { |
267 | 272 | // Update the list of containers |
268 | this.collectionOfIndexes = collectionOfIndexes; | |
273 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
269 | 274 | // And refresh |
270 | 275 | updateList(openTypeView.getPattern()); |
271 | 276 | } |
17 | 17 | import java.awt.*; |
18 | 18 | import java.net.URI; |
19 | 19 | import java.util.Collection; |
20 | import java.util.Collections; | |
21 | import java.util.concurrent.Future; | |
20 | 22 | import java.util.concurrent.ScheduledExecutorService; |
21 | 23 | import java.util.function.Consumer; |
22 | 24 | |
28 | 30 | protected OpenTypeHierarchyView openTypeHierarchyView; |
29 | 31 | protected SelectLocationController selectLocationController; |
30 | 32 | |
31 | protected Collection<Indexes> collectionOfIndexes; | |
33 | protected Collection<Future<Indexes>> collectionOfFutureIndexes; | |
32 | 34 | protected Consumer<URI> openCallback; |
33 | 35 | |
34 | 36 | public OpenTypeHierarchyController(API api, ScheduledExecutorService executor, JFrame mainFrame) { |
40 | 42 | selectLocationController = new SelectLocationController(api, mainFrame); |
41 | 43 | } |
42 | 44 | |
43 | public void show(Collection<Indexes> collectionOfIndexes, Container.Entry entry, String typeName, Consumer<URI> openCallback) { | |
45 | public void show(Collection<Future<Indexes>> collectionOfFutureIndexes, Container.Entry entry, String typeName, Consumer<URI> openCallback) { | |
44 | 46 | // Init attributes |
45 | this.collectionOfIndexes = collectionOfIndexes; | |
47 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
46 | 48 | this.openCallback = openCallback; |
47 | 49 | executor.execute(() -> { |
48 | 50 | // Waiting the end of indexation... |
49 | 51 | openTypeHierarchyView.showWaitCursor(); |
50 | for (Indexes indexes : collectionOfIndexes) { | |
51 | indexes.waitIndexers(); | |
52 | } | |
53 | 52 | SwingUtilities.invokeLater(() -> { |
54 | 53 | openTypeHierarchyView.hideWaitCursor(); |
55 | 54 | // Show |
56 | openTypeHierarchyView.show(collectionOfIndexes, entry, typeName); | |
55 | openTypeHierarchyView.show(collectionOfFutureIndexes, entry, typeName); | |
57 | 56 | }); |
58 | 57 | }); |
59 | 58 | } |
61 | 60 | protected void onTypeSelected(Point leftBottom, Collection<Container.Entry> entries, String typeName) { |
62 | 61 | if (entries.size() == 1) { |
63 | 62 | // Open the single entry uri |
64 | openCallback.accept(UriUtil.createURI(api, collectionOfIndexes, entries.iterator().next(), null, typeName)); | |
63 | openCallback.accept(UriUtil.createURI(api, collectionOfFutureIndexes, entries.iterator().next(), null, typeName)); | |
65 | 64 | } else { |
66 | 65 | // Multiple entries -> Open a "Select location" popup |
67 | 66 | selectLocationController.show( |
68 | 67 | new Point(leftBottom.x+(16+2), leftBottom.y+2), |
69 | 68 | entries, |
70 | (entry) -> openCallback.accept(UriUtil.createURI(api, collectionOfIndexes, entry, null, typeName)), // entry selected | |
69 | (entry) -> openCallback.accept(UriUtil.createURI(api, collectionOfFutureIndexes, entry, null, typeName)), // entry selected | |
71 | 70 | () -> openTypeHierarchyView.focus()); // popup closeClosure |
72 | 71 | } |
73 | 72 | } |
74 | 73 | |
75 | 74 | // --- IndexesChangeListener --- // |
76 | public void indexesChanged(Collection<Indexes> collectionOfIndexes) { | |
75 | public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
77 | 76 | if (openTypeHierarchyView.isVisible()) { |
78 | 77 | // Update the list of containers |
79 | this.collectionOfIndexes = collectionOfIndexes; | |
78 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
80 | 79 | // And refresh |
81 | openTypeHierarchyView.updateTree(collectionOfIndexes); | |
80 | openTypeHierarchyView.updateTree(collectionOfFutureIndexes); | |
82 | 81 | } |
83 | 82 | } |
84 | 83 | } |
11 | 11 | import org.jd.gui.api.model.Container; |
12 | 12 | import org.jd.gui.api.model.Indexes; |
13 | 13 | import org.jd.gui.api.model.Type; |
14 | import org.jd.gui.model.container.FilteredContainerWrapper; | |
14 | import org.jd.gui.model.container.DelegatingFilterContainer; | |
15 | 15 | import org.jd.gui.service.type.TypeFactoryService; |
16 | 16 | import org.jd.gui.spi.TypeFactory; |
17 | 17 | import org.jd.gui.util.exception.ExceptionUtil; |
22 | 22 | import java.net.URI; |
23 | 23 | import java.net.URISyntaxException; |
24 | 24 | import java.util.*; |
25 | import java.util.concurrent.Future; | |
25 | 26 | import java.util.concurrent.ScheduledExecutorService; |
26 | 27 | import java.util.function.BiConsumer; |
27 | 28 | import java.util.function.BiFunction; |
37 | 38 | protected JFrame mainFrame; |
38 | 39 | protected SearchInConstantPoolsView searchInConstantPoolsView; |
39 | 40 | protected Map<String, Map<String, Collection>> cache; |
40 | protected Set<FilteredContainerWrapper> filteredContainerWrappers = new HashSet<>(); | |
41 | protected Collection<Indexes> collectionOfIndexes; | |
41 | protected Set<DelegatingFilterContainer> delegatingFilterContainers = new HashSet<>(); | |
42 | protected Collection<Future<Indexes>> collectionOfFutureIndexes; | |
42 | 43 | protected Consumer<URI> openCallback; |
43 | 44 | protected long indexesHashCode = 0L; |
44 | 45 | |
66 | 67 | }; |
67 | 68 | } |
68 | 69 | |
69 | public void show(Collection<Indexes> collectionOfIndexes, Consumer<URI> openCallback) { | |
70 | public void show(Collection<Future<Indexes>> collectionOfFutureIndexes, Consumer<URI> openCallback) { | |
70 | 71 | // Init attributes |
71 | this.collectionOfIndexes = collectionOfIndexes; | |
72 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
72 | 73 | this.openCallback = openCallback; |
73 | 74 | // Refresh view |
74 | long hashCode = collectionOfIndexes.hashCode(); | |
75 | long hashCode = collectionOfFutureIndexes.hashCode(); | |
75 | 76 | if (hashCode != indexesHashCode) { |
76 | 77 | // List of indexes has changed |
77 | 78 | updateTree(searchInConstantPoolsView.getPattern(), searchInConstantPoolsView.getFlags()); |
83 | 84 | |
84 | 85 | @SuppressWarnings("unchecked") |
85 | 86 | protected void updateTree(String pattern, int flags) { |
86 | filteredContainerWrappers.clear(); | |
87 | delegatingFilterContainers.clear(); | |
87 | 88 | |
88 | 89 | executor.execute(() -> { |
90 | // Waiting the end of indexation... | |
89 | 91 | searchInConstantPoolsView.showWaitCursor(); |
90 | 92 | |
91 | 93 | int matchingTypeCount = 0; |
92 | 94 | int patternLength = pattern.length(); |
93 | 95 | |
94 | 96 | if (patternLength > 0) { |
95 | // Waiting the end of indexation... | |
96 | for (Indexes indexes : collectionOfIndexes) { | |
97 | indexes.waitIndexers(); | |
98 | } | |
99 | ||
100 | for (Indexes indexes : collectionOfIndexes) { | |
101 | HashSet<Container.Entry> matchingEntries = new HashSet<>(); | |
102 | // Find matched entries | |
103 | filter(indexes, pattern, flags, matchingEntries); | |
104 | ||
105 | if (!matchingEntries.isEmpty()) { | |
106 | // Search root container with first matching entry | |
107 | Container.Entry parentEntry = matchingEntries.iterator().next(); | |
108 | Container container = null; | |
109 | ||
110 | while (parentEntry.getContainer().getRoot() != null) { | |
111 | container = parentEntry.getContainer(); | |
112 | parentEntry = container.getRoot().getParent(); | |
97 | try { | |
98 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
99 | if (futureIndexes.isDone()) { | |
100 | Indexes indexes = futureIndexes.get(); | |
101 | HashSet<Container.Entry> matchingEntries = new HashSet<>(); | |
102 | // Find matched entries | |
103 | filter(indexes, pattern, flags, matchingEntries); | |
104 | ||
105 | if (!matchingEntries.isEmpty()) { | |
106 | // Search root container with first matching entry | |
107 | Container.Entry parentEntry = matchingEntries.iterator().next(); | |
108 | Container container = null; | |
109 | ||
110 | while (parentEntry.getContainer().getRoot() != null) { | |
111 | container = parentEntry.getContainer(); | |
112 | parentEntry = container.getRoot().getParent(); | |
113 | } | |
114 | ||
115 | // TODO In a future release, display matching strings, types, inner-types, fields and methods, not only matching files | |
116 | matchingEntries = getOuterEntries(matchingEntries); | |
117 | ||
118 | matchingTypeCount += matchingEntries.size(); | |
119 | ||
120 | // Create a filtered container | |
121 | delegatingFilterContainers.add(new DelegatingFilterContainer(container, matchingEntries)); | |
122 | } | |
113 | 123 | } |
114 | ||
115 | // TODO In a future release, display matching strings, types, inner-types, fields and methods, not only matching files | |
116 | matchingEntries = getOuterEntries(matchingEntries); | |
117 | ||
118 | matchingTypeCount += matchingEntries.size(); | |
119 | ||
120 | // Create a filtered container | |
121 | filteredContainerWrappers.add(new FilteredContainerWrapper(container, matchingEntries)); | |
122 | 124 | } |
125 | } catch (Exception e) { | |
126 | assert ExceptionUtil.printStackTrace(e); | |
123 | 127 | } |
124 | 128 | } |
125 | 129 | |
126 | 130 | final int count = matchingTypeCount; |
127 | 131 | |
128 | 132 | searchInConstantPoolsView.hideWaitCursor(); |
129 | searchInConstantPoolsView.updateTree(filteredContainerWrappers, count); | |
133 | searchInConstantPoolsView.updateTree(delegatingFilterContainers, count); | |
130 | 134 | }); |
131 | 135 | } |
132 | 136 | |
401 | 405 | // Open the single entry uri |
402 | 406 | Container.Entry entry = null; |
403 | 407 | |
404 | for (FilteredContainerWrapper container : filteredContainerWrappers) { | |
408 | for (DelegatingFilterContainer container : delegatingFilterContainers) { | |
405 | 409 | entry = container.getEntry(uri); |
406 | 410 | if (entry != null) |
407 | 411 | break; |
436 | 440 | // sbPattern.append(type.name) |
437 | 441 | // |
438 | 442 | // def query = sbPattern.toString() |
439 | // def outerPath = UriUtil.getOuterPath(collectionOfIndexes, entry, type) | |
443 | // def outerPath = UriUtil.getOuterPath(collectionOfFutureIndexes, entry, type) | |
440 | 444 | // |
441 | 445 | // openClosure(new URI(entry.uri.scheme, entry.uri.host, outerPath, query, null)) |
442 | 446 | // } else { |
453 | 457 | } |
454 | 458 | |
455 | 459 | // --- IndexesChangeListener --- // |
456 | public void indexesChanged(Collection<Indexes> collectionOfIndexes) { | |
460 | public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
457 | 461 | if (searchInConstantPoolsView.isVisible()) { |
458 | 462 | // Update the list of containers |
459 | this.collectionOfIndexes = collectionOfIndexes; | |
463 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
460 | 464 | // And refresh |
461 | 465 | updateTree(searchInConstantPoolsView.getPattern(), searchInConstantPoolsView.getFlags()); |
462 | 466 | } |
9 | 9 | import org.jd.gui.api.API; |
10 | 10 | import org.jd.gui.api.model.Container; |
11 | 11 | import org.jd.gui.api.model.Type; |
12 | import org.jd.gui.model.container.FilteredContainerWrapper; | |
12 | import org.jd.gui.model.container.DelegatingFilterContainer; | |
13 | 13 | import org.jd.gui.service.type.TypeFactoryService; |
14 | 14 | import org.jd.gui.spi.TypeFactory; |
15 | 15 | import org.jd.gui.view.SelectLocationView; |
59 | 59 | list.add(entry); |
60 | 60 | } |
61 | 61 | |
62 | HashSet<FilteredContainerWrapper> filteredContainerWrappers = new HashSet<>(); | |
62 | HashSet<DelegatingFilterContainer> delegatingFilterContainers = new HashSet<>(); | |
63 | 63 | |
64 | 64 | for (Map.Entry<Container, ArrayList<Container.Entry>> mapEntry : map.entrySet()) { |
65 | 65 | Container container = mapEntry.getKey(); |
66 | 66 | // Create a filtered container |
67 | 67 | // TODO In a future release, display matching types and inner-types, not only matching files |
68 | filteredContainerWrappers.add(new FilteredContainerWrapper(container, getOuterEntries(mapEntry.getValue()))); | |
68 | delegatingFilterContainers.add(new DelegatingFilterContainer(container, getOuterEntries(mapEntry.getValue()))); | |
69 | 69 | } |
70 | 70 | |
71 | Consumer<URI> selectedEntryCallback = uri -> onLocationSelected(filteredContainerWrappers, uri, selectedLocationCallback); | |
71 | Consumer<URI> selectedEntryCallback = uri -> onLocationSelected(delegatingFilterContainers, uri, selectedLocationCallback); | |
72 | 72 | |
73 | selectLocationView.show(location, filteredContainerWrappers, entries.size(), selectedEntryCallback, closeCallback); | |
73 | selectLocationView.show(location, delegatingFilterContainers, entries.size(), selectedEntryCallback, closeCallback); | |
74 | 74 | } |
75 | 75 | |
76 | 76 | protected Collection<Container.Entry> getOuterEntries(Collection<Container.Entry> entries) { |
152 | 152 | return result; |
153 | 153 | } |
154 | 154 | |
155 | protected void onLocationSelected(Set<FilteredContainerWrapper> filteredContainerWrappers, URI uri, Consumer<Container.Entry> selectedLocationCallback) { | |
155 | protected void onLocationSelected(Set<DelegatingFilterContainer> delegatingFilterContainers, URI uri, Consumer<Container.Entry> selectedLocationCallback) { | |
156 | 156 | // Open the single entry uri |
157 | 157 | Container.Entry entry = null; |
158 | 158 | |
159 | for (FilteredContainerWrapper container : filteredContainerWrappers) { | |
159 | for (DelegatingFilterContainer container : delegatingFilterContainers) { | |
160 | 160 | entry = container.getEntry(uri); |
161 | 161 | if (entry != null) { |
162 | 162 | break; |
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.model.container; | |
8 | ||
9 | import org.jd.gui.api.model.Container; | |
10 | ||
11 | import java.io.InputStream; | |
12 | import java.net.URI; | |
13 | import java.util.*; | |
14 | ||
15 | public class DelegatingFilterContainer implements Container { | |
16 | protected static final URI DEFAULT_ROOT_URI = URI.create("file:."); | |
17 | ||
18 | protected Container container; | |
19 | protected DelegatedEntry root; | |
20 | ||
21 | protected Set<URI> validEntries = new HashSet<>(); | |
22 | protected Map<URI, DelegatedEntry> uriToDelegatedEntry = new HashMap<>(); | |
23 | protected Map<URI, DelegatedContainer> uriToDelegatedContainer = new HashMap<>(); | |
24 | ||
25 | public DelegatingFilterContainer(Container container, Collection<Entry> entries) { | |
26 | this.container = container; | |
27 | this.root = getDelegatedEntry(container.getRoot()); | |
28 | ||
29 | for (Entry entry : entries) { | |
30 | while ((entry != null) && !validEntries.contains(entry.getUri())) { | |
31 | validEntries.add(entry.getUri()); | |
32 | entry = entry.getParent(); | |
33 | } | |
34 | } | |
35 | } | |
36 | ||
37 | @Override public String getType() { return container.getType(); } | |
38 | @Override public Container.Entry getRoot() { return root; } | |
39 | ||
40 | public Container.Entry getEntry(URI uri) { return uriToDelegatedEntry.get(uri); } | |
41 | public Set<URI> getUris() { return validEntries; } | |
42 | ||
43 | protected DelegatedEntry getDelegatedEntry(Container.Entry entry) { | |
44 | URI uri = entry.getUri(); | |
45 | DelegatedEntry delegatedEntry = uriToDelegatedEntry.get(uri); | |
46 | if (delegatedEntry == null) { | |
47 | uriToDelegatedEntry.put(uri, delegatedEntry =new DelegatedEntry(entry)); | |
48 | } | |
49 | return delegatedEntry; | |
50 | } | |
51 | ||
52 | protected DelegatedContainer getDelegatedContainer(Container container) { | |
53 | Entry root = container.getRoot(); | |
54 | URI uri = (root == null) ? DEFAULT_ROOT_URI : root.getUri(); | |
55 | DelegatedContainer delegatedContainer = uriToDelegatedContainer.get(uri); | |
56 | if (delegatedContainer == null) { | |
57 | uriToDelegatedContainer.put(uri, delegatedContainer =new DelegatedContainer(container)); | |
58 | } | |
59 | return delegatedContainer; | |
60 | } | |
61 | ||
62 | protected class DelegatedEntry implements Entry, Comparable<DelegatedEntry> { | |
63 | protected Entry entry; | |
64 | protected Collection<Entry> children; | |
65 | ||
66 | public DelegatedEntry(Entry entry) { | |
67 | this.entry = entry; | |
68 | } | |
69 | ||
70 | @Override public Container getContainer() { return getDelegatedContainer(entry.getContainer()); } | |
71 | @Override public Entry getParent() { return getDelegatedEntry(entry.getParent()); } | |
72 | @Override public URI getUri() { return entry.getUri(); } | |
73 | @Override public String getPath() { return entry.getPath(); } | |
74 | @Override public boolean isDirectory() { return entry.isDirectory(); } | |
75 | @Override public long length() { return entry.length(); } | |
76 | @Override public InputStream getInputStream() { return entry.getInputStream(); } | |
77 | ||
78 | @Override | |
79 | public Collection<Entry> getChildren() { | |
80 | if (children == null) { | |
81 | children = new ArrayList<>(); | |
82 | for (Entry child : entry.getChildren()) { | |
83 | if (validEntries.contains(child.getUri())) { | |
84 | children.add(getDelegatedEntry(child)); | |
85 | } | |
86 | } | |
87 | } | |
88 | return children; | |
89 | } | |
90 | ||
91 | @Override | |
92 | public int compareTo(DelegatedEntry other) { | |
93 | if (entry.isDirectory()) { | |
94 | if (!other.isDirectory()) { | |
95 | return -1; | |
96 | } | |
97 | } else { | |
98 | if (other.isDirectory()) { | |
99 | return 1; | |
100 | } | |
101 | } | |
102 | return entry.getPath().compareTo(other.getPath()); | |
103 | } | |
104 | } | |
105 | ||
106 | protected class DelegatedContainer implements Container { | |
107 | protected Container container; | |
108 | ||
109 | public DelegatedContainer(Container container) { | |
110 | this.container = container; | |
111 | } | |
112 | ||
113 | @Override public String getType() { return container.getType(); } | |
114 | @Override public Entry getRoot() { return getDelegatedEntry(container.getRoot()); } | |
115 | } | |
116 | }⏎ |
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.model.container; | |
8 | ||
9 | import org.jd.gui.api.model.Container; | |
10 | ||
11 | import java.io.InputStream; | |
12 | import java.net.URI; | |
13 | import java.util.*; | |
14 | ||
15 | public class FilteredContainerWrapper implements Container { | |
16 | protected static final URI DEFAULT_ROOT_URI = URI.create("file:."); | |
17 | ||
18 | protected Container container; | |
19 | protected EntryWrapper root; | |
20 | ||
21 | protected Set<URI> validEntries = new HashSet<>(); | |
22 | protected Map<URI, EntryWrapper> uriToEntryWrapper = new HashMap<>(); | |
23 | protected Map<URI, ContainerWrapper> uriToContainerWrapper = new HashMap<>(); | |
24 | ||
25 | public FilteredContainerWrapper(Container container, Collection<Entry> entries) { | |
26 | this.container = container; | |
27 | this.root = getEntryWrapper(container.getRoot()); | |
28 | ||
29 | for (Entry entry : entries) { | |
30 | while ((entry != null) && !validEntries.contains(entry.getUri())) { | |
31 | validEntries.add(entry.getUri()); | |
32 | entry = entry.getParent(); | |
33 | } | |
34 | } | |
35 | } | |
36 | ||
37 | @Override public String getType() { return container.getType(); } | |
38 | @Override public Container.Entry getRoot() { return root; } | |
39 | ||
40 | public Container.Entry getEntry(URI uri) { return uriToEntryWrapper.get(uri); } | |
41 | public Set<URI> getUris() { return validEntries; } | |
42 | ||
43 | protected EntryWrapper getEntryWrapper(Container.Entry entry) { | |
44 | URI uri = entry.getUri(); | |
45 | EntryWrapper entryWrapper = uriToEntryWrapper.get(uri); | |
46 | if (entryWrapper == null) { | |
47 | uriToEntryWrapper.put(uri, entryWrapper=new EntryWrapper(entry)); | |
48 | } | |
49 | return entryWrapper; | |
50 | } | |
51 | ||
52 | protected ContainerWrapper getContainerWrapper(Container container) { | |
53 | Entry root = container.getRoot(); | |
54 | URI uri = (root == null) ? DEFAULT_ROOT_URI : root.getUri(); | |
55 | ContainerWrapper containerWrapper = uriToContainerWrapper.get(uri); | |
56 | if (containerWrapper == null) { | |
57 | uriToContainerWrapper.put(uri, containerWrapper=new ContainerWrapper(container)); | |
58 | } | |
59 | return containerWrapper; | |
60 | } | |
61 | ||
62 | protected class EntryWrapper implements Entry, Comparable<EntryWrapper> { | |
63 | protected Entry entry; | |
64 | protected Collection<Entry> children; | |
65 | ||
66 | public EntryWrapper(Entry entry) { | |
67 | this.entry = entry; | |
68 | } | |
69 | ||
70 | @Override public Container getContainer() { return getContainerWrapper(entry.getContainer()); } | |
71 | @Override public Entry getParent() { return getEntryWrapper(entry.getParent()); } | |
72 | @Override public URI getUri() { return entry.getUri(); } | |
73 | @Override public String getPath() { return entry.getPath(); } | |
74 | @Override public boolean isDirectory() { return entry.isDirectory(); } | |
75 | @Override public long length() { return entry.length(); } | |
76 | @Override public InputStream getInputStream() { return entry.getInputStream(); } | |
77 | ||
78 | @Override | |
79 | public Collection<Entry> getChildren() { | |
80 | if (children == null) { | |
81 | children = new ArrayList<>(); | |
82 | for (Entry child : entry.getChildren()) { | |
83 | if (validEntries.contains(child.getUri())) { | |
84 | children.add(getEntryWrapper(child)); | |
85 | } | |
86 | } | |
87 | } | |
88 | return children; | |
89 | } | |
90 | ||
91 | @Override | |
92 | public int compareTo(EntryWrapper other) { | |
93 | if (entry.isDirectory()) { | |
94 | if (!other.isDirectory()) { | |
95 | return -1; | |
96 | } | |
97 | } else { | |
98 | if (other.isDirectory()) { | |
99 | return 1; | |
100 | } | |
101 | } | |
102 | return entry.getPath().compareTo(other.getPath()); | |
103 | } | |
104 | } | |
105 | ||
106 | protected class ContainerWrapper implements Container { | |
107 | protected Container container; | |
108 | ||
109 | public ContainerWrapper(Container container) { | |
110 | this.container = container; | |
111 | } | |
112 | ||
113 | @Override public String getType() { return container.getType(); } | |
114 | @Override public Entry getRoot() { return getEntryWrapper(container.getRoot()); } | |
115 | } | |
116 | }⏎ |
66 | 66 | @Override |
67 | 67 | public Indexes index(API api) { |
68 | 68 | HashMap<String, Map<String, Collection>> map = new HashMap<>(); |
69 | MapMapCollectionWithDefault mapWithDefault = new MapMapCollectionWithDefault(map); | |
69 | DelegatedMapMapWithDefault mapWithDefault = new DelegatedMapMapWithDefault(map); | |
70 | 70 | |
71 | 71 | // Index populating value automatically |
72 | Indexes indexesWithDefault = new Indexes() { | |
73 | @Override public void waitIndexers() {} | |
74 | @Override public Map<String, Collection> getIndex(String name) { return mapWithDefault.get(name); } | |
75 | }; | |
72 | Indexes indexesWithDefault = name -> mapWithDefault.get(name); | |
76 | 73 | |
77 | 74 | // Index entry |
78 | 75 | Indexer indexer = api.getIndexer(entry); |
82 | 79 | } |
83 | 80 | |
84 | 81 | // To prevent memory leaks, return an index without the 'populate' behaviour |
85 | return new Indexes() { | |
86 | @Override public void waitIndexers() {} | |
87 | @Override public Map<String, Collection> getIndex(String name) { return map.get(name); } | |
88 | }; | |
82 | return name -> map.get(name); | |
89 | 83 | } |
90 | 84 | |
91 | 85 | // --- SourcesSavable --- // |
138 | 132 | } |
139 | 133 | } |
140 | 134 | |
141 | protected static class MapWrapper<K, V> implements Map<K, V> { | |
135 | protected static class DelegatedMap<K, V> implements Map<K, V> { | |
142 | 136 | protected Map<K, V> map; |
143 | 137 | |
144 | public MapWrapper(Map<K, V> map) { this.map = map; } | |
138 | public DelegatedMap(Map<K, V> map) { this.map = map; } | |
145 | 139 | |
146 | 140 | @Override public int size() { return map.size(); } |
147 | 141 | @Override public boolean isEmpty() { return map.isEmpty(); } |
159 | 153 | @Override public int hashCode() { return map.hashCode(); } |
160 | 154 | } |
161 | 155 | |
162 | protected static class MapCollectionWithDefault extends MapWrapper<String, Collection> { | |
163 | public MapCollectionWithDefault(Map<String, Collection> map) { super(map); } | |
156 | protected static class DelegatedMapWithDefault extends DelegatedMap<String, Collection> { | |
157 | public DelegatedMapWithDefault(Map<String, Collection> map) { super(map); } | |
164 | 158 | |
165 | 159 | @Override public Collection get(Object o) { |
166 | 160 | Collection value = map.get(o); |
172 | 166 | } |
173 | 167 | } |
174 | 168 | |
175 | protected static class MapMapCollectionWithDefault extends MapWrapper<String, Map<String, Collection>> { | |
169 | protected static class DelegatedMapMapWithDefault extends DelegatedMap<String, Map<String, Collection>> { | |
176 | 170 | protected HashMap<String, Map<String, Collection>> wrappers = new HashMap<>(); |
177 | 171 | |
178 | public MapMapCollectionWithDefault(Map<String, Map<String, Collection>> map) { super(map); } | |
172 | public DelegatedMapMapWithDefault(Map<String, Map<String, Collection>> map) { super(map); } | |
179 | 173 | |
180 | 174 | @Override public Map<String, Collection> get(Object o) { |
181 | 175 | Map<String, Collection> value = wrappers.get(o); |
184 | 178 | String key = o.toString(); |
185 | 179 | HashMap<String, Collection> m = new HashMap<>(); |
186 | 180 | map.put(key, m); |
187 | wrappers.put(key, value=new MapCollectionWithDefault(m)); | |
181 | wrappers.put(key, value=new DelegatedMapWithDefault(m)); | |
188 | 182 | } |
189 | 183 | |
190 | 184 | return value; |
17 | 17 | import java.net.URI; |
18 | 18 | import java.net.URISyntaxException; |
19 | 19 | import java.util.Collection; |
20 | import java.util.concurrent.Future; | |
20 | 21 | |
21 | 22 | public class UriUtil { |
22 | 23 | /* |
23 | 24 | * Convert inner entry URI to outer entry uri with a fragment. Example: |
24 | 25 | * file://codebase/a/b/c/D$E.class => file://codebase/a/b/c/D.class#typeDeclaration=D$E |
25 | 26 | */ |
26 | public static URI createURI(API api, Collection<Indexes> collectionOfIndexes, Container.Entry entry, String query, String fragment) { | |
27 | public static URI createURI(API api, Collection<Future<Indexes>> collectionOfFutureIndexes, Container.Entry entry, String query, String fragment) { | |
27 | 28 | TypeFactory typeFactory = TypeFactoryService.getInstance().get(entry); |
28 | 29 | |
29 | 30 | if (typeFactory != null) { |
31 | 32 | |
32 | 33 | if (type != null) { |
33 | 34 | URI uri = entry.getUri(); |
34 | String path = getOuterPath(collectionOfIndexes, entry, type); | |
35 | String path = getOuterPath(collectionOfFutureIndexes, entry, type); | |
35 | 36 | |
36 | 37 | try { |
37 | 38 | return new URI(uri.getScheme(), uri.getHost(), path, query, fragment); |
45 | 46 | } |
46 | 47 | |
47 | 48 | @SuppressWarnings("unchecked") |
48 | protected static String getOuterPath(Collection<Indexes> collectionOfIndexes, Container.Entry entry, Type type) { | |
49 | protected static String getOuterPath(Collection<Future<Indexes>> collectionOfFutureIndexes, Container.Entry entry, Type type) { | |
49 | 50 | String outerName = type.getOuterName(); |
50 | 51 | |
51 | 52 | if (outerName != null) { |
52 | for (Indexes indexes : collectionOfIndexes) { | |
53 | Collection<Container.Entry> outerEntries = indexes.getIndex("typeDeclarations").get(outerName); | |
53 | try { | |
54 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
55 | if (futureIndexes.isDone()) { | |
56 | Collection<Container.Entry> outerEntries = futureIndexes.get().getIndex("typeDeclarations").get(outerName); | |
54 | 57 | |
55 | if (outerEntries != null) { | |
56 | for (Container.Entry outerEntry : outerEntries) { | |
57 | if (outerEntry.getContainer() == entry.getContainer()) { | |
58 | return outerEntry.getUri().getPath(); | |
58 | if (outerEntries != null) { | |
59 | for (Container.Entry outerEntry : outerEntries) { | |
60 | if (outerEntry.getContainer() == entry.getContainer()) { | |
61 | return outerEntry.getUri().getPath(); | |
62 | } | |
63 | } | |
59 | 64 | } |
60 | 65 | } |
61 | 66 | } |
67 | } catch (Exception e) { | |
68 | assert ExceptionUtil.printStackTrace(e); | |
62 | 69 | } |
63 | 70 | } |
64 | 71 |
11 | 11 | import org.jd.gui.api.model.Indexes; |
12 | 12 | import org.jd.gui.api.model.TreeNodeData; |
13 | 13 | import org.jd.gui.api.model.Type; |
14 | import org.jd.gui.util.exception.ExceptionUtil; | |
14 | 15 | import org.jd.gui.util.function.TriConsumer; |
15 | 16 | import org.jd.gui.util.swing.SwingUtil; |
16 | 17 | import org.jd.gui.view.component.Tree; |
26 | 27 | import java.awt.event.*; |
27 | 28 | import java.util.*; |
28 | 29 | import java.util.List; |
30 | import java.util.concurrent.Future; | |
29 | 31 | |
30 | 32 | public class OpenTypeHierarchyView { |
31 | 33 | protected static final ImageIcon ROOT_CLASS_ICON = new ImageIcon(OpenTypeHierarchyView.class.getClassLoader().getResource("org/jd/gui/images/generate_class.png")); |
34 | 36 | protected static final TreeNodeComparator TREE_NODE_COMPARATOR = new TreeNodeComparator(); |
35 | 37 | |
36 | 38 | protected API api; |
37 | protected Collection<Indexes> collectionOfIndexes; | |
39 | protected Collection<Future<Indexes>> collectionOfFutureIndexes; | |
38 | 40 | |
39 | 41 | protected JDialog openTypeHierarchyDialog; |
40 | 42 | protected Tree openTypeHierarchyTree; |
140 | 142 | }); |
141 | 143 | } |
142 | 144 | |
143 | public void show(Collection<Indexes> collectionOfIndexes, Container.Entry entry, String typeName) { | |
144 | this.collectionOfIndexes = collectionOfIndexes; | |
145 | public void show(Collection<Future<Indexes>> collectionOfFutureIndexes, Container.Entry entry, String typeName) { | |
146 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
145 | 147 | SwingUtil.invokeLater(() -> { |
146 | 148 | updateTree(entry, typeName); |
147 | 149 | openTypeHierarchyDialog.setVisible(true); |
159 | 161 | SwingUtil.invokeLater(() -> openTypeHierarchyDialog.setCursor(Cursor.getDefaultCursor())); |
160 | 162 | } |
161 | 163 | |
162 | public void updateTree(Collection<Indexes> collectionOfIndexes) { | |
163 | this.collectionOfIndexes = collectionOfIndexes; | |
164 | public void updateTree(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
165 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
164 | 166 | TreeNode selectedTreeNode = (TreeNode)openTypeHierarchyTree.getLastSelectedPathComponent(); |
165 | 167 | |
166 | 168 | if (selectedTreeNode != null) { |
366 | 368 | protected List<String> getSubTypeNames(String typeName) { |
367 | 369 | ArrayList<String> result = new ArrayList<>(); |
368 | 370 | |
369 | for (Indexes indexes : collectionOfIndexes) { | |
370 | Map<String, Collection> subTypeNames = indexes.getIndex("subTypeNames"); | |
371 | if (subTypeNames != null) { | |
372 | Collection<String> collection = subTypeNames.get(typeName); | |
373 | if (collection != null) { | |
374 | for (String tn : collection) { | |
375 | if (tn != null) { | |
376 | result.add(tn); | |
371 | try { | |
372 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
373 | if (futureIndexes.isDone()) { | |
374 | Map<String, Collection> subTypeNames = futureIndexes.get().getIndex("subTypeNames"); | |
375 | if (subTypeNames != null) { | |
376 | Collection<String> collection = subTypeNames.get(typeName); | |
377 | if (collection != null) { | |
378 | for (String tn : collection) { | |
379 | if (tn != null) { | |
380 | result.add(tn); | |
381 | } | |
382 | } | |
377 | 383 | } |
378 | 384 | } |
379 | 385 | } |
380 | 386 | } |
387 | } catch (Exception e) { | |
388 | assert ExceptionUtil.printStackTrace(e); | |
381 | 389 | } |
382 | 390 | |
383 | 391 | return result; |
387 | 395 | protected List<Container.Entry> getEntries(String typeName) { |
388 | 396 | ArrayList<Container.Entry> result = new ArrayList<>(); |
389 | 397 | |
390 | for (Indexes indexes : collectionOfIndexes) { | |
391 | Map<String, Collection> typeDeclarations = indexes.getIndex("typeDeclarations"); | |
392 | if (typeDeclarations != null) { | |
393 | Collection<Container.Entry> collection = typeDeclarations.get(typeName); | |
394 | if (collection != null) { | |
395 | for (Container.Entry e : collection) { | |
396 | if (e != null) { | |
397 | result.add(e); | |
398 | try { | |
399 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
400 | if (futureIndexes.isDone()) { | |
401 | Map<String, Collection> typeDeclarations = futureIndexes.get().getIndex("typeDeclarations"); | |
402 | if (typeDeclarations != null) { | |
403 | Collection<Container.Entry> collection = typeDeclarations.get(typeName); | |
404 | if (collection != null) { | |
405 | for (Container.Entry e : collection) { | |
406 | if (e != null) { | |
407 | result.add(e); | |
408 | } | |
409 | } | |
398 | 410 | } |
399 | 411 | } |
400 | 412 | } |
401 | 413 | } |
414 | } catch (Exception e) { | |
415 | assert ExceptionUtil.printStackTrace(e); | |
402 | 416 | } |
403 | 417 | |
404 | 418 | return result; |
11 | 11 | import org.jd.gui.api.feature.TreeNodeExpandable; |
12 | 12 | import org.jd.gui.api.feature.UriGettable; |
13 | 13 | import org.jd.gui.api.model.Container; |
14 | import org.jd.gui.model.container.FilteredContainerWrapper; | |
14 | import org.jd.gui.model.container.DelegatingFilterContainer; | |
15 | 15 | import org.jd.gui.spi.TreeNodeFactory; |
16 | 16 | import org.jd.gui.util.function.TriConsumer; |
17 | 17 | import org.jd.gui.util.swing.SwingUtil; |
363 | 363 | } |
364 | 364 | |
365 | 365 | @SuppressWarnings("unchecked") |
366 | public void updateTree(Collection<FilteredContainerWrapper> containers, int matchingTypeCount) { | |
366 | public void updateTree(Collection<DelegatingFilterContainer> containers, int matchingTypeCount) { | |
367 | 367 | SwingUtil.invokeLater(() -> { |
368 | 368 | DefaultTreeModel model = (DefaultTreeModel)searchInConstantPoolsTree.getModel(); |
369 | 369 | T root = (T)model.getRoot(); |
375 | 375 | expanded.clear(); |
376 | 376 | |
377 | 377 | if (containers != null) { |
378 | ArrayList<FilteredContainerWrapper> list = new ArrayList<>(containers); | |
378 | ArrayList<DelegatingFilterContainer> list = new ArrayList<>(containers); | |
379 | 379 | |
380 | 380 | list.sort(CONTAINER_COMPARATOR); |
381 | 381 | |
382 | for (FilteredContainerWrapper container : list) { | |
382 | for (DelegatingFilterContainer container : list) { | |
383 | 383 | // Init uri set |
384 | 384 | accepted.addAll(container.getUris()); |
385 | 385 | // Populate tree |
11 | 11 | import org.jd.gui.api.feature.TreeNodeExpandable; |
12 | 12 | import org.jd.gui.api.feature.UriGettable; |
13 | 13 | import org.jd.gui.api.model.Container; |
14 | import org.jd.gui.model.container.FilteredContainerWrapper; | |
14 | import org.jd.gui.model.container.DelegatingFilterContainer; | |
15 | 15 | import org.jd.gui.spi.TreeNodeFactory; |
16 | 16 | import org.jd.gui.util.swing.SwingUtil; |
17 | 17 | import org.jd.gui.view.component.Tree; |
31 | 31 | import java.util.function.Consumer; |
32 | 32 | |
33 | 33 | public class SelectLocationView<T extends DefaultMutableTreeNode & ContainerEntryGettable & UriGettable> { |
34 | protected static final FilteredContainerWrapperComparator FILTERED_CONTAINER_WRAPPER_COMPARATOR = new FilteredContainerWrapperComparator(); | |
34 | protected static final DelegatingFilterContainerComparator DELEGATING_FILTER_CONTAINER_COMPARATOR = new DelegatingFilterContainerComparator(); | |
35 | 35 | |
36 | 36 | protected API api; |
37 | 37 | |
98 | 98 | } |
99 | 99 | |
100 | 100 | @SuppressWarnings("unchecked") |
101 | public void show(Point location, Collection<FilteredContainerWrapper> containers, int locationCount, Consumer<URI> selectedEntryCallback, Runnable closeCallback) { | |
101 | public void show(Point location, Collection<DelegatingFilterContainer> containers, int locationCount, Consumer<URI> selectedEntryCallback, Runnable closeCallback) { | |
102 | 102 | this.selectedEntryCallback = selectedEntryCallback; |
103 | 103 | this.closeCallback = closeCallback; |
104 | 104 | |
109 | 109 | // Reset tree nodes |
110 | 110 | root.removeAllChildren(); |
111 | 111 | |
112 | ArrayList<FilteredContainerWrapper> sortedContainers = new ArrayList<>(containers); | |
113 | sortedContainers.sort(FILTERED_CONTAINER_WRAPPER_COMPARATOR); | |
114 | ||
115 | for (FilteredContainerWrapper container : sortedContainers) { | |
112 | ArrayList<DelegatingFilterContainer> sortedContainers = new ArrayList<>(containers); | |
113 | sortedContainers.sort(DELEGATING_FILTER_CONTAINER_COMPARATOR); | |
114 | ||
115 | for (DelegatingFilterContainer container : sortedContainers) { | |
116 | 116 | Container.Entry parentEntry = container.getRoot().getParent(); |
117 | 117 | TreeNodeFactory factory = api.getTreeNodeFactory(parentEntry); |
118 | 118 | |
193 | 193 | } |
194 | 194 | } |
195 | 195 | |
196 | protected static class FilteredContainerWrapperComparator implements Comparator<FilteredContainerWrapper> { | |
196 | protected static class DelegatingFilterContainerComparator implements Comparator<DelegatingFilterContainer> { | |
197 | 197 | @Override |
198 | public int compare(FilteredContainerWrapper fcw1, FilteredContainerWrapper fcw2) { | |
198 | public int compare(DelegatingFilterContainer fcw1, DelegatingFilterContainer fcw2) { | |
199 | 199 | return fcw1.getRoot().getUri().compareTo(fcw2.getRoot().getUri()); |
200 | 200 | } |
201 | 201 | } |
79 | 79 | } |
80 | 80 | |
81 | 81 | public void addPage(String title, Icon icon, String tip, T page) { |
82 | // Update preferences | |
83 | if (page instanceof PreferencesChangeListener) { | |
84 | ((PreferencesChangeListener)page).preferencesChanged(preferences); | |
85 | } | |
86 | 82 | // Add a new tab |
87 | 83 | JLabel tabCloseButton = new JLabel(CLOSE_ICON); |
88 | 84 | tabCloseButton.setToolTipText("Close this panel"); |
119 | 119 | int hashCode = 1; |
120 | 120 | |
121 | 121 | while (enumeration.hasMoreElements()) { |
122 | hashCode *= 31; | |
123 | ||
122 | 124 | Object element = enumeration.nextElement(); |
123 | ||
124 | hashCode *= 31; | |
125 | 125 | |
126 | 126 | if (element != null) { |
127 | 127 | hashCode += element.hashCode(); |
171 | 171 | if ((page == null) && (baseNode instanceof PageCreator)) { |
172 | 172 | page = ((PageCreator)baseNode).createPage(api); |
173 | 173 | page.putClientProperty("node", baseNode); |
174 | page.putClientProperty("preferences-stamp", Integer.valueOf(api.getPreferences().hashCode())); | |
175 | page.putClientProperty("collectionOfIndexes-stamp", Integer.valueOf(api.getCollectionOfIndexes().hashCode())); | |
176 | 174 | |
177 | 175 | String path = baseUri.getPath(); |
178 | 176 | String label = path.substring(path.lastIndexOf('/')+1); |
+2
-2
11 | 11 | import org.jd.gui.api.feature.PageCreator; |
12 | 12 | import org.jd.gui.api.feature.UriGettable; |
13 | 13 | import org.jd.gui.api.model.Container; |
14 | import org.jd.gui.view.component.OneTypeReferenceByLinePage; | |
14 | import org.jd.gui.view.component.OneTypeReferencePerLinePage; | |
15 | 15 | import org.jd.gui.view.data.TreeNodeBean; |
16 | 16 | |
17 | 17 | import javax.swing.*; |
48 | 48 | @Override |
49 | 49 | @SuppressWarnings("unchecked") |
50 | 50 | public <T extends JComponent & UriGettable> T createPage(API api) { |
51 | return (T)new OneTypeReferenceByLinePage(api, entry); | |
51 | return (T)new OneTypeReferencePerLinePage(api, entry); | |
52 | 52 | } |
53 | 53 | } |
54 | 54 | } |
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.util.index; | |
8 | ||
9 | import org.jd.gui.api.model.Container; | |
10 | import org.jd.gui.api.model.Indexes; | |
11 | ||
12 | import java.util.ArrayList; | |
13 | import java.util.Collection; | |
14 | import java.util.List; | |
15 | import java.util.Map; | |
16 | ||
17 | public class IndexUtil { | |
18 | public static boolean containsInternalTypeName(Collection<Indexes> collectionOfIndexes, String internalTypeName) { | |
19 | for (Indexes indexes : collectionOfIndexes) { | |
20 | Map<String, Collection> index = indexes.getIndex("typeDeclarations"); | |
21 | if ((index != null) && (index.get(internalTypeName) != null)) { | |
22 | return true; | |
23 | } | |
24 | } | |
25 | ||
26 | return false; | |
27 | } | |
28 | ||
29 | @SuppressWarnings("unchecked") | |
30 | public static List<Container.Entry> grepInternalTypeName(Collection<Indexes> collectionOfIndexes, String internalTypeName) { | |
31 | ArrayList<Container.Entry> entries = new ArrayList<>(); | |
32 | ||
33 | for (Indexes indexes : collectionOfIndexes) { | |
34 | Map<String, Collection> index = indexes.getIndex("typeDeclarations"); | |
35 | if (index != null) { | |
36 | Collection<Container.Entry> collection = index.get(internalTypeName); | |
37 | if (collection != null) { | |
38 | entries.addAll(collection); | |
39 | } | |
40 | } | |
41 | } | |
42 | ||
43 | return entries; | |
44 | } | |
45 | } |
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.util.index; | |
8 | ||
9 | import org.jd.gui.api.model.Container; | |
10 | import org.jd.gui.api.model.Indexes; | |
11 | import org.jd.gui.util.exception.ExceptionUtil; | |
12 | ||
13 | import java.util.ArrayList; | |
14 | import java.util.Collection; | |
15 | import java.util.List; | |
16 | import java.util.Map; | |
17 | import java.util.concurrent.Future; | |
18 | ||
19 | public class IndexesUtil { | |
20 | public static boolean containsInternalTypeName(Collection<Future<Indexes>> collectionOfFutureIndexes, String internalTypeName) { | |
21 | try { | |
22 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
23 | if (futureIndexes.isDone()) { | |
24 | Map<String, Collection> index = futureIndexes.get().getIndex("typeDeclarations"); | |
25 | if ((index != null) && (index.get(internalTypeName) != null)) { | |
26 | return true; | |
27 | } | |
28 | } | |
29 | } | |
30 | } catch (Exception e) { | |
31 | assert ExceptionUtil.printStackTrace(e); | |
32 | } | |
33 | ||
34 | return false; | |
35 | } | |
36 | ||
37 | @SuppressWarnings("unchecked") | |
38 | public static List<Container.Entry> findInternalTypeName(Collection<Future<Indexes>> collectionOfFutureIndexes, String internalTypeName) { | |
39 | ArrayList<Container.Entry> entries = new ArrayList<>(); | |
40 | ||
41 | try { | |
42 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
43 | if (futureIndexes.isDone()) { | |
44 | Map<String, Collection> index = futureIndexes.get().getIndex("typeDeclarations"); | |
45 | if (index != null) { | |
46 | Collection<Container.Entry> collection = index.get(internalTypeName); | |
47 | if (collection != null) { | |
48 | entries.addAll(collection); | |
49 | } | |
50 | } | |
51 | } | |
52 | } | |
53 | } catch (Exception e) { | |
54 | assert ExceptionUtil.printStackTrace(e); | |
55 | } | |
56 | ||
57 | return entries; | |
58 | } | |
59 | } |
85 | 85 | // Decompile class file |
86 | 86 | DECOMPILER.decompile(configuration, loader, printer, entryInternalName); |
87 | 87 | setText(printer.getStringBuffer().toString()); |
88 | ||
89 | // Show hyperlinks | |
90 | indexesChanged(api.getCollectionOfIndexes()); | |
91 | 88 | } catch (Throwable t) { |
92 | 89 | assert ExceptionUtil.printStackTrace(t); |
93 | 90 | setText("// INTERNAL ERROR //"); |
92 | 92 | |
93 | 93 | @Override protected RSyntaxTextArea newSyntaxTextArea() { return new SourceSyntaxTextArea(); } |
94 | 94 | |
95 | public class SourceSyntaxTextArea extends RSyntaxTextArea { | |
96 | /** | |
97 | * @see HyperlinkPage.HyperlinkSyntaxTextArea#getUnderlineForToken(org.fife.ui.rsyntaxtextarea.Token) | |
98 | */ | |
99 | @Override | |
100 | public boolean getUnderlineForToken(Token t) { | |
101 | Map.Entry<Integer, HyperlinkData> entry = hyperlinks.floorEntry(t.getOffset()); | |
102 | if (entry != null) { | |
103 | HyperlinkData data = entry.getValue(); | |
104 | if ((data != null) && (t.getOffset() < data.endPosition) && (t.getOffset() >= data.startPosition) && isHyperlinkEnabled(data)) { | |
105 | return true; | |
106 | } | |
107 | } | |
108 | return super.getUnderlineForToken(t); | |
109 | } | |
110 | ||
95 | public class SourceSyntaxTextArea extends HyperlinkSyntaxTextArea { | |
111 | 96 | @Override protected RTextAreaUI createRTextAreaUI() { return new SourceSyntaxTextAreaUI(this); } |
112 | 97 | } |
113 | 98 |
13 | 13 | import org.jd.gui.api.model.Container; |
14 | 14 | import org.jd.gui.api.model.Indexes; |
15 | 15 | import org.jd.gui.util.exception.ExceptionUtil; |
16 | import org.jd.gui.util.index.IndexUtil; | |
16 | import org.jd.gui.util.index.IndexesUtil; | |
17 | 17 | import org.jd.gui.util.io.TextReader; |
18 | 18 | import org.jd.gui.util.xml.AbstractXmlPathFinder; |
19 | 19 | |
22 | 22 | import java.net.URISyntaxException; |
23 | 23 | import java.util.*; |
24 | 24 | import java.util.List; |
25 | import java.util.concurrent.Future; | |
25 | 26 | |
26 | 27 | public class EjbJarXmlFilePage extends TypeReferencePage implements UriGettable, IndexesChangeListener { |
27 | 28 | protected API api; |
28 | 29 | protected Container.Entry entry; |
29 | protected Collection<Indexes> collectionOfIndexes; | |
30 | protected Collection<Future<Indexes>> collectionOfFutureIndexes = Collections.emptyList(); | |
30 | 31 | |
31 | 32 | public EjbJarXmlFilePage(API api, Container.Entry entry) { |
32 | 33 | this.api = api; |
37 | 38 | new PathFinder().find(text); |
38 | 39 | // Display |
39 | 40 | setText(text); |
40 | // Show hyperlinks | |
41 | indexesChanged(api.getCollectionOfIndexes()); | |
42 | 41 | } |
43 | 42 | |
44 | 43 | public String getSyntaxStyle() { return SyntaxConstants.SYNTAX_STYLE_XML; } |
58 | 57 | |
59 | 58 | // Open link |
60 | 59 | String internalTypeName = data.internalTypeName; |
61 | List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, internalTypeName); | |
60 | List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
62 | 61 | String rootUri = entry.getContainer().getRoot().getUri().toString(); |
63 | 62 | ArrayList<Container.Entry> sameContainerEntries = new ArrayList<>(); |
64 | 63 | |
90 | 89 | } |
91 | 90 | |
92 | 91 | // --- IndexesChangeListener --- // |
93 | public void indexesChanged(Collection<Indexes> collectionOfIndexes) { | |
92 | public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
94 | 93 | // Update the list of containers |
95 | this.collectionOfIndexes = collectionOfIndexes; | |
94 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
96 | 95 | // Refresh links |
97 | 96 | boolean refresh = false; |
98 | 97 | |
99 | 98 | for (Map.Entry<Integer, HyperlinkData> entry : hyperlinks.entrySet()) { |
100 | 99 | TypeHyperlinkData entryData = (TypeHyperlinkData)entry.getValue(); |
101 | 100 | String internalTypeName = entryData.internalTypeName; |
102 | boolean enabled = IndexUtil.containsInternalTypeName(collectionOfIndexes, internalTypeName); | |
101 | boolean enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
103 | 102 | |
104 | 103 | if (entryData.enabled != enabled) { |
105 | 104 | entryData.enabled = enabled; |
100 | 100 | } |
101 | 101 | |
102 | 102 | public class HyperlinkSyntaxTextArea extends RSyntaxTextArea { |
103 | /** | |
104 | * @see HyperlinkPage.HyperlinkSyntaxTextArea#getUnderlineForToken(org.fife.ui.rsyntaxtextarea.Token) | |
105 | */ | |
106 | @Override | |
103 | 107 | public boolean getUnderlineForToken(Token t) { |
104 | 108 | Map.Entry<Integer, HyperlinkData> entry = hyperlinks.floorEntry(t.getOffset()); |
105 | 109 | if (entry != null) { |
40 | 40 | ANTLRJavaParser.parse(new ANTLRInputStream(text), referenceListener); |
41 | 41 | // Display |
42 | 42 | setText(text); |
43 | // Show hyperlinks | |
44 | indexesChanged(api.getCollectionOfIndexes()); | |
45 | 43 | } |
46 | 44 | |
47 | 45 | public String getSyntaxStyle() { return SyntaxConstants.SYNTAX_STYLE_JAVA; } |
228 | 226 | } |
229 | 227 | |
230 | 228 | public class ReferenceListener extends AbstractJavaListener { |
231 | ||
232 | 229 | protected StringBuilder sbTypeDeclaration = new StringBuilder(); |
233 | 230 | protected HashMap<String, TypePage.ReferenceData> referencesCache = new HashMap<>(); |
234 | 231 | protected String currentInternalTypeName; |
12 | 12 | import org.jd.gui.api.model.Container; |
13 | 13 | import org.jd.gui.api.model.Indexes; |
14 | 14 | import org.jd.gui.util.exception.ExceptionUtil; |
15 | import org.jd.gui.util.index.IndexUtil; | |
15 | import org.jd.gui.util.index.IndexesUtil; | |
16 | 16 | |
17 | 17 | import java.awt.*; |
18 | 18 | import java.net.URI; |
19 | 19 | import java.util.Collection; |
20 | import java.util.Collections; | |
20 | 21 | import java.util.List; |
21 | 22 | import java.util.Map; |
23 | import java.util.concurrent.Future; | |
22 | 24 | |
23 | 25 | public class LogPage extends HyperlinkPage implements UriGettable, IndexesChangeListener { |
24 | 26 | protected API api; |
25 | 27 | protected URI uri; |
26 | protected Collection<Indexes> collectionOfIndexes; | |
28 | protected Collection<Future<Indexes>> collectionOfFutureIndexes = Collections.emptyList(); | |
27 | 29 | |
28 | 30 | public LogPage(API api, URI uri, String content) { |
29 | 31 | this.api = api; |
41 | 43 | parseLine(content, index, content.length()); |
42 | 44 | // Display |
43 | 45 | setText(content); |
44 | // Show hyperlinks | |
45 | indexesChanged(api.getCollectionOfIndexes()); | |
46 | 46 | } |
47 | 47 | |
48 | 48 | protected void parseLine(String content, int index, int eol) { |
75 | 75 | int lastDotIndex = typeAndMethodNames.lastIndexOf('.'); |
76 | 76 | String methodName = typeAndMethodNames.substring(lastDotIndex + 1); |
77 | 77 | String internalTypeName = typeAndMethodNames.substring(0, lastDotIndex).replace('.', '/'); |
78 | List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, internalTypeName); | |
78 | List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
79 | 79 | int leftParenthesisIndex = hyperlinkData.endPosition + 1; |
80 | 80 | int rightParenthesisIndex = text.indexOf(')', leftParenthesisIndex); |
81 | 81 | String lineNumberOrNativeMethodFlag = text.substring(leftParenthesisIndex, rightParenthesisIndex); |
108 | 108 | } |
109 | 109 | |
110 | 110 | // --- IndexesChangeListener --- // |
111 | public void indexesChanged(Collection<Indexes> collectionOfIndexes) { | |
111 | public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
112 | 112 | // Update the list of containers |
113 | this.collectionOfIndexes = collectionOfIndexes; | |
113 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
114 | 114 | // Refresh links |
115 | 115 | boolean refresh = false; |
116 | 116 | String text = getText(); |
120 | 120 | String typeAndMethodNames = text.substring(entryData.startPosition, entryData.endPosition); |
121 | 121 | int lastDotIndex = typeAndMethodNames.lastIndexOf('.'); |
122 | 122 | String internalTypeName = typeAndMethodNames.substring(0, lastDotIndex).replace('.', '/'); |
123 | boolean enabled = IndexUtil.containsInternalTypeName(collectionOfIndexes, internalTypeName); | |
123 | boolean enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
124 | 124 | |
125 | 125 | if (entryData.enabled != enabled) { |
126 | 126 | entryData.enabled = enabled; |
12 | 12 | import org.jd.gui.api.model.Container; |
13 | 13 | import org.jd.gui.api.model.Indexes; |
14 | 14 | import org.jd.gui.util.exception.ExceptionUtil; |
15 | import org.jd.gui.util.index.IndexUtil; | |
15 | import org.jd.gui.util.index.IndexesUtil; | |
16 | 16 | import org.jd.gui.util.io.TextReader; |
17 | 17 | |
18 | 18 | import java.awt.*; |
19 | 19 | import java.net.URI; |
20 | 20 | import java.net.URISyntaxException; |
21 | import java.util.ArrayList; | |
22 | import java.util.Collection; | |
21 | import java.util.*; | |
23 | 22 | import java.util.List; |
24 | import java.util.Map; | |
23 | import java.util.concurrent.Future; | |
25 | 24 | |
26 | 25 | public class ManifestFilePage extends HyperlinkPage implements UriGettable, IndexesChangeListener { |
27 | 26 | protected API api; |
28 | 27 | protected Container.Entry entry; |
29 | protected Collection<Indexes> collectionOfIndexes; | |
28 | protected Collection<Future<Indexes>> collectionOfFutureIndexes = Collections.emptyList(); | |
30 | 29 | |
31 | 30 | public ManifestFilePage(API api, Container.Entry entry) { |
32 | 31 | this.api = api; |
59 | 58 | } |
60 | 59 | // Display |
61 | 60 | setText(text); |
62 | // Show hyperlinks | |
63 | indexesChanged(api.getCollectionOfIndexes()); | |
64 | 61 | } |
65 | 62 | |
66 | 63 | public int skipSeparators(String text, int index) { |
133 | 130 | String text = getText(); |
134 | 131 | String textLink = getValue(text, hyperlinkData.startPosition, hyperlinkData.endPosition); |
135 | 132 | String internalTypeName = textLink.replace('.', '/'); |
136 | List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, internalTypeName); | |
133 | List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
137 | 134 | String rootUri = entry.getContainer().getRoot().getUri().toString(); |
138 | 135 | ArrayList<Container.Entry> sameContainerEntries = new ArrayList<>(); |
139 | 136 | |
165 | 162 | } |
166 | 163 | |
167 | 164 | // --- IndexesChangeListener --- // |
168 | public void indexesChanged(Collection<Indexes> collectionOfIndexes) { | |
165 | public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
169 | 166 | // Update the list of containers |
170 | this.collectionOfIndexes = collectionOfIndexes; | |
167 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
171 | 168 | // Refresh links |
172 | 169 | boolean refresh = false; |
173 | 170 | String text = getText(); |
176 | 173 | ManifestHyperlinkData entryData = (ManifestHyperlinkData)entry.getValue(); |
177 | 174 | String textLink = getValue(text, entryData.startPosition, entryData.endPosition); |
178 | 175 | String internalTypeName = textLink.replace('.', '/'); |
179 | boolean enabled = IndexUtil.containsInternalTypeName(collectionOfIndexes, internalTypeName); | |
176 | boolean enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
180 | 177 | |
181 | 178 | if (entryData.enabled != enabled) { |
182 | 179 | entryData.enabled = enabled; |
191 | 188 | |
192 | 189 | public static String getValue(String text, int startPosition, int endPosition) { |
193 | 190 | return text |
194 | // Extract text of link | |
195 | .substring(startPosition, endPosition) | |
196 | // Convert multiline value | |
197 | .replace("\r\n ", "") | |
198 | .replace("\r ", "") | |
199 | .replace("\n ", ""); | |
191 | // Extract text of link | |
192 | .substring(startPosition, endPosition) | |
193 | // Convert multiline value | |
194 | .replace("\r\n ", "") | |
195 | .replace("\r ", "") | |
196 | .replace("\n ", ""); | |
200 | 197 | } |
201 | 198 | |
202 | 199 | public static class ManifestHyperlinkData extends HyperlinkData { |
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.view.component; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | import org.jd.gui.api.feature.IndexesChangeListener; | |
11 | import org.jd.gui.api.feature.UriGettable; | |
12 | import org.jd.gui.api.model.Container; | |
13 | import org.jd.gui.api.model.Indexes; | |
14 | import org.jd.gui.util.exception.ExceptionUtil; | |
15 | import org.jd.gui.util.index.IndexUtil; | |
16 | ||
17 | import java.awt.*; | |
18 | import java.io.BufferedReader; | |
19 | import java.io.IOException; | |
20 | import java.io.InputStreamReader; | |
21 | import java.net.URI; | |
22 | import java.net.URISyntaxException; | |
23 | import java.util.ArrayList; | |
24 | import java.util.Collection; | |
25 | import java.util.List; | |
26 | import java.util.Map; | |
27 | ||
28 | public class OneTypeReferenceByLinePage extends TypeReferencePage implements UriGettable, IndexesChangeListener { | |
29 | protected API api; | |
30 | protected Container.Entry entry; | |
31 | protected Collection<Indexes> collectionOfIndexes; | |
32 | ||
33 | public OneTypeReferenceByLinePage(API api, Container.Entry entry) { | |
34 | this.api = api; | |
35 | this.entry = entry; | |
36 | // Load content file & Create hyperlinks | |
37 | StringBuilder sb = new StringBuilder(); | |
38 | int offset = 0; | |
39 | ||
40 | try (BufferedReader br = new BufferedReader(new InputStreamReader(entry.getInputStream()))) { | |
41 | String line; | |
42 | ||
43 | while ((line = br.readLine()) != null) { | |
44 | String trim = line.trim(); | |
45 | ||
46 | if (trim.length() > 0) { | |
47 | int startIndex = offset + line.indexOf(trim); | |
48 | int endIndex = startIndex + trim.length(); | |
49 | String internalTypeName = trim.replace('.', '/'); | |
50 | ||
51 | addHyperlink(new TypeReferencePage.TypeHyperlinkData(startIndex, endIndex, internalTypeName)); | |
52 | } | |
53 | ||
54 | offset += line.length() + 1; | |
55 | sb.append(line).append('\n'); | |
56 | } | |
57 | } catch (IOException e) { | |
58 | assert ExceptionUtil.printStackTrace(e); | |
59 | } | |
60 | ||
61 | // Display | |
62 | setText(sb.toString()); | |
63 | // Show hyperlinks | |
64 | indexesChanged(api.getCollectionOfIndexes()); | |
65 | } | |
66 | ||
67 | protected boolean isHyperlinkEnabled(HyperlinkData hyperlinkData) { return ((TypeHyperlinkData)hyperlinkData).enabled; } | |
68 | ||
69 | protected void openHyperlink(int x, int y, HyperlinkData hyperlinkData) { | |
70 | TypeHyperlinkData data = (TypeHyperlinkData)hyperlinkData; | |
71 | ||
72 | if (data.enabled) { | |
73 | try { | |
74 | // Save current position in history | |
75 | Point location = textArea.getLocationOnScreen(); | |
76 | int offset = textArea.viewToModel(new Point(x-location.x, y-location.y)); | |
77 | URI uri = entry.getUri(); | |
78 | api.addURI(new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), "position=" + offset, null)); | |
79 | ||
80 | // Open link | |
81 | String internalTypeName = data.internalTypeName; | |
82 | List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, internalTypeName); | |
83 | String rootUri = entry.getContainer().getRoot().getUri().toString(); | |
84 | ArrayList<Container.Entry> sameContainerEntries = new ArrayList<>(); | |
85 | ||
86 | for (Container.Entry entry : entries) { | |
87 | if (entry.getUri().toString().startsWith(rootUri)) { | |
88 | sameContainerEntries.add(entry); | |
89 | } | |
90 | } | |
91 | ||
92 | if (sameContainerEntries.size() > 0) { | |
93 | api.openURI(x, y, sameContainerEntries, null, data.internalTypeName); | |
94 | } else if (entries.size() > 0) { | |
95 | api.openURI(x, y, entries, null, data.internalTypeName); | |
96 | } | |
97 | } catch (URISyntaxException e) { | |
98 | assert ExceptionUtil.printStackTrace(e); | |
99 | } | |
100 | } | |
101 | } | |
102 | ||
103 | // --- UriGettable --- // | |
104 | public URI getUri() { return entry.getUri(); } | |
105 | ||
106 | // --- ContentSavable --- // | |
107 | public String getFileName() { | |
108 | String path = entry.getPath(); | |
109 | int index = path.lastIndexOf('/'); | |
110 | return path.substring(index+1); | |
111 | } | |
112 | ||
113 | // --- IndexesChangeListener --- // | |
114 | public void indexesChanged(Collection<Indexes> collectionOfIndexes) { | |
115 | // Update the list of containers | |
116 | this.collectionOfIndexes = collectionOfIndexes; | |
117 | // Refresh links | |
118 | boolean refresh = false; | |
119 | ||
120 | for (Map.Entry<Integer, HyperlinkData> entry : hyperlinks.entrySet()) { | |
121 | TypeHyperlinkData entryData = (TypeHyperlinkData)entry.getValue(); | |
122 | String internalTypeName = entryData.internalTypeName; | |
123 | boolean enabled = IndexUtil.containsInternalTypeName(collectionOfIndexes, internalTypeName); | |
124 | ||
125 | if (entryData.enabled != enabled) { | |
126 | entryData.enabled = enabled; | |
127 | refresh = true; | |
128 | } | |
129 | } | |
130 | ||
131 | if (refresh) { | |
132 | textArea.repaint(); | |
133 | } | |
134 | } | |
135 | } |
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.view.component; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | import org.jd.gui.api.feature.IndexesChangeListener; | |
11 | import org.jd.gui.api.feature.UriGettable; | |
12 | import org.jd.gui.api.model.Container; | |
13 | import org.jd.gui.api.model.Indexes; | |
14 | import org.jd.gui.util.exception.ExceptionUtil; | |
15 | import org.jd.gui.util.index.IndexesUtil; | |
16 | ||
17 | import java.awt.*; | |
18 | import java.io.BufferedReader; | |
19 | import java.io.IOException; | |
20 | import java.io.InputStreamReader; | |
21 | import java.net.URI; | |
22 | import java.net.URISyntaxException; | |
23 | import java.util.*; | |
24 | import java.util.List; | |
25 | import java.util.concurrent.Future; | |
26 | ||
27 | public class OneTypeReferencePerLinePage extends TypeReferencePage implements UriGettable, IndexesChangeListener { | |
28 | protected API api; | |
29 | protected Container.Entry entry; | |
30 | protected Collection<Future<Indexes>> collectionOfFutureIndexes = Collections.emptyList(); | |
31 | ||
32 | public OneTypeReferencePerLinePage(API api, Container.Entry entry) { | |
33 | this.api = api; | |
34 | this.entry = entry; | |
35 | // Load content file & Create hyperlinks | |
36 | StringBuilder sb = new StringBuilder(); | |
37 | int offset = 0; | |
38 | ||
39 | try (BufferedReader br = new BufferedReader(new InputStreamReader(entry.getInputStream()))) { | |
40 | String line; | |
41 | ||
42 | while ((line = br.readLine()) != null) { | |
43 | String trim = line.trim(); | |
44 | ||
45 | if (trim.length() > 0) { | |
46 | int startIndex = offset + line.indexOf(trim); | |
47 | int endIndex = startIndex + trim.length(); | |
48 | String internalTypeName = trim.replace('.', '/'); | |
49 | ||
50 | addHyperlink(new TypeReferencePage.TypeHyperlinkData(startIndex, endIndex, internalTypeName)); | |
51 | } | |
52 | ||
53 | offset += line.length() + 1; | |
54 | sb.append(line).append('\n'); | |
55 | } | |
56 | } catch (IOException e) { | |
57 | assert ExceptionUtil.printStackTrace(e); | |
58 | } | |
59 | ||
60 | // Display | |
61 | setText(sb.toString()); | |
62 | } | |
63 | ||
64 | protected boolean isHyperlinkEnabled(HyperlinkData hyperlinkData) { return ((TypeHyperlinkData)hyperlinkData).enabled; } | |
65 | ||
66 | protected void openHyperlink(int x, int y, HyperlinkData hyperlinkData) { | |
67 | TypeHyperlinkData data = (TypeHyperlinkData)hyperlinkData; | |
68 | ||
69 | if (data.enabled) { | |
70 | try { | |
71 | // Save current position in history | |
72 | Point location = textArea.getLocationOnScreen(); | |
73 | int offset = textArea.viewToModel(new Point(x-location.x, y-location.y)); | |
74 | URI uri = entry.getUri(); | |
75 | api.addURI(new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), "position=" + offset, null)); | |
76 | ||
77 | // Open link | |
78 | String internalTypeName = data.internalTypeName; | |
79 | List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
80 | String rootUri = entry.getContainer().getRoot().getUri().toString(); | |
81 | ArrayList<Container.Entry> sameContainerEntries = new ArrayList<>(); | |
82 | ||
83 | for (Container.Entry entry : entries) { | |
84 | if (entry.getUri().toString().startsWith(rootUri)) { | |
85 | sameContainerEntries.add(entry); | |
86 | } | |
87 | } | |
88 | ||
89 | if (sameContainerEntries.size() > 0) { | |
90 | api.openURI(x, y, sameContainerEntries, null, data.internalTypeName); | |
91 | } else if (entries.size() > 0) { | |
92 | api.openURI(x, y, entries, null, data.internalTypeName); | |
93 | } | |
94 | } catch (URISyntaxException e) { | |
95 | assert ExceptionUtil.printStackTrace(e); | |
96 | } | |
97 | } | |
98 | } | |
99 | ||
100 | // --- UriGettable --- // | |
101 | public URI getUri() { return entry.getUri(); } | |
102 | ||
103 | // --- ContentSavable --- // | |
104 | public String getFileName() { | |
105 | String path = entry.getPath(); | |
106 | int index = path.lastIndexOf('/'); | |
107 | return path.substring(index+1); | |
108 | } | |
109 | ||
110 | // --- IndexesChangeListener --- // | |
111 | public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
112 | // Update the list of containers | |
113 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
114 | // Refresh links | |
115 | boolean refresh = false; | |
116 | ||
117 | for (Map.Entry<Integer, HyperlinkData> entry : hyperlinks.entrySet()) { | |
118 | TypeHyperlinkData entryData = (TypeHyperlinkData)entry.getValue(); | |
119 | String internalTypeName = entryData.internalTypeName; | |
120 | boolean enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
121 | ||
122 | if (entryData.enabled != enabled) { | |
123 | entryData.enabled = enabled; | |
124 | refresh = true; | |
125 | } | |
126 | } | |
127 | ||
128 | if (refresh) { | |
129 | textArea.repaint(); | |
130 | } | |
131 | } | |
132 | } |
16 | 16 | import org.jd.gui.api.model.Indexes; |
17 | 17 | import org.jd.gui.api.model.Type; |
18 | 18 | import org.jd.gui.util.exception.ExceptionUtil; |
19 | import org.jd.gui.util.index.IndexUtil; | |
19 | import org.jd.gui.util.index.IndexesUtil; | |
20 | 20 | import org.jd.gui.util.matcher.DescriptorMatcher; |
21 | 21 | |
22 | 22 | import java.awt.*; |
24 | 24 | import java.net.URISyntaxException; |
25 | 25 | import java.util.*; |
26 | 26 | import java.util.List; |
27 | import java.util.concurrent.Future; | |
27 | 28 | import java.util.function.BiFunction; |
28 | 29 | import java.util.regex.Matcher; |
29 | 30 | import java.util.regex.Pattern; |
31 | 32 | public abstract class TypePage extends CustomLineNumbersPage implements UriGettable, UriOpenable, IndexesChangeListener, FocusedTypeGettable { |
32 | 33 | protected API api; |
33 | 34 | protected Container.Entry entry; |
34 | protected Collection<Indexes> collectionOfIndexes; | |
35 | protected Collection<Future<Indexes>> collectionOfFutureIndexes = Collections.emptyList(); | |
35 | 36 | |
36 | 37 | protected HashMap<String, DeclarationData> declarations = new HashMap<>(); |
37 | 38 | protected TreeMap<Integer, DeclarationData> typeDeclarations = new TreeMap<>(); |
65 | 66 | // Open link |
66 | 67 | ReferenceData reference = hyperlinkReferenceData.reference; |
67 | 68 | String typeName = reference.typeName; |
68 | List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, typeName); | |
69 | List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, typeName); | |
69 | 70 | String fragment = typeName; |
70 | 71 | |
71 | 72 | if (reference.name != null) { |
331 | 332 | |
332 | 333 | // --- IndexesChangeListener --- // |
333 | 334 | @Override |
334 | public void indexesChanged(Collection<Indexes> collectionOfIndexes) { | |
335 | public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
335 | 336 | // Update the list of containers |
336 | this.collectionOfIndexes = collectionOfIndexes; | |
337 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
337 | 338 | // Refresh links |
338 | 339 | boolean refresh = false; |
339 | 340 | |
359 | 360 | } |
360 | 361 | } else { |
361 | 362 | enabled = false; |
362 | for (Indexes indexes : collectionOfIndexes) { | |
363 | Map<String, Collection> index = indexes.getIndex("typeDeclarations"); | |
364 | if ((index != null) && (index.get(typeName) != null)) { | |
365 | enabled = true; | |
366 | break; | |
367 | } | |
363 | ||
364 | try { | |
365 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
366 | if (futureIndexes.isDone()) { | |
367 | Map<String, Collection> index = futureIndexes.get().getIndex("typeDeclarations"); | |
368 | if ((index != null) && (index.get(typeName) != null)) { | |
369 | enabled = true; | |
370 | break; | |
371 | } | |
372 | } | |
373 | } | |
374 | } catch (Exception e) { | |
375 | assert ExceptionUtil.printStackTrace(e); | |
368 | 376 | } |
369 | 377 | } |
370 | 378 | |
383 | 391 | protected String searchTypeHavingMember(String typeName, String name, String descriptor, Container.Entry entry) { |
384 | 392 | ArrayList<Container.Entry> entries = new ArrayList<>(); |
385 | 393 | |
386 | for (Indexes indexes : collectionOfIndexes) { | |
387 | Map<String, Collection> index = indexes.getIndex("typeDeclarations"); | |
388 | if (index != null) { | |
389 | Collection<Container.Entry> collection = index.get(typeName); | |
390 | if (collection != null) { | |
391 | entries.addAll(collection); | |
392 | } | |
393 | } | |
394 | try { | |
395 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
396 | if (futureIndexes.isDone()) { | |
397 | Map<String, Collection> index = futureIndexes.get().getIndex("typeDeclarations"); | |
398 | if (index != null) { | |
399 | Collection<Container.Entry> collection = index.get(typeName); | |
400 | if (collection != null) { | |
401 | entries.addAll(collection); | |
402 | } | |
403 | } | |
404 | } | |
405 | } | |
406 | } catch (Exception e) { | |
407 | assert ExceptionUtil.printStackTrace(e); | |
394 | 408 | } |
395 | 409 | |
396 | 410 | String rootUri = entry.getContainer().getRoot().getUri().toString(); |
13 | 13 | import org.jd.gui.api.model.Container; |
14 | 14 | import org.jd.gui.api.model.Indexes; |
15 | 15 | import org.jd.gui.util.exception.ExceptionUtil; |
16 | import org.jd.gui.util.index.IndexUtil; | |
16 | import org.jd.gui.util.index.IndexesUtil; | |
17 | 17 | import org.jd.gui.util.io.TextReader; |
18 | 18 | import org.jd.gui.util.xml.AbstractXmlPathFinder; |
19 | 19 | |
22 | 22 | import java.net.URISyntaxException; |
23 | 23 | import java.util.*; |
24 | 24 | import java.util.List; |
25 | import java.util.concurrent.Future; | |
25 | 26 | |
26 | 27 | public class WebXmlFilePage extends TypeReferencePage implements UriGettable, IndexesChangeListener { |
27 | 28 | protected API api; |
28 | 29 | protected Container.Entry entry; |
29 | protected Collection<Indexes> collectionOfIndexes; | |
30 | protected Collection<Future<Indexes>> collectionOfFutureIndexes; | |
30 | 31 | |
31 | 32 | public WebXmlFilePage(API api, Container.Entry entry) { |
32 | 33 | this.api = api; |
37 | 38 | new PathFinder().find(text); |
38 | 39 | // Display |
39 | 40 | setText(text); |
40 | // Show hyperlinks | |
41 | indexesChanged(api.getCollectionOfIndexes()); | |
42 | 41 | } |
43 | 42 | |
44 | 43 | public String getSyntaxStyle() { return SyntaxConstants.SYNTAX_STYLE_XML; } |
66 | 65 | } |
67 | 66 | } else { |
68 | 67 | String internalTypeName = data.internalTypeName; |
69 | List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, internalTypeName); | |
68 | List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
70 | 69 | String rootUri = entry.getContainer().getRoot().getUri().toString(); |
71 | 70 | ArrayList<Container.Entry> sameContainerEntries = new ArrayList<>(); |
72 | 71 | |
129 | 128 | } |
130 | 129 | |
131 | 130 | // --- IndexesChangeListener --- // |
132 | public void indexesChanged(Collection<Indexes> collectionOfIndexes) { | |
131 | public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
133 | 132 | // Update the list of containers |
134 | this.collectionOfIndexes = collectionOfIndexes; | |
133 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
135 | 134 | // Refresh links |
136 | 135 | boolean refresh = false; |
137 | 136 | |
144 | 143 | enabled = searchEntry(this.entry.getContainer().getRoot(), d.path) != null; |
145 | 144 | } else { |
146 | 145 | String internalTypeName = data.internalTypeName; |
147 | enabled = IndexUtil.containsInternalTypeName(collectionOfIndexes, internalTypeName); | |
146 | enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
148 | 147 | } |
149 | 148 | |
150 | 149 | if (data.enabled != enabled) { |
170 | 169 | } |
171 | 170 | |
172 | 171 | protected static List<String> typeHyperlinkPaths = Arrays.asList( |
173 | "web-app/filter/filter-class", | |
174 | "web-app/listener/listener-class", | |
175 | "web-app/servlet/servlet-class"); | |
172 | "web-app/filter/filter-class", | |
173 | "web-app/listener/listener-class", | |
174 | "web-app/servlet/servlet-class"); | |
176 | 175 | |
177 | 176 | protected static List<String> pathHyperlinkPaths = Arrays.asList( |
178 | "web-app/jsp-config/taglib/taglib-location", | |
179 | "web-app/welcome-file-list/welcome-file", | |
180 | "web-app/login-config/form-login-config/form-login-page", | |
181 | "web-app/login-config/form-login-config/form-error-page", | |
182 | "web-app/jsp-config/jsp-property-group/include-prelude", | |
183 | "web-app/jsp-config/jsp-property-group/include-coda"); | |
177 | "web-app/jsp-config/taglib/taglib-location", | |
178 | "web-app/welcome-file-list/welcome-file", | |
179 | "web-app/login-config/form-login-config/form-login-page", | |
180 | "web-app/login-config/form-login-config/form-error-page", | |
181 | "web-app/jsp-config/jsp-property-group/include-prelude", | |
182 | "web-app/jsp-config/jsp-property-group/include-coda"); | |
184 | 183 | |
185 | 184 | protected static List<String> hyperlinkPaths = new ArrayList<>(typeHyperlinkPaths.size() + pathHyperlinkPaths.size()); |
186 | 185 |
13 | 13 | import org.jd.gui.api.model.Container; |
14 | 14 | import org.jd.gui.api.model.Indexes; |
15 | 15 | import org.jd.gui.util.exception.ExceptionUtil; |
16 | import org.jd.gui.util.index.IndexUtil; | |
16 | import org.jd.gui.util.index.IndexesUtil; | |
17 | 17 | import org.jd.gui.util.io.TextReader; |
18 | 18 | |
19 | 19 | import java.awt.*; |
23 | 23 | import java.util.Collection; |
24 | 24 | import java.util.List; |
25 | 25 | import java.util.Map; |
26 | import java.util.concurrent.Future; | |
26 | 27 | import java.util.regex.Matcher; |
27 | 28 | import java.util.regex.Pattern; |
28 | 29 | |
29 | 30 | public class XmlFilePage extends TypeReferencePage implements UriGettable, IndexesChangeListener { |
30 | 31 | protected API api; |
31 | 32 | protected Container.Entry entry; |
32 | protected Collection<Indexes> collectionOfIndexes; | |
33 | protected Collection<Future<Indexes>> collectionOfFutureIndexes; | |
33 | 34 | |
34 | 35 | public XmlFilePage(API api, Container.Entry entry) { |
35 | 36 | this.api = api; |
54 | 55 | } |
55 | 56 | // Display |
56 | 57 | setText(text); |
57 | // Show hyperlinks | |
58 | indexesChanged(api.getCollectionOfIndexes()); | |
59 | 58 | } |
60 | 59 | |
61 | 60 | public String getSyntaxStyle() { return SyntaxConstants.SYNTAX_STYLE_XML; } |
75 | 74 | |
76 | 75 | // Open link |
77 | 76 | String internalTypeName = data.internalTypeName; |
78 | List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, internalTypeName); | |
77 | List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
79 | 78 | String rootUri = entry.getContainer().getRoot().getUri().toString(); |
80 | 79 | ArrayList<Container.Entry> sameContainerEntries = new ArrayList<>(); |
81 | 80 | |
107 | 106 | } |
108 | 107 | |
109 | 108 | // --- IndexesChangeListener --- // |
110 | public void indexesChanged(Collection<Indexes> collectionOfIndexes) { | |
109 | public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
111 | 110 | // Update the list of containers |
112 | this.collectionOfIndexes = collectionOfIndexes; | |
111 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
113 | 112 | // Refresh links |
114 | 113 | boolean refresh = false; |
115 | 114 | |
116 | 115 | for (Map.Entry<Integer, HyperlinkData> entry : hyperlinks.entrySet()) { |
117 | 116 | TypeHyperlinkData data = (TypeHyperlinkData)entry.getValue(); |
118 | 117 | String internalTypeName = data.internalTypeName; |
119 | boolean enabled = IndexUtil.containsInternalTypeName(collectionOfIndexes, internalTypeName); | |
118 | boolean enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName); | |
120 | 119 | |
121 | 120 | if (data.enabled != enabled) { |
122 | 121 | data.enabled = enabled; |