Codebase list jd-gui / db81a9f
Improve background indexing emmanue1 5 years ago
32 changed file(s) with 676 addition(s) and 651 deletion(s). Raw diff Collapse all Expand all
1717 import java.nio.file.Path;
1818 import java.util.Collection;
1919 import java.util.Map;
20 import java.util.concurrent.Future;
2021
2122 public interface API {
2223 boolean openURI(URI uri);
4748
4849 Map<String, String> getPreferences();
4950
50 Collection<Indexes> getCollectionOfIndexes();
51 Collection<Future<Indexes>> getCollectionOfFutureIndexes();
5152 }
99 import org.jd.gui.api.model.Indexes;
1010
1111 import java.util.Collection;
12 import java.util.concurrent.Future;
1213
1314 public interface IndexesChangeListener {
14 void indexesChanged(Collection<Indexes> collectionOfIndexes);
15 void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes);
1516 }
6363 * </ul>
6464 */
6565 public interface Indexes {
66 void waitIndexers();
67
6866 Map<String, Collection> getIndex(String name);
6967 }
6666
6767 protected History history = new History();
6868 protected JComponent currentPage = null;
69 protected ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
69 protected ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
7070 protected ArrayList<IndexesChangeListener> containerChangeListeners = new ArrayList<>();
7171
7272 @SuppressWarnings("unchecked")
110110 file -> openFile((File)file));
111111 });
112112 }
113
113
114114 // --- Show GUI --- //
115115 @SuppressWarnings("unchecked")
116116 public void show(List<File> files) {
131131 IndexerService.getInstance();
132132 TreeNodeFactoryService.getInstance();
133133 TypeFactoryService.getInstance();
134 PasteHandlerService.getInstance();
135 PreferencesPanelService.getInstance();
136 ContextualActionsFactoryService.getInstance();
137134
138135 SwingUtil.invokeLater(() -> {
139136 // Populate recent files menu
158155 new JLayer();
159156 });
160157 }, 400, TimeUnit.MILLISECONDS);
158
159 PasteHandlerService.getInstance();
160 PreferencesPanelService.getInstance();
161 ContextualActionsFactoryService.getInstance();
162 SourceSaverService.getInstance();
161163 }
162164
163165 // --- Actions --- //
311313 }
312314
313315 protected void onOpenType() {
314 openTypeController.show(getCollectionOfIndexes(), uri -> openURI(uri));
316 openTypeController.show(getCollectionOfFutureIndexes(), uri -> openURI(uri));
315317 }
316318
317319 protected void onOpenTypeHierarchy() {
318320 if (currentPage instanceof FocusedTypeGettable) {
319321 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));
321323 }
322324 }
323325
329331 }
330332
331333 protected void onSearch() {
332 searchInConstantPoolsController.show(getCollectionOfIndexes(), uri -> openURI(uri));
334 searchInConstantPoolsController.show(getCollectionOfFutureIndexes(), uri -> openURI(uri));
333335 }
334336
335337 protected void onFindPrevious() {
379381
380382 protected void onCurrentPageChanged(JComponent page) {
381383 currentPage = page;
384 checkPreferencesChange(page);
382385 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 }
397386 }
398387
399388 protected void checkPreferencesChange(JComponent page) {
400389 if (page instanceof PreferencesChangeListener) {
401390 Map<String, String> preferences = configuration.getPreferences();
402391 Integer currentHashcode = Integer.valueOf(preferences.hashCode());
403 Integer lastHashcode = (Integer)page.getClientProperty("preferences-stamp");
392 Integer lastHashcode = (Integer)page.getClientProperty("preferences-hashCode");
404393
405394 if (!currentHashcode.equals(lastHashcode)) {
406395 ((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);
408410 }
409411 }
410412 }
515517 protected void panelClosed() {
516518 SwingUtil.invokeLater(() -> {
517519 // Fire 'indexesChanged' event
518 Collection<Indexes> collectionOfIndexes = getCollectionOfIndexes();
520 Collection<Future<Indexes>> collectionOfFutureIndexes = getCollectionOfFutureIndexes();
519521 for (IndexesChangeListener listener : containerChangeListeners) {
520 listener.indexesChanged(collectionOfIndexes);
522 listener.indexesChanged(collectionOfFutureIndexes);
521523 }
522524 if (currentPage instanceof IndexesChangeListener) {
523 ((IndexesChangeListener)currentPage).indexesChanged(collectionOfIndexes);
525 ((IndexesChangeListener)currentPage).indexesChanged(collectionOfFutureIndexes);
524526 }
525527 });
526528 }
555557 if (entries.size() == 1) {
556558 // Open the single entry uri
557559 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));
559561 } else {
560562 // Multiple entries -> Open a "Select location" popup
561 Collection<Indexes> collectionOfIndexes = getCollectionOfIndexes();
563 Collection<Future<Indexes>> collectionOfFutureIndexes = getCollectionOfFutureIndexes();
562564 selectLocationController.show(
563565 new Point(x+(16+2), y+2),
564566 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
567569 return true;
568570 }
569571 }
585587 mainView.addMainPanel(title, icon, tip, component);
586588
587589 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);
595598 }
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);
603601 }
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;
618605 });
619 }
620
621 checkIndexesChange(currentPage);
606
607 component.putClientProperty("indexes", futureIndexes);
608 }
622609 }
623610
624611 @Override public Collection<Action> getContextualActions(Container.Entry entry, String fragment) { return ContextualActionsFactoryService.getInstance().get(this, entry, fragment); }
641628
642629 @Override public Map<String, String> getPreferences() { return configuration.getPreferences(); }
643630
631 @Override
644632 @SuppressWarnings("unchecked")
645 public Collection<Indexes> getCollectionOfIndexes() {
633 public Collection<Future<Indexes>> getCollectionOfFutureIndexes() {
646634 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 };
648655
649656 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);
654660 }
655661 }
656662
1010 import org.jd.gui.api.feature.IndexesChangeListener;
1111 import org.jd.gui.api.model.Container;
1212 import org.jd.gui.api.model.Indexes;
13 import org.jd.gui.util.exception.ExceptionUtil;
1314 import org.jd.gui.util.net.UriUtil;
1415 import org.jd.gui.view.OpenTypeView;
1516
1718 import java.awt.*;
1819 import java.net.URI;
1920 import java.util.*;
21 import java.util.concurrent.Future;
2022 import java.util.concurrent.ScheduledExecutorService;
2123 import java.util.function.Consumer;
2224 import java.util.regex.Pattern;
2628
2729 protected API api;
2830 protected ScheduledExecutorService executor;
29 protected Collection<Indexes> collectionOfIndexes;
31 protected Collection<Future<Indexes>> collectionOfFutureIndexes;
3032 protected Consumer<URI> openCallback;
3133
3234 protected JFrame mainFrame;
5254 };
5355 }
5456
55 public void show(Collection<Indexes> collectionOfIndexes, Consumer<URI> openCallback) {
57 public void show(Collection<Future<Indexes>> collectionOfFutureIndexes, Consumer<URI> openCallback) {
5658 // Init attributes
57 this.collectionOfIndexes = collectionOfIndexes;
59 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
5860 this.openCallback = openCallback;
5961 // Refresh view
60 long hashCode = collectionOfIndexes.hashCode();
62 long hashCode = collectionOfFutureIndexes.hashCode();
6163 if (hashCode != indexesHashCode) {
6264 // List of indexes has changed -> Refresh result list
6365 updateList(openTypeView.getPattern());
7981 // Waiting the end of indexation...
8082 openTypeView.showWaitCursor();
8183
82 for (Indexes indexes : collectionOfIndexes) {
83 indexes.waitIndexers();
84 }
85
8684 Pattern regExpPattern = createRegExpPattern(pattern);
8785 Map<String, Collection<Container.Entry>> result = new HashMap<>();
8886
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 }
112103 } 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 }
120135 }
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());
133136 }
134137 }
135138 }
139 } catch (Exception e) {
140 assert ExceptionUtil.printStackTrace(e);
136141 }
137142
138143 SwingUtilities.invokeLater(() -> {
250255 protected void onTypeSelected(Point leftBottom, Collection<Container.Entry> entries, String typeName) {
251256 if (entries.size() == 1) {
252257 // 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));
254259 } else {
255260 // Multiple entries -> Open a "Select location" popup
256261 selectLocationController.show(
257262 new Point(leftBottom.x+(16+2), leftBottom.y+2),
258263 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
261266 }
262267 }
263268
264269 // --- IndexesChangeListener --- //
265 public void indexesChanged(Collection<Indexes> collectionOfIndexes) {
270 public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) {
266271 if (openTypeView.isVisible()) {
267272 // Update the list of containers
268 this.collectionOfIndexes = collectionOfIndexes;
273 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
269274 // And refresh
270275 updateList(openTypeView.getPattern());
271276 }
1717 import java.awt.*;
1818 import java.net.URI;
1919 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.concurrent.Future;
2022 import java.util.concurrent.ScheduledExecutorService;
2123 import java.util.function.Consumer;
2224
2830 protected OpenTypeHierarchyView openTypeHierarchyView;
2931 protected SelectLocationController selectLocationController;
3032
31 protected Collection<Indexes> collectionOfIndexes;
33 protected Collection<Future<Indexes>> collectionOfFutureIndexes;
3234 protected Consumer<URI> openCallback;
3335
3436 public OpenTypeHierarchyController(API api, ScheduledExecutorService executor, JFrame mainFrame) {
4042 selectLocationController = new SelectLocationController(api, mainFrame);
4143 }
4244
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) {
4446 // Init attributes
45 this.collectionOfIndexes = collectionOfIndexes;
47 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
4648 this.openCallback = openCallback;
4749 executor.execute(() -> {
4850 // Waiting the end of indexation...
4951 openTypeHierarchyView.showWaitCursor();
50 for (Indexes indexes : collectionOfIndexes) {
51 indexes.waitIndexers();
52 }
5352 SwingUtilities.invokeLater(() -> {
5453 openTypeHierarchyView.hideWaitCursor();
5554 // Show
56 openTypeHierarchyView.show(collectionOfIndexes, entry, typeName);
55 openTypeHierarchyView.show(collectionOfFutureIndexes, entry, typeName);
5756 });
5857 });
5958 }
6160 protected void onTypeSelected(Point leftBottom, Collection<Container.Entry> entries, String typeName) {
6261 if (entries.size() == 1) {
6362 // 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));
6564 } else {
6665 // Multiple entries -> Open a "Select location" popup
6766 selectLocationController.show(
6867 new Point(leftBottom.x+(16+2), leftBottom.y+2),
6968 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
7170 () -> openTypeHierarchyView.focus()); // popup closeClosure
7271 }
7372 }
7473
7574 // --- IndexesChangeListener --- //
76 public void indexesChanged(Collection<Indexes> collectionOfIndexes) {
75 public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) {
7776 if (openTypeHierarchyView.isVisible()) {
7877 // Update the list of containers
79 this.collectionOfIndexes = collectionOfIndexes;
78 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
8079 // And refresh
81 openTypeHierarchyView.updateTree(collectionOfIndexes);
80 openTypeHierarchyView.updateTree(collectionOfFutureIndexes);
8281 }
8382 }
8483 }
1111 import org.jd.gui.api.model.Container;
1212 import org.jd.gui.api.model.Indexes;
1313 import org.jd.gui.api.model.Type;
14 import org.jd.gui.model.container.FilteredContainerWrapper;
14 import org.jd.gui.model.container.DelegatingFilterContainer;
1515 import org.jd.gui.service.type.TypeFactoryService;
1616 import org.jd.gui.spi.TypeFactory;
1717 import org.jd.gui.util.exception.ExceptionUtil;
2222 import java.net.URI;
2323 import java.net.URISyntaxException;
2424 import java.util.*;
25 import java.util.concurrent.Future;
2526 import java.util.concurrent.ScheduledExecutorService;
2627 import java.util.function.BiConsumer;
2728 import java.util.function.BiFunction;
3738 protected JFrame mainFrame;
3839 protected SearchInConstantPoolsView searchInConstantPoolsView;
3940 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;
4243 protected Consumer<URI> openCallback;
4344 protected long indexesHashCode = 0L;
4445
6667 };
6768 }
6869
69 public void show(Collection<Indexes> collectionOfIndexes, Consumer<URI> openCallback) {
70 public void show(Collection<Future<Indexes>> collectionOfFutureIndexes, Consumer<URI> openCallback) {
7071 // Init attributes
71 this.collectionOfIndexes = collectionOfIndexes;
72 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
7273 this.openCallback = openCallback;
7374 // Refresh view
74 long hashCode = collectionOfIndexes.hashCode();
75 long hashCode = collectionOfFutureIndexes.hashCode();
7576 if (hashCode != indexesHashCode) {
7677 // List of indexes has changed
7778 updateTree(searchInConstantPoolsView.getPattern(), searchInConstantPoolsView.getFlags());
8384
8485 @SuppressWarnings("unchecked")
8586 protected void updateTree(String pattern, int flags) {
86 filteredContainerWrappers.clear();
87 delegatingFilterContainers.clear();
8788
8889 executor.execute(() -> {
90 // Waiting the end of indexation...
8991 searchInConstantPoolsView.showWaitCursor();
9092
9193 int matchingTypeCount = 0;
9294 int patternLength = pattern.length();
9395
9496 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 }
113123 }
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));
122124 }
125 } catch (Exception e) {
126 assert ExceptionUtil.printStackTrace(e);
123127 }
124128 }
125129
126130 final int count = matchingTypeCount;
127131
128132 searchInConstantPoolsView.hideWaitCursor();
129 searchInConstantPoolsView.updateTree(filteredContainerWrappers, count);
133 searchInConstantPoolsView.updateTree(delegatingFilterContainers, count);
130134 });
131135 }
132136
401405 // Open the single entry uri
402406 Container.Entry entry = null;
403407
404 for (FilteredContainerWrapper container : filteredContainerWrappers) {
408 for (DelegatingFilterContainer container : delegatingFilterContainers) {
405409 entry = container.getEntry(uri);
406410 if (entry != null)
407411 break;
436440 // sbPattern.append(type.name)
437441 //
438442 // def query = sbPattern.toString()
439 // def outerPath = UriUtil.getOuterPath(collectionOfIndexes, entry, type)
443 // def outerPath = UriUtil.getOuterPath(collectionOfFutureIndexes, entry, type)
440444 //
441445 // openClosure(new URI(entry.uri.scheme, entry.uri.host, outerPath, query, null))
442446 // } else {
453457 }
454458
455459 // --- IndexesChangeListener --- //
456 public void indexesChanged(Collection<Indexes> collectionOfIndexes) {
460 public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) {
457461 if (searchInConstantPoolsView.isVisible()) {
458462 // Update the list of containers
459 this.collectionOfIndexes = collectionOfIndexes;
463 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
460464 // And refresh
461465 updateTree(searchInConstantPoolsView.getPattern(), searchInConstantPoolsView.getFlags());
462466 }
99 import org.jd.gui.api.API;
1010 import org.jd.gui.api.model.Container;
1111 import org.jd.gui.api.model.Type;
12 import org.jd.gui.model.container.FilteredContainerWrapper;
12 import org.jd.gui.model.container.DelegatingFilterContainer;
1313 import org.jd.gui.service.type.TypeFactoryService;
1414 import org.jd.gui.spi.TypeFactory;
1515 import org.jd.gui.view.SelectLocationView;
5959 list.add(entry);
6060 }
6161
62 HashSet<FilteredContainerWrapper> filteredContainerWrappers = new HashSet<>();
62 HashSet<DelegatingFilterContainer> delegatingFilterContainers = new HashSet<>();
6363
6464 for (Map.Entry<Container, ArrayList<Container.Entry>> mapEntry : map.entrySet()) {
6565 Container container = mapEntry.getKey();
6666 // Create a filtered container
6767 // 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())));
6969 }
7070
71 Consumer<URI> selectedEntryCallback = uri -> onLocationSelected(filteredContainerWrappers, uri, selectedLocationCallback);
71 Consumer<URI> selectedEntryCallback = uri -> onLocationSelected(delegatingFilterContainers, uri, selectedLocationCallback);
7272
73 selectLocationView.show(location, filteredContainerWrappers, entries.size(), selectedEntryCallback, closeCallback);
73 selectLocationView.show(location, delegatingFilterContainers, entries.size(), selectedEntryCallback, closeCallback);
7474 }
7575
7676 protected Collection<Container.Entry> getOuterEntries(Collection<Container.Entry> entries) {
152152 return result;
153153 }
154154
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) {
156156 // Open the single entry uri
157157 Container.Entry entry = null;
158158
159 for (FilteredContainerWrapper container : filteredContainerWrappers) {
159 for (DelegatingFilterContainer container : delegatingFilterContainers) {
160160 entry = container.getEntry(uri);
161161 if (entry != null) {
162162 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
-117
app/src/main/java/org/jd/gui/model/container/FilteredContainerWrapper.java less more
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 }
6666 @Override
6767 public Indexes index(API api) {
6868 HashMap<String, Map<String, Collection>> map = new HashMap<>();
69 MapMapCollectionWithDefault mapWithDefault = new MapMapCollectionWithDefault(map);
69 DelegatedMapMapWithDefault mapWithDefault = new DelegatedMapMapWithDefault(map);
7070
7171 // 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);
7673
7774 // Index entry
7875 Indexer indexer = api.getIndexer(entry);
8279 }
8380
8481 // 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);
8983 }
9084
9185 // --- SourcesSavable --- //
138132 }
139133 }
140134
141 protected static class MapWrapper<K, V> implements Map<K, V> {
135 protected static class DelegatedMap<K, V> implements Map<K, V> {
142136 protected Map<K, V> map;
143137
144 public MapWrapper(Map<K, V> map) { this.map = map; }
138 public DelegatedMap(Map<K, V> map) { this.map = map; }
145139
146140 @Override public int size() { return map.size(); }
147141 @Override public boolean isEmpty() { return map.isEmpty(); }
159153 @Override public int hashCode() { return map.hashCode(); }
160154 }
161155
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); }
164158
165159 @Override public Collection get(Object o) {
166160 Collection value = map.get(o);
172166 }
173167 }
174168
175 protected static class MapMapCollectionWithDefault extends MapWrapper<String, Map<String, Collection>> {
169 protected static class DelegatedMapMapWithDefault extends DelegatedMap<String, Map<String, Collection>> {
176170 protected HashMap<String, Map<String, Collection>> wrappers = new HashMap<>();
177171
178 public MapMapCollectionWithDefault(Map<String, Map<String, Collection>> map) { super(map); }
172 public DelegatedMapMapWithDefault(Map<String, Map<String, Collection>> map) { super(map); }
179173
180174 @Override public Map<String, Collection> get(Object o) {
181175 Map<String, Collection> value = wrappers.get(o);
184178 String key = o.toString();
185179 HashMap<String, Collection> m = new HashMap<>();
186180 map.put(key, m);
187 wrappers.put(key, value=new MapCollectionWithDefault(m));
181 wrappers.put(key, value=new DelegatedMapWithDefault(m));
188182 }
189183
190184 return value;
1717 import java.net.URI;
1818 import java.net.URISyntaxException;
1919 import java.util.Collection;
20 import java.util.concurrent.Future;
2021
2122 public class UriUtil {
2223 /*
2324 * Convert inner entry URI to outer entry uri with a fragment. Example:
2425 * file://codebase/a/b/c/D$E.class => file://codebase/a/b/c/D.class#typeDeclaration=D$E
2526 */
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) {
2728 TypeFactory typeFactory = TypeFactoryService.getInstance().get(entry);
2829
2930 if (typeFactory != null) {
3132
3233 if (type != null) {
3334 URI uri = entry.getUri();
34 String path = getOuterPath(collectionOfIndexes, entry, type);
35 String path = getOuterPath(collectionOfFutureIndexes, entry, type);
3536
3637 try {
3738 return new URI(uri.getScheme(), uri.getHost(), path, query, fragment);
4546 }
4647
4748 @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) {
4950 String outerName = type.getOuterName();
5051
5152 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);
5457
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 }
5964 }
6065 }
6166 }
67 } catch (Exception e) {
68 assert ExceptionUtil.printStackTrace(e);
6269 }
6370 }
6471
1111 import org.jd.gui.api.model.Indexes;
1212 import org.jd.gui.api.model.TreeNodeData;
1313 import org.jd.gui.api.model.Type;
14 import org.jd.gui.util.exception.ExceptionUtil;
1415 import org.jd.gui.util.function.TriConsumer;
1516 import org.jd.gui.util.swing.SwingUtil;
1617 import org.jd.gui.view.component.Tree;
2627 import java.awt.event.*;
2728 import java.util.*;
2829 import java.util.List;
30 import java.util.concurrent.Future;
2931
3032 public class OpenTypeHierarchyView {
3133 protected static final ImageIcon ROOT_CLASS_ICON = new ImageIcon(OpenTypeHierarchyView.class.getClassLoader().getResource("org/jd/gui/images/generate_class.png"));
3436 protected static final TreeNodeComparator TREE_NODE_COMPARATOR = new TreeNodeComparator();
3537
3638 protected API api;
37 protected Collection<Indexes> collectionOfIndexes;
39 protected Collection<Future<Indexes>> collectionOfFutureIndexes;
3840
3941 protected JDialog openTypeHierarchyDialog;
4042 protected Tree openTypeHierarchyTree;
140142 });
141143 }
142144
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;
145147 SwingUtil.invokeLater(() -> {
146148 updateTree(entry, typeName);
147149 openTypeHierarchyDialog.setVisible(true);
159161 SwingUtil.invokeLater(() -> openTypeHierarchyDialog.setCursor(Cursor.getDefaultCursor()));
160162 }
161163
162 public void updateTree(Collection<Indexes> collectionOfIndexes) {
163 this.collectionOfIndexes = collectionOfIndexes;
164 public void updateTree(Collection<Future<Indexes>> collectionOfFutureIndexes) {
165 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
164166 TreeNode selectedTreeNode = (TreeNode)openTypeHierarchyTree.getLastSelectedPathComponent();
165167
166168 if (selectedTreeNode != null) {
366368 protected List<String> getSubTypeNames(String typeName) {
367369 ArrayList<String> result = new ArrayList<>();
368370
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 }
377383 }
378384 }
379385 }
380386 }
387 } catch (Exception e) {
388 assert ExceptionUtil.printStackTrace(e);
381389 }
382390
383391 return result;
387395 protected List<Container.Entry> getEntries(String typeName) {
388396 ArrayList<Container.Entry> result = new ArrayList<>();
389397
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 }
398410 }
399411 }
400412 }
401413 }
414 } catch (Exception e) {
415 assert ExceptionUtil.printStackTrace(e);
402416 }
403417
404418 return result;
1111 import org.jd.gui.api.feature.TreeNodeExpandable;
1212 import org.jd.gui.api.feature.UriGettable;
1313 import org.jd.gui.api.model.Container;
14 import org.jd.gui.model.container.FilteredContainerWrapper;
14 import org.jd.gui.model.container.DelegatingFilterContainer;
1515 import org.jd.gui.spi.TreeNodeFactory;
1616 import org.jd.gui.util.function.TriConsumer;
1717 import org.jd.gui.util.swing.SwingUtil;
363363 }
364364
365365 @SuppressWarnings("unchecked")
366 public void updateTree(Collection<FilteredContainerWrapper> containers, int matchingTypeCount) {
366 public void updateTree(Collection<DelegatingFilterContainer> containers, int matchingTypeCount) {
367367 SwingUtil.invokeLater(() -> {
368368 DefaultTreeModel model = (DefaultTreeModel)searchInConstantPoolsTree.getModel();
369369 T root = (T)model.getRoot();
375375 expanded.clear();
376376
377377 if (containers != null) {
378 ArrayList<FilteredContainerWrapper> list = new ArrayList<>(containers);
378 ArrayList<DelegatingFilterContainer> list = new ArrayList<>(containers);
379379
380380 list.sort(CONTAINER_COMPARATOR);
381381
382 for (FilteredContainerWrapper container : list) {
382 for (DelegatingFilterContainer container : list) {
383383 // Init uri set
384384 accepted.addAll(container.getUris());
385385 // Populate tree
1111 import org.jd.gui.api.feature.TreeNodeExpandable;
1212 import org.jd.gui.api.feature.UriGettable;
1313 import org.jd.gui.api.model.Container;
14 import org.jd.gui.model.container.FilteredContainerWrapper;
14 import org.jd.gui.model.container.DelegatingFilterContainer;
1515 import org.jd.gui.spi.TreeNodeFactory;
1616 import org.jd.gui.util.swing.SwingUtil;
1717 import org.jd.gui.view.component.Tree;
3131 import java.util.function.Consumer;
3232
3333 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();
3535
3636 protected API api;
3737
9898 }
9999
100100 @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) {
102102 this.selectedEntryCallback = selectedEntryCallback;
103103 this.closeCallback = closeCallback;
104104
109109 // Reset tree nodes
110110 root.removeAllChildren();
111111
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) {
116116 Container.Entry parentEntry = container.getRoot().getParent();
117117 TreeNodeFactory factory = api.getTreeNodeFactory(parentEntry);
118118
193193 }
194194 }
195195
196 protected static class FilteredContainerWrapperComparator implements Comparator<FilteredContainerWrapper> {
196 protected static class DelegatingFilterContainerComparator implements Comparator<DelegatingFilterContainer> {
197197 @Override
198 public int compare(FilteredContainerWrapper fcw1, FilteredContainerWrapper fcw2) {
198 public int compare(DelegatingFilterContainer fcw1, DelegatingFilterContainer fcw2) {
199199 return fcw1.getRoot().getUri().compareTo(fcw2.getRoot().getUri());
200200 }
201201 }
7979 }
8080
8181 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 }
8682 // Add a new tab
8783 JLabel tabCloseButton = new JLabel(CLOSE_ICON);
8884 tabCloseButton.setToolTipText("Close this panel");
119119 int hashCode = 1;
120120
121121 while (enumeration.hasMoreElements()) {
122 hashCode *= 31;
123
122124 Object element = enumeration.nextElement();
123
124 hashCode *= 31;
125125
126126 if (element != null) {
127127 hashCode += element.hashCode();
171171 if ((page == null) && (baseNode instanceof PageCreator)) {
172172 page = ((PageCreator)baseNode).createPage(api);
173173 page.putClientProperty("node", baseNode);
174 page.putClientProperty("preferences-stamp", Integer.valueOf(api.getPreferences().hashCode()));
175 page.putClientProperty("collectionOfIndexes-stamp", Integer.valueOf(api.getCollectionOfIndexes().hashCode()));
176174
177175 String path = baseUri.getPath();
178176 String label = path.substring(path.lastIndexOf('/')+1);
1111 import org.jd.gui.api.feature.PageCreator;
1212 import org.jd.gui.api.feature.UriGettable;
1313 import org.jd.gui.api.model.Container;
14 import org.jd.gui.view.component.OneTypeReferenceByLinePage;
14 import org.jd.gui.view.component.OneTypeReferencePerLinePage;
1515 import org.jd.gui.view.data.TreeNodeBean;
1616
1717 import javax.swing.*;
4848 @Override
4949 @SuppressWarnings("unchecked")
5050 public <T extends JComponent & UriGettable> T createPage(API api) {
51 return (T)new OneTypeReferenceByLinePage(api, entry);
51 return (T)new OneTypeReferencePerLinePage(api, entry);
5252 }
5353 }
5454 }
+0
-46
services/src/main/java/org/jd/gui/util/index/IndexUtil.java less more
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 }
8585 // Decompile class file
8686 DECOMPILER.decompile(configuration, loader, printer, entryInternalName);
8787 setText(printer.getStringBuffer().toString());
88
89 // Show hyperlinks
90 indexesChanged(api.getCollectionOfIndexes());
9188 } catch (Throwable t) {
9289 assert ExceptionUtil.printStackTrace(t);
9390 setText("// INTERNAL ERROR //");
9292
9393 @Override protected RSyntaxTextArea newSyntaxTextArea() { return new SourceSyntaxTextArea(); }
9494
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 {
11196 @Override protected RTextAreaUI createRTextAreaUI() { return new SourceSyntaxTextAreaUI(this); }
11297 }
11398
1313 import org.jd.gui.api.model.Container;
1414 import org.jd.gui.api.model.Indexes;
1515 import org.jd.gui.util.exception.ExceptionUtil;
16 import org.jd.gui.util.index.IndexUtil;
16 import org.jd.gui.util.index.IndexesUtil;
1717 import org.jd.gui.util.io.TextReader;
1818 import org.jd.gui.util.xml.AbstractXmlPathFinder;
1919
2222 import java.net.URISyntaxException;
2323 import java.util.*;
2424 import java.util.List;
25 import java.util.concurrent.Future;
2526
2627 public class EjbJarXmlFilePage extends TypeReferencePage implements UriGettable, IndexesChangeListener {
2728 protected API api;
2829 protected Container.Entry entry;
29 protected Collection<Indexes> collectionOfIndexes;
30 protected Collection<Future<Indexes>> collectionOfFutureIndexes = Collections.emptyList();
3031
3132 public EjbJarXmlFilePage(API api, Container.Entry entry) {
3233 this.api = api;
3738 new PathFinder().find(text);
3839 // Display
3940 setText(text);
40 // Show hyperlinks
41 indexesChanged(api.getCollectionOfIndexes());
4241 }
4342
4443 public String getSyntaxStyle() { return SyntaxConstants.SYNTAX_STYLE_XML; }
5857
5958 // Open link
6059 String internalTypeName = data.internalTypeName;
61 List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, internalTypeName);
60 List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, internalTypeName);
6261 String rootUri = entry.getContainer().getRoot().getUri().toString();
6362 ArrayList<Container.Entry> sameContainerEntries = new ArrayList<>();
6463
9089 }
9190
9291 // --- IndexesChangeListener --- //
93 public void indexesChanged(Collection<Indexes> collectionOfIndexes) {
92 public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) {
9493 // Update the list of containers
95 this.collectionOfIndexes = collectionOfIndexes;
94 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
9695 // Refresh links
9796 boolean refresh = false;
9897
9998 for (Map.Entry<Integer, HyperlinkData> entry : hyperlinks.entrySet()) {
10099 TypeHyperlinkData entryData = (TypeHyperlinkData)entry.getValue();
101100 String internalTypeName = entryData.internalTypeName;
102 boolean enabled = IndexUtil.containsInternalTypeName(collectionOfIndexes, internalTypeName);
101 boolean enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName);
103102
104103 if (entryData.enabled != enabled) {
105104 entryData.enabled = enabled;
100100 }
101101
102102 public class HyperlinkSyntaxTextArea extends RSyntaxTextArea {
103 /**
104 * @see HyperlinkPage.HyperlinkSyntaxTextArea#getUnderlineForToken(org.fife.ui.rsyntaxtextarea.Token)
105 */
106 @Override
103107 public boolean getUnderlineForToken(Token t) {
104108 Map.Entry<Integer, HyperlinkData> entry = hyperlinks.floorEntry(t.getOffset());
105109 if (entry != null) {
4040 ANTLRJavaParser.parse(new ANTLRInputStream(text), referenceListener);
4141 // Display
4242 setText(text);
43 // Show hyperlinks
44 indexesChanged(api.getCollectionOfIndexes());
4543 }
4644
4745 public String getSyntaxStyle() { return SyntaxConstants.SYNTAX_STYLE_JAVA; }
228226 }
229227
230228 public class ReferenceListener extends AbstractJavaListener {
231
232229 protected StringBuilder sbTypeDeclaration = new StringBuilder();
233230 protected HashMap<String, TypePage.ReferenceData> referencesCache = new HashMap<>();
234231 protected String currentInternalTypeName;
1212 import org.jd.gui.api.model.Container;
1313 import org.jd.gui.api.model.Indexes;
1414 import org.jd.gui.util.exception.ExceptionUtil;
15 import org.jd.gui.util.index.IndexUtil;
15 import org.jd.gui.util.index.IndexesUtil;
1616
1717 import java.awt.*;
1818 import java.net.URI;
1919 import java.util.Collection;
20 import java.util.Collections;
2021 import java.util.List;
2122 import java.util.Map;
23 import java.util.concurrent.Future;
2224
2325 public class LogPage extends HyperlinkPage implements UriGettable, IndexesChangeListener {
2426 protected API api;
2527 protected URI uri;
26 protected Collection<Indexes> collectionOfIndexes;
28 protected Collection<Future<Indexes>> collectionOfFutureIndexes = Collections.emptyList();
2729
2830 public LogPage(API api, URI uri, String content) {
2931 this.api = api;
4143 parseLine(content, index, content.length());
4244 // Display
4345 setText(content);
44 // Show hyperlinks
45 indexesChanged(api.getCollectionOfIndexes());
4646 }
4747
4848 protected void parseLine(String content, int index, int eol) {
7575 int lastDotIndex = typeAndMethodNames.lastIndexOf('.');
7676 String methodName = typeAndMethodNames.substring(lastDotIndex + 1);
7777 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);
7979 int leftParenthesisIndex = hyperlinkData.endPosition + 1;
8080 int rightParenthesisIndex = text.indexOf(')', leftParenthesisIndex);
8181 String lineNumberOrNativeMethodFlag = text.substring(leftParenthesisIndex, rightParenthesisIndex);
108108 }
109109
110110 // --- IndexesChangeListener --- //
111 public void indexesChanged(Collection<Indexes> collectionOfIndexes) {
111 public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) {
112112 // Update the list of containers
113 this.collectionOfIndexes = collectionOfIndexes;
113 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
114114 // Refresh links
115115 boolean refresh = false;
116116 String text = getText();
120120 String typeAndMethodNames = text.substring(entryData.startPosition, entryData.endPosition);
121121 int lastDotIndex = typeAndMethodNames.lastIndexOf('.');
122122 String internalTypeName = typeAndMethodNames.substring(0, lastDotIndex).replace('.', '/');
123 boolean enabled = IndexUtil.containsInternalTypeName(collectionOfIndexes, internalTypeName);
123 boolean enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName);
124124
125125 if (entryData.enabled != enabled) {
126126 entryData.enabled = enabled;
1212 import org.jd.gui.api.model.Container;
1313 import org.jd.gui.api.model.Indexes;
1414 import org.jd.gui.util.exception.ExceptionUtil;
15 import org.jd.gui.util.index.IndexUtil;
15 import org.jd.gui.util.index.IndexesUtil;
1616 import org.jd.gui.util.io.TextReader;
1717
1818 import java.awt.*;
1919 import java.net.URI;
2020 import java.net.URISyntaxException;
21 import java.util.ArrayList;
22 import java.util.Collection;
21 import java.util.*;
2322 import java.util.List;
24 import java.util.Map;
23 import java.util.concurrent.Future;
2524
2625 public class ManifestFilePage extends HyperlinkPage implements UriGettable, IndexesChangeListener {
2726 protected API api;
2827 protected Container.Entry entry;
29 protected Collection<Indexes> collectionOfIndexes;
28 protected Collection<Future<Indexes>> collectionOfFutureIndexes = Collections.emptyList();
3029
3130 public ManifestFilePage(API api, Container.Entry entry) {
3231 this.api = api;
5958 }
6059 // Display
6160 setText(text);
62 // Show hyperlinks
63 indexesChanged(api.getCollectionOfIndexes());
6461 }
6562
6663 public int skipSeparators(String text, int index) {
133130 String text = getText();
134131 String textLink = getValue(text, hyperlinkData.startPosition, hyperlinkData.endPosition);
135132 String internalTypeName = textLink.replace('.', '/');
136 List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, internalTypeName);
133 List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, internalTypeName);
137134 String rootUri = entry.getContainer().getRoot().getUri().toString();
138135 ArrayList<Container.Entry> sameContainerEntries = new ArrayList<>();
139136
165162 }
166163
167164 // --- IndexesChangeListener --- //
168 public void indexesChanged(Collection<Indexes> collectionOfIndexes) {
165 public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) {
169166 // Update the list of containers
170 this.collectionOfIndexes = collectionOfIndexes;
167 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
171168 // Refresh links
172169 boolean refresh = false;
173170 String text = getText();
176173 ManifestHyperlinkData entryData = (ManifestHyperlinkData)entry.getValue();
177174 String textLink = getValue(text, entryData.startPosition, entryData.endPosition);
178175 String internalTypeName = textLink.replace('.', '/');
179 boolean enabled = IndexUtil.containsInternalTypeName(collectionOfIndexes, internalTypeName);
176 boolean enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName);
180177
181178 if (entryData.enabled != enabled) {
182179 entryData.enabled = enabled;
191188
192189 public static String getValue(String text, int startPosition, int endPosition) {
193190 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 ", "");
200197 }
201198
202199 public static class ManifestHyperlinkData extends HyperlinkData {
+0
-136
services/src/main/java/org/jd/gui/view/component/OneTypeReferenceByLinePage.java less more
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 }
1616 import org.jd.gui.api.model.Indexes;
1717 import org.jd.gui.api.model.Type;
1818 import org.jd.gui.util.exception.ExceptionUtil;
19 import org.jd.gui.util.index.IndexUtil;
19 import org.jd.gui.util.index.IndexesUtil;
2020 import org.jd.gui.util.matcher.DescriptorMatcher;
2121
2222 import java.awt.*;
2424 import java.net.URISyntaxException;
2525 import java.util.*;
2626 import java.util.List;
27 import java.util.concurrent.Future;
2728 import java.util.function.BiFunction;
2829 import java.util.regex.Matcher;
2930 import java.util.regex.Pattern;
3132 public abstract class TypePage extends CustomLineNumbersPage implements UriGettable, UriOpenable, IndexesChangeListener, FocusedTypeGettable {
3233 protected API api;
3334 protected Container.Entry entry;
34 protected Collection<Indexes> collectionOfIndexes;
35 protected Collection<Future<Indexes>> collectionOfFutureIndexes = Collections.emptyList();
3536
3637 protected HashMap<String, DeclarationData> declarations = new HashMap<>();
3738 protected TreeMap<Integer, DeclarationData> typeDeclarations = new TreeMap<>();
6566 // Open link
6667 ReferenceData reference = hyperlinkReferenceData.reference;
6768 String typeName = reference.typeName;
68 List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, typeName);
69 List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, typeName);
6970 String fragment = typeName;
7071
7172 if (reference.name != null) {
331332
332333 // --- IndexesChangeListener --- //
333334 @Override
334 public void indexesChanged(Collection<Indexes> collectionOfIndexes) {
335 public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) {
335336 // Update the list of containers
336 this.collectionOfIndexes = collectionOfIndexes;
337 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
337338 // Refresh links
338339 boolean refresh = false;
339340
359360 }
360361 } else {
361362 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);
368376 }
369377 }
370378
383391 protected String searchTypeHavingMember(String typeName, String name, String descriptor, Container.Entry entry) {
384392 ArrayList<Container.Entry> entries = new ArrayList<>();
385393
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);
394408 }
395409
396410 String rootUri = entry.getContainer().getRoot().getUri().toString();
1313 import org.jd.gui.api.model.Container;
1414 import org.jd.gui.api.model.Indexes;
1515 import org.jd.gui.util.exception.ExceptionUtil;
16 import org.jd.gui.util.index.IndexUtil;
16 import org.jd.gui.util.index.IndexesUtil;
1717 import org.jd.gui.util.io.TextReader;
1818 import org.jd.gui.util.xml.AbstractXmlPathFinder;
1919
2222 import java.net.URISyntaxException;
2323 import java.util.*;
2424 import java.util.List;
25 import java.util.concurrent.Future;
2526
2627 public class WebXmlFilePage extends TypeReferencePage implements UriGettable, IndexesChangeListener {
2728 protected API api;
2829 protected Container.Entry entry;
29 protected Collection<Indexes> collectionOfIndexes;
30 protected Collection<Future<Indexes>> collectionOfFutureIndexes;
3031
3132 public WebXmlFilePage(API api, Container.Entry entry) {
3233 this.api = api;
3738 new PathFinder().find(text);
3839 // Display
3940 setText(text);
40 // Show hyperlinks
41 indexesChanged(api.getCollectionOfIndexes());
4241 }
4342
4443 public String getSyntaxStyle() { return SyntaxConstants.SYNTAX_STYLE_XML; }
6665 }
6766 } else {
6867 String internalTypeName = data.internalTypeName;
69 List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, internalTypeName);
68 List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, internalTypeName);
7069 String rootUri = entry.getContainer().getRoot().getUri().toString();
7170 ArrayList<Container.Entry> sameContainerEntries = new ArrayList<>();
7271
129128 }
130129
131130 // --- IndexesChangeListener --- //
132 public void indexesChanged(Collection<Indexes> collectionOfIndexes) {
131 public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) {
133132 // Update the list of containers
134 this.collectionOfIndexes = collectionOfIndexes;
133 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
135134 // Refresh links
136135 boolean refresh = false;
137136
144143 enabled = searchEntry(this.entry.getContainer().getRoot(), d.path) != null;
145144 } else {
146145 String internalTypeName = data.internalTypeName;
147 enabled = IndexUtil.containsInternalTypeName(collectionOfIndexes, internalTypeName);
146 enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName);
148147 }
149148
150149 if (data.enabled != enabled) {
170169 }
171170
172171 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");
176175
177176 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");
184183
185184 protected static List<String> hyperlinkPaths = new ArrayList<>(typeHyperlinkPaths.size() + pathHyperlinkPaths.size());
186185
1313 import org.jd.gui.api.model.Container;
1414 import org.jd.gui.api.model.Indexes;
1515 import org.jd.gui.util.exception.ExceptionUtil;
16 import org.jd.gui.util.index.IndexUtil;
16 import org.jd.gui.util.index.IndexesUtil;
1717 import org.jd.gui.util.io.TextReader;
1818
1919 import java.awt.*;
2323 import java.util.Collection;
2424 import java.util.List;
2525 import java.util.Map;
26 import java.util.concurrent.Future;
2627 import java.util.regex.Matcher;
2728 import java.util.regex.Pattern;
2829
2930 public class XmlFilePage extends TypeReferencePage implements UriGettable, IndexesChangeListener {
3031 protected API api;
3132 protected Container.Entry entry;
32 protected Collection<Indexes> collectionOfIndexes;
33 protected Collection<Future<Indexes>> collectionOfFutureIndexes;
3334
3435 public XmlFilePage(API api, Container.Entry entry) {
3536 this.api = api;
5455 }
5556 // Display
5657 setText(text);
57 // Show hyperlinks
58 indexesChanged(api.getCollectionOfIndexes());
5958 }
6059
6160 public String getSyntaxStyle() { return SyntaxConstants.SYNTAX_STYLE_XML; }
7574
7675 // Open link
7776 String internalTypeName = data.internalTypeName;
78 List<Container.Entry> entries = IndexUtil.grepInternalTypeName(collectionOfIndexes, internalTypeName);
77 List<Container.Entry> entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, internalTypeName);
7978 String rootUri = entry.getContainer().getRoot().getUri().toString();
8079 ArrayList<Container.Entry> sameContainerEntries = new ArrayList<>();
8180
107106 }
108107
109108 // --- IndexesChangeListener --- //
110 public void indexesChanged(Collection<Indexes> collectionOfIndexes) {
109 public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) {
111110 // Update the list of containers
112 this.collectionOfIndexes = collectionOfIndexes;
111 this.collectionOfFutureIndexes = collectionOfFutureIndexes;
113112 // Refresh links
114113 boolean refresh = false;
115114
116115 for (Map.Entry<Integer, HyperlinkData> entry : hyperlinks.entrySet()) {
117116 TypeHyperlinkData data = (TypeHyperlinkData)entry.getValue();
118117 String internalTypeName = data.internalTypeName;
119 boolean enabled = IndexUtil.containsInternalTypeName(collectionOfIndexes, internalTypeName);
118 boolean enabled = IndexesUtil.containsInternalTypeName(collectionOfFutureIndexes, internalTypeName);
120119
121120 if (data.enabled != enabled) {
122121 data.enabled = enabled;