Source Code Cross Referenced for SymbolUsageLocationSearch.java in  » IDE » Schmortopf » Schmortopf » JavaSourceEditor » SymbolUsageLocationSearch » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE » Schmortopf » Schmortopf.JavaSourceEditor.SymbolUsageLocationSearch 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package Schmortopf.JavaSourceEditor.SymbolUsageLocationSearch;
0002:
0003:        /**
0004:         *  Searches all locations, where a given symbol is used.
0005:         *  A symbol can be:                                              
0006:         *  - a method,
0007:         *  - a class or member attribute,                                   
0008:         *  - a given fully qualified classname [ -> search for instantiations ]
0009:         *
0010:         *  Operation:
0011:         *
0012:         *  This process uses the results of the file ***dependencies scanner***:
0013:         *  One only has to search files, which have the source file containing the
0014:         *  symbol in their dependency-files-list.
0015:         *  Or short: Only look in files, which depend in some way from the
0016:         *  file containing the given symbol.
0017:         *
0018:         *  For each **possible** candidate [entry in some "Block" parsertree node], 
0019:         *  one must follow the trace through possible
0020:         *  parents tree's back (like done, when the user clicks on
0021:         *  "Jump to declaration" - just do the same and see, the target really is
0022:         *  the file containing the given symbol. If this is the case, one usage
0023:         *  location has been found and can be added to a list.
0024:         *
0025:         */
0026:
0027:        import java.util.Vector;
0028:        import java.awt.EventQueue;
0029:        import java.awt.Point;
0030:        import java.io.CharArrayReader;
0031:        import javax.swing.JOptionPane;
0032:        import javax.swing.tree.DefaultMutableTreeNode;
0033:
0034:        import Schmortopf.Main.IDE_ProjectFrame;
0035:        import Schmortopf.FileStructure.FileStructureDescriptionManager;
0036:        import Schmortopf.FileStructure.FileStructureDescriptionParserTreePostProcessor;
0037:        import Schmortopf.FileStructure.Descriptions.*;
0038:        import Schmortopf.JavaSourceEditor.SourceEditorDocument;
0039:        import Schmortopf.JavaSourceEditor.TextSearch.*;
0040:        import Schmortopf.JavaLanguageParser.*;
0041:        import Schmortopf.JavaLanguageParser.JavaCCParser.*;
0042:        import Schmortopf.FileComponents.Model.TokenTreeUserObject;
0043:        import Schmortopf.FileComponents.Model.EditableLeafObject;
0044:        import Schmortopf.FileComponents.View.FileComponentsTreeCellRenderer;
0045:        import Schmortopf.JavaSourceEditor.TextSearch.ObjectSearch;
0046:        import Schmortopf.SearchResults.SearchResultsUserObject;
0047:        import Schmortopf.Utility.StringUtilities;
0048:        import Schmortopf.Utility.ThreadEngine.ThreadEngine;
0049:        import Schmortopf.Utility.gui.dialogs.ProgressWindow;
0050:        import Schmortopf.JavaSourceEditor.CodeCompletion.CodeCompletionUtilities;
0051:        import Language.Language;
0052:        import Shared.Logging.Log;
0053:
0054:        public class SymbolUsageLocationSearch implements 
0055:                ParserOutputProcessor, JavaParserConstants {
0056:
0057:            private IDE_ProjectFrame projectFrame;
0058:            private ParserTreeNode currentNode; // used by the java parser
0059:
0060:            private final String searchMessage = Language
0061:                    .Translate("Searching")
0062:                    + "...";
0063:            private final String searchInfoMessage = Language
0064:                    .Translate("The results are displayed in the search results tree.");
0065:
0066:            private boolean searchHasBeenCancelledByTheUser = false;
0067:
0068:            public SymbolUsageLocationSearch(IDE_ProjectFrame theProjectFrame) {
0069:                this .projectFrame = theProjectFrame;
0070:            } // Constructor
0071:
0072:            /**
0073:             *  Search all locations inside the project,
0074:             *  where the classes passed in selectedTargetFSDs are used.
0075:             */
0076:            public void searchClassUsageLocationsFor(
0077:                    final FileStructureDescription[] selectedTargetFSDs,
0078:                    final boolean doTrackAttributes) {
0079:                // Wait until the other popups have goone, so the
0080:                // way is cleared for a new progresswindow:
0081:                EventQueue.invokeLater(new Runnable() {
0082:                    public void run() {
0083:                        // We must call the dependencies updater and tell it to process all
0084:                        // pending entries. For this and other reasons, we must process this
0085:                        // in a user thread, otherwise one could produce deadlocks:
0086:                        Runnable searchRunnable = new Runnable() {
0087:                            public void run() {
0088:                                // Give Swing some time right now (to show the progressWindow):
0089:                                //try{ Thread.sleep(1199); } catch( Exception e2 ){}
0090:                                searchClassUsageLocations_InThread(
0091:                                        selectedTargetFSDs, doTrackAttributes);
0092:                            }
0093:                        };
0094:                        ThreadEngine.getInstance().addRunnable(searchRunnable,
0095:                                "searchClassUsageLocationsFor");
0096:                    }
0097:                });
0098:            } // searchClassUsageLocationsFor
0099:
0100:            /**
0101:             *  Search all locations inside the project,
0102:             *  where the classes passed in selectedTargetFSDs are used.
0103:             */
0104:            private void searchClassUsageLocations_InThread(
0105:                    final FileStructureDescription[] selectedTargetFSDs,
0106:                    final boolean doTrackAttributes) {
0107:                searchHasBeenCancelledByTheUser = false; // initialize
0108:                String searchName = "Class"; // is displayed as tab title in the search results panel
0109:                // Make sure, the searchresults tree displays some useful information
0110:                // while the search is running, and reset it, if the search didn't find anything.
0111:                this .projectFrame.initializeSearchResults(searchName,
0112:                        searchMessage);
0113:                // Give Swing some time right now:
0114:                try {
0115:                    Thread.sleep(44);
0116:                } catch (Exception e0) {
0117:                }
0118:                // Call the actual worker method:
0119:                boolean elementsHaveBeenFound = this 
0120:                        .search_Class_Usage_Locations_In_Thread(searchName,
0121:                                selectedTargetFSDs, doTrackAttributes);
0122:                if (!elementsHaveBeenFound) {
0123:                    // Signalize it's ready for new searches:
0124:                    this .projectFrame.initializeSearchResults(searchName,
0125:                            Language.Translate("No hits"));
0126:                    // Give Swing some time right now:
0127:                    try {
0128:                        Thread.sleep(44);
0129:                    } catch (Exception e2) {
0130:                    }
0131:                }
0132:            } // searchClassUsageLocations_InThread
0133:
0134:            /**                                     
0135:             *  Search all locations inside the project,
0136:             *  where the classes passed in selectedTargetFSDs are used.
0137:             */
0138:            private boolean search_Class_Usage_Locations_In_Thread(
0139:                    final String searchName,
0140:                    final FileStructureDescription[] selectedTargetFSDs,
0141:                    final boolean doTrackAttributes) {
0142:
0143:                //ystem.out.println("cc> search_Class_Usage_Locations_In_Thread starts.");
0144:                //ystem.out.println("cc> selectedTargetFSDs.length= " + selectedTargetFSDs.length );
0145:
0146:                boolean elementsHaveBeenFound = false;
0147:                long startTime = System.currentTimeMillis();
0148:                // Make the progressWindow and show it, if the search
0149:                // has package or global scope, otherwise the search is so fast,
0150:                // that the progressWindow is not needed:
0151:                ProgressWindow progressWindowCandidate = null;
0152:                String windowText = searchMessage + "\n" + searchInfoMessage;
0153:                progressWindowCandidate = new ProgressWindow(windowText, null,
0154:                        projectFrame.getParentFrameForChildren(), projectFrame
0155:                                .getMainFrameProvider(), true);
0156:                progressWindowCandidate.showCentered();
0157:
0158:                final ProgressWindow progressWindow = progressWindowCandidate;
0159:
0160:                FileStructureDescriptionManager fsdManager = this .projectFrame
0161:                        .getFileStructureDescriptionManager();
0162:                // We need the file dependencies list to be complete, so tell the
0163:                // dependencies updater to process all pending entries right now.
0164:                // The pc must be in a user thread context for this.
0165:                fsdManager.waitForUpdaters();
0166:
0167:                // In contrary to the other two searches [ attribute and method usage search ]
0168:                // this search just can be carries out by making one search for each element
0169:                // in the selectedTargetFSDs and adding the hits:
0170:                // Fill all hits into ClassReferenceEntry objects and add them to this vector:
0171:                Vector classReferences = new Vector();
0172:                for (int targetFSDIndex = 0; targetFSDIndex < selectedTargetFSDs.length; targetFSDIndex++) {
0173:                    final FileStructureDescription targetFSD = selectedTargetFSDs[targetFSDIndex];
0174:                    searchClassUsageLocationsOf(
0175:                            selectedTargetFSDs[targetFSDIndex],
0176:                            classReferences, fsdManager, doTrackAttributes,
0177:                            progressWindow);
0178:                    if (progressWindow != null) {
0179:                        // Break the search, if the user has pushed the cancel button:
0180:                        if (progressWindow.getWasCancelled()) {
0181:                            searchHasBeenCancelledByTheUser = true;
0182:                            break;
0183:                        }
0184:                        try {
0185:                            Thread.yield();
0186:                        } catch (Exception e234986) {
0187:                        }
0188:                    }
0189:                } // for loop for each selectedTargetFSDs element
0190:
0191:                if (!this .searchHasBeenCancelledByTheUser) {
0192:                    // Not absolutely required, but more secure, because at least the queue of the
0193:                    // dependency updater will contain some entries: Force to perform all pending
0194:                    // entries again:
0195:                    fsdManager.waitForUpdaters();
0196:
0197:                    if (progressWindow != null) {
0198:                        final int maxValue = classReferences.size();
0199:                        EventQueue.invokeLater(new Runnable() {
0200:                            public void run() {
0201:                                progressWindow.setProgressValue(0);
0202:                                progressWindow.setProgressMaxValue(maxValue);
0203:                            }
0204:                        });
0205:                    }
0206:
0207:                    // Create the SearchResultsUserObject vector:
0208:                    Vector searchResultsUserObjectVector = new Vector();
0209:                    for (int i = 0; i < classReferences.size(); i++) {
0210:
0211:                        if (progressWindow != null) {
0212:                            final int progressValue = i;
0213:                            EventQueue.invokeLater(new Runnable() {
0214:                                public void run() {
0215:                                    progressWindow
0216:                                            .setProgressValue(progressValue);
0217:                                }
0218:                            });
0219:                            // Break the search, if the user has pushed the cancel button:
0220:                            if (progressWindow.getWasCancelled()) {
0221:                                searchHasBeenCancelledByTheUser = true;
0222:                                break;
0223:                            }
0224:                            try {
0225:                                Thread.yield();
0226:                            } catch (Exception e234986) {
0227:                            }
0228:                        }
0229:
0230:                        final ClassReferenceEntry entry = (ClassReferenceEntry) classReferences
0231:                                .elementAt(i);
0232:                        // We need the SourceEditorDocument:
0233:                        EditableLeafObject leaf = fsdManager
0234:                                .getJavaSourceEditorLeafForFSD(entry
0235:                                        .getParentFSD());
0236:                        // On leaf level, one should unload the content, after having loaded and processed it.
0237:                        // But one shouldn't unload it, if it already was loaded by another one, when this method starts.
0238:                        // It's not serious, if this doesn't work some times, so no need for synchronization here.
0239:                        boolean leafWasLoadedInitially = leaf.isContentLoaded();
0240:                        Object leafContent = leaf.getContent();
0241:                        if (leafContent instanceof  SourceEditorDocument) {
0242:                            final SourceEditorDocument sourceDoc = (SourceEditorDocument) leafContent;
0243:
0244:                            // Create a SearchResultsFileNodeUserObject and add it to the vector:
0245:                            final int docPosition = sourceDoc
0246:                                    .getPositionOfStartOfLine(entry
0247:                                            .getStartLine() - 1)
0248:                                    + (entry.getStartColumn() + entry
0249:                                            .getEndColumn()) / 2;
0250:                            final boolean breakAtPoints = false;
0251:                            final int[] nearestWordPosition = sourceDoc
0252:                                    .getNearestWordPositionTo(docPosition,
0253:                                            breakAtPoints);
0254:                            final int startOffset = nearestWordPosition[0];
0255:                            final int endOffset = nearestWordPosition[1];
0256:
0257:                            final SearchResultsUserObject resultUserObject = new SearchResultsUserObject(
0258:                                    leaf, entry.getStartLine() - 1,
0259:                                    docPosition, entry.getEndColumn()
0260:                                            - entry.getStartColumn() + 1);
0261:
0262:                            searchResultsUserObjectVector
0263:                                    .addElement(resultUserObject);
0264:                        } // if
0265:                        else {
0266:                            Log
0267:                                    .Error("leafContent as NOT instanceof SourceEditorDocument");
0268:                        }
0269:                        // Be careful with unloading: One only is allowed to unload the leaf,
0270:                        // if it has not been loaded, when this method has started, otherwise we could
0271:                        // possibly unload a leaf, which currently is displayed in the editor, which
0272:                        // would cause the editor to crash soon after this.
0273:                        if (!leafWasLoadedInitially) {
0274:                            leaf.unloadContent(false); // make memory of this available sooner (gc)
0275:                        }
0276:                    } // for
0277:
0278:                    /*
0279:                    long elapsedTime = System.currentTimeMillis() - startTime;
0280:                    Log.Info("cc> elapsedTime= " + elapsedTime );
0281:                    Log.Info("cc> CheckResults: Found " + searchResultsUserObjectVector.size() + " hits.");
0282:                     */
0283:
0284:                    // Close and dipose the progressWindow, if it has been created:
0285:                    if (progressWindow != null) {
0286:                        EventQueue.invokeLater(new Runnable() {
0287:                            public void run() {
0288:                                progressWindow.setVisible(false);
0289:                                progressWindow.dispose();
0290:                            }
0291:                        });
0292:                        // Give Swing some time right now:
0293:                        try {
0294:                            Thread.sleep(88);
0295:                        } catch (Exception e1) {
0296:                        }
0297:                    } // if
0298:
0299:                    // Tell the searchresults tree to display action-entries for the
0300:                    // found results, if some were found:
0301:                    if (searchResultsUserObjectVector.size() > 0) {
0302:                        elementsHaveBeenFound = true;
0303:                        SearchResultsUserObject[] searchResultsUserObjects = new SearchResultsUserObject[searchResultsUserObjectVector
0304:                                .size()];
0305:                        searchResultsUserObjectVector
0306:                                .copyInto(searchResultsUserObjects);
0307:                        this .projectFrame
0308:                                .setSearchResultsTreeContentWithObjectSearchResults(
0309:                                        searchName, searchResultsUserObjects);
0310:                    } else {
0311:                        String title = Language
0312:                                .Translate("Object Search Results");
0313:                        String message = Language
0314:                                .Translate("The object search hasn't found any results.");
0315:                        JOptionPane
0316:                                .showMessageDialog(this .projectFrame, message,
0317:                                        title, JOptionPane.INFORMATION_MESSAGE);
0318:                    }
0319:                    classReferences.setSize(0); // GC assistance
0320:                } // if th search has not been cancelled by the user
0321:                else {
0322:                    // Close and dipose the progressWindow, if it has been created:
0323:                    if (progressWindow != null) {
0324:                        EventQueue.invokeLater(new Runnable() {
0325:                            public void run() {
0326:                                progressWindow.setVisible(false);
0327:                                progressWindow.dispose();
0328:                            }
0329:                        });
0330:                        // Give Swing some time right now:
0331:                        try {
0332:                            Thread.sleep(88);
0333:                        } catch (Exception e1) {
0334:                        }
0335:                    } // if
0336:                } // else
0337:
0338:                //ystem.out.println("cc> search_Class_Usage_Locations_In_Thread ends.");
0339:
0340:                return elementsHaveBeenFound;
0341:            } // searchClassUsageLocations_InThread
0342:
0343:            /**
0344:             *  Add all found usages of basisFSD anywhere in the project
0345:             *  in ClassReferenceEntry objects to the classReferences vetcor.
0346:             */
0347:            private void searchClassUsageLocationsOf(
0348:                    final FileStructureDescription basisFSD,
0349:                    final Vector classReferences,
0350:                    final FileStructureDescriptionManager fsdManager,
0351:                    final boolean doTrackAttributes,
0352:                    final ProgressWindow progressWindow) {
0353:
0354:                //ystem.out.println("cc> searchClassUsageLocationsOf " +
0355:                //                   basisFSD.fullyQualifiedClassNameBuffer.toString() +
0356:                //                   " starts." );
0357:
0358:                // Search references to classFSD in all classes, which have a dependency
0359:                // to classFSD:
0360:                Vector dependentFSDs = new Vector();
0361:                // Add all files, which depend from the basisFSD
0362:                // and any project class and its dependent classes in the parent chain:
0363:                this .addAllFSDsWhichDependFrom(basisFSD, dependentFSDs,
0364:                        fsdManager);
0365:
0366:                //ystem.out.println("cc> searchClassUsageLocationsOf: " +
0367:                //                   dependentFSDs.size() +
0368:                //                   " dependent classes have been found." );
0369:
0370:                // Parse each class of the dependentFSDs and examine the java tree:
0371:                FileStructureDescriptionParserTreePostProcessor postProcessor = new FileStructureDescriptionParserTreePostProcessor(
0372:                        fsdManager);
0373:
0374:                if (progressWindow != null) {
0375:                    progressWindow.setProgressMaxValue(dependentFSDs.size());
0376:                }
0377:
0378:                if (!this .searchHasBeenCancelledByTheUser) {
0379:                    // Fill all hits into ClassReferenceEntry objects and add them to this vector:
0380:                    for (int fsdIndex = 0; fsdIndex < dependentFSDs.size(); fsdIndex++) {
0381:
0382:                        if (progressWindow != null) {
0383:                            final int progressValue = fsdIndex;
0384:                            EventQueue.invokeLater(new Runnable() {
0385:                                public void run() {
0386:                                    progressWindow
0387:                                            .setProgressValue(progressValue);
0388:                                }
0389:                            });
0390:                            // Break the search, if the user has pushed the cancel button:
0391:                            if (progressWindow.getWasCancelled()) {
0392:                                searchHasBeenCancelledByTheUser = true;
0393:                                break;
0394:                            }
0395:                            try {
0396:                                Thread.yield();
0397:                            } catch (Exception e234986) {
0398:                            }
0399:                        }
0400:
0401:                        final FileStructureDescription candidateFSD = (FileStructureDescription) dependentFSDs
0402:                                .elementAt(fsdIndex);
0403:                        // Get the associated source text (can be from java files or from jar archives)
0404:                        final StringBuffer candidateSourceCode = fsdManager
0405:                                .getJavaSourceForFSD(candidateFSD);
0406:                        // Get the full parser tree:
0407:                        final ParserTreeNode compilationUnitNode = this 
0408:                                .getCompilationUnitNodeFor(
0409:                                        candidateSourceCode,
0410:                                        candidateFSD.fullyQualifiedClassNameBuffer
0411:                                                .toString());
0412:                        // For the following scan, the fsd must have the local fields, which usually only
0413:                        // are parsed for fsd's of sources, which are going to be displayed in the source editor.
0414:                        // This actions here are made for many fsd's, which of course are not displayed in
0415:                        // the editor, so we have to update them to have the local fields information:
0416:                        // Note the two flags:
0417:                        // create local fields = true ( as mentionned above )
0418:                        // call dependency scanner = true : Because the dependency fields are cleared
0419:                        //                                  by the postProcessor, the dependencies
0420:                        //                                  ALWAYS must be recalculated.
0421:                        //                                  Because the postprocessor stores
0422:                        //                                  the compilationrootnode and the fsd in the entries
0423:                        //                                  sent to the dependency updater, this doesn't
0424:                        //                                  cost much time:
0425:                        // This all is done on the same fsd reference.
0426:                        postProcessor.updatePostProcessParserTree(candidateFSD,
0427:                                candidateFSD.belongsToProject,
0428:                                compilationUnitNode,
0429:                                candidateFSD.pathNameBuffer.toString(), true, /*create local fields*/
0430:                                true /*call dependency scanner*/);
0431:                        // Now deepscan the tree for finding locations where an object of class given by
0432:                        // the basisFSD is created or explicitly used in objects or in cast expressions.
0433:                        this .scanForClassUsage(candidateFSD,
0434:                                compilationUnitNode,
0435:                                basisFSD.fullyQualifiedClassNameBuffer
0436:                                        .toString(), classReferences,
0437:                                doTrackAttributes);
0438:                    } // for fsdIndex
0439:                } // if
0440:
0441:                //ystem.out.println("cc> searchClassUsageLocationsOf " +
0442:                //                   basisFSD.fullyQualifiedClassNameBuffer.toString() +
0443:                //                   " ends." );
0444:
0445:            } // searchClassUsageLocationsOf
0446:
0447:            /**
0448:             *   Scan the javaCCBasisNode (created from the candidateFSD)
0449:             *   for object creation of a class given by
0450:             *   searchedFullyQualifiedClassName, or declaration of attributes or
0451:             *   explicit type casts of this class.
0452:             *   Each found location is passed to a ClassReferenceEntry object
0453:             *   and added to the classReferences vector.
0454:             */
0455:            private void scanForClassUsage(
0456:                    final FileStructureDescription candidateFSD,
0457:                    final DefaultMutableTreeNode javaCCBasisNode,
0458:                    final String searchedFullyQualifiedClassName,
0459:                    final Vector classReferences,
0460:                    final boolean doTrackAttributes) {
0461:
0462:                //ystem.out.println("cc> scanForClassUsage for " +
0463:                //                   candidateFSD.fullyQualifiedClassNameBuffer.toString() +
0464:                //                   " starts." );
0465:
0466:                // This here really is very easy:
0467:                // Just deepscan for ClassOrInterfaceType nodes and compare
0468:                // the contained identifier leaf. This will catch all
0469:                // occurences in method parameters, typecasts, attribute assignments..
0470:
0471:                // A work vector for the loop:
0472:                Vector workTargetVector = new Vector();
0473:
0474:                // The basisNode = CompilationUnit isn't interesting, so get its children :
0475:                final DefaultMutableTreeNode[] basisNodeChildren = this 
0476:                        .getChildren(javaCCBasisNode);
0477:                for (int basisNodeIndex = 0; basisNodeIndex < basisNodeChildren.length; basisNodeIndex++) {
0478:                    // Nodes have String user objects:
0479:                    final DefaultMutableTreeNode this Child = basisNodeChildren[basisNodeIndex];
0480:                    final Object userObject = this Child.getUserObject();
0481:                    if (userObject instanceof  Integer) {
0482:                        // Integer reference comparison is ok here.
0483:                        if ((Integer) userObject == ParserOutputProcessor.NodeForTypeDeclaration) {
0484:                            // Get the ClassDeclaration children:
0485:                            DefaultMutableTreeNode[] classDeclarationNodes = this 
0486:                                    .getAllChildNodesWithName(
0487:                                            this Child,
0488:                                            ParserOutputProcessor.NodeForClassOrInterfaceDeclaration);
0489:                            for (int classDecIndex = 0; classDecIndex < classDeclarationNodes.length; classDecIndex++) {
0490:                                // Get the ClassBody node children:
0491:                                DefaultMutableTreeNode[] classBodyNodes = this 
0492:                                        .getAllChildNodesWithName(
0493:                                                classDeclarationNodes[classDecIndex],
0494:                                                ParserOutputProcessor.NodeForClassOrInterfaceBody);
0495:                                for (int classBodyIndex = 0; classBodyIndex < classBodyNodes.length; classBodyIndex++) {
0496:                                    // Get the ClassBodyDeclaration node children:
0497:                                    DefaultMutableTreeNode[] classBodyDeclarationNodes = this 
0498:                                            .getAllChildNodesWithName(
0499:                                                    classBodyNodes[classBodyIndex],
0500:                                                    ParserOutputProcessor.NodeForClassOrInterfaceBodyDeclaration);
0501:                                    for (int classBodyDeclarationIndex = 0; classBodyDeclarationIndex < classBodyDeclarationNodes.length; classBodyDeclarationIndex++) {
0502:                                        // The children of the classBodyDeclarationNodes are
0503:                                        // FieldDeclaration, ConstructorDeclaration or MethodDeclaration nodes.
0504:                                        final DefaultMutableTreeNode cbdNode = classBodyDeclarationNodes[classBodyDeclarationIndex];
0505:                                        this 
0506:                                                .deepScanForClassIdentifierOccurences(
0507:                                                        candidateFSD,
0508:                                                        classReferences,
0509:                                                        cbdNode,
0510:                                                        searchedFullyQualifiedClassName,
0511:                                                        workTargetVector);
0512:                                    }
0513:                                }
0514:                            } // for classDecIndex
0515:                        } // if
0516:                    } // if
0517:                } // for basisNodeIndex
0518:
0519:                // Optionally track all ( member and local ) attributes of this class.
0520:                // This again is simple: Just use the member and localblock attribute vectors
0521:                // of the candidate fsd, which has been processed with localfields for this
0522:                // purpose before:
0523:                if (doTrackAttributes) {
0524:                    // Track attributes of the cadidateFSD and
0525:                    // recur over all nested and anonymous classes.
0526:                    // For this initial call, candidateFSD also is the toplevel fsd,
0527:                    // therefore it occurs twice. When the called method calls itself
0528:                    // during recursion, this won't be the case anymore.
0529:                    this .addAttributesForClassSearchForFSD(candidateFSD,
0530:                            javaCCBasisNode, candidateFSD,
0531:                            searchedFullyQualifiedClassName, classReferences);
0532:                } // if doTrackAttributes
0533:
0534:                //ystem.out.println("cc> scanForClassUsage for " +
0535:                //                   candidateFSD.fullyQualifiedClassNameBuffer.toString() +
0536:                //                   " has ended." );
0537:
0538:            } // scanForClassUsageOf
0539:
0540:            /**
0541:             *  Recursive method: Adds attributes for classsearches over this
0542:             *  fsd and recurs over nested and anonymous classes:
0543:             */
0544:            private void addAttributesForClassSearchForFSD(
0545:                    final FileStructureDescription topLevelFSD,
0546:                    final DefaultMutableTreeNode topLevelJavaCCBasisNode,
0547:                    final FileStructureDescription candidateFSD,
0548:                    final String searchedFullyQualifiedClassName,
0549:                    final Vector classReferences) {
0550:                String globalScopeType = (topLevelFSD == candidateFSD) ? "toplevel"
0551:                        : "nested";
0552:                // Process the passed fsd:
0553:                this .addAttributesForClassSearch(topLevelFSD,
0554:                        topLevelJavaCCBasisNode,
0555:                        candidateFSD.fieldDescriptions, globalScopeType
0556:                                + " member", searchedFullyQualifiedClassName,
0557:                        classReferences);
0558:                this .addAttributesForClassSearch(topLevelFSD,
0559:                        topLevelJavaCCBasisNode,
0560:                        candidateFSD.localBlockFieldDescriptions,
0561:                        globalScopeType + " local",
0562:                        searchedFullyQualifiedClassName, classReferences);
0563:                // and recur over
0564:                // 1) nested fsd's of the passed candidateFSD :
0565:                for (int i = 0; i < candidateFSD.innerClasses.size(); i++) {
0566:                    final FileStructureDescription innerClassFSD = (FileStructureDescription) candidateFSD.innerClasses
0567:                            .elementAt(i);
0568:                    this .addAttributesForClassSearchForFSD(topLevelFSD,
0569:                            topLevelJavaCCBasisNode, innerClassFSD,
0570:                            searchedFullyQualifiedClassName, classReferences);
0571:                } // for
0572:                // 2. anonymous fsd's  of the passed candidateFSD :
0573:                for (int i = 0; i < candidateFSD.localBlockAnonymousClasses
0574:                        .size(); i++) {
0575:                    final FileStructureDescription anonymousClassFSD = (FileStructureDescription) candidateFSD.localBlockAnonymousClasses
0576:                            .elementAt(i);
0577:                    this .addAttributesForClassSearchForFSD(topLevelFSD,
0578:                            topLevelJavaCCBasisNode, anonymousClassFSD,
0579:                            searchedFullyQualifiedClassName, classReferences);
0580:                } // for
0581:            } // addAttributesForClassSearch
0582:
0583:            private void addAttributesForClassSearch(
0584:                    final FileStructureDescription topLevelFSD,
0585:                    final DefaultMutableTreeNode topLevelJavaCCBasisNode,
0586:                    final Vector fields, // members or local ones
0587:                    final String scopeType, // associated text for inserting
0588:                    final String searchedFullyQualifiedClassName,
0589:                    final Vector classReferences) {
0590:                // work vector reference for the attribute searches:
0591:                Vector attributeSearchReferences = new Vector();
0592:                // The topLevelFSD is used for combining class identifiers
0593:                // with importstatements.
0594:                for (int i = 0; i < fields.size(); i++) {
0595:                    final FileStructureDescriptionForField fieldFSD = (FileStructureDescriptionForField) fields
0596:                            .elementAt(i);
0597:                    if (!fieldFSD.isPrimitiveType) {
0598:                        final String localQualifier = fieldFSD
0599:                                .getFullyQualifiedClassName(false);
0600:                        final String[] inScopePossibleIdentifiers = CodeCompletionUtilities
0601:                                .CreatePossibleQualifiedClassIdentifiers(
0602:                                        topLevelFSD, localQualifier.toString());
0603:                        boolean found = false;
0604:                        for (int p = 0; p < inScopePossibleIdentifiers.length; p++) {
0605:                            if (inScopePossibleIdentifiers[p]
0606:                                    .equals(searchedFullyQualifiedClassName)) {
0607:                                found = true;
0608:                                break;
0609:                            }
0610:                        }
0611:                        if (found) {
0612:                            // Make an attribute search for this field and pass the line, where
0613:                            // this attribute is defined, so one always is inscope:
0614:                            attributeSearchReferences.setSize(0);
0615:                            // Caution: We already are in a ThreadEngine Thread Context,
0616:                            //          and we ONLY want the attribute search inside the
0617:                            //          topLevelFSD, therefore use scanForFieldCallsOf(): 
0618:                            this .scanForFieldCallsOf(topLevelFSD,
0619:                                    topLevelJavaCCBasisNode,
0620:                                    fieldFSD.objectNameWithPosition.content,
0621:                                    attributeSearchReferences);
0622:
0623:                            // Convert the found FieldReferenceEntry elements into
0624:                            // ClassReferenceEntry elements for this class search :
0625:                            for (int k = 0; k < attributeSearchReferences
0626:                                    .size(); k++) {
0627:                                final FieldReferenceEntry fieldRef = (FieldReferenceEntry) attributeSearchReferences
0628:                                        .elementAt(k);
0629:                                final ClassReferenceEntry entry = new ClassReferenceEntry(
0630:                                        topLevelFSD, scopeType + " "
0631:                                                + fieldRef.getFieldName(),
0632:                                        fieldRef.getStartLine(), fieldRef
0633:                                                .getStartColumn(), fieldRef
0634:                                                .getEndLine(), fieldRef
0635:                                                .getEndColumn());
0636:                                classReferences.addElement(entry);
0637:                            } // for k
0638:                            attributeSearchReferences.setSize(0);
0639:                        }
0640:                    } // if
0641:                } // for
0642:            } // addAttributesForClassSearch
0643:
0644:            private void deepScanForClassIdentifierOccurences(
0645:                    final FileStructureDescription candidateFSD,
0646:                    final Vector classReferences,
0647:                    final DefaultMutableTreeNode cbdNode,
0648:                    final String searchedFullyQualifiedClassName,
0649:                    final Vector workTargetVector) {
0650:                // 1 of 2: Search the identifier leafs of all ClassOrInterfaceType nodes:
0651:                //         This gets all declarations and casts.
0652:                //
0653:                // Reset the work vector and fill it with all found ClassOrInterfaceType nodes:
0654:                workTargetVector.setSize(0);
0655:                this 
0656:                        .deepScanForNodesWithName(
0657:                                workTargetVector,
0658:                                cbdNode,
0659:                                ParserOutputProcessor.NodeForClassOrInterfaceType,
0660:                                true);
0661:                DefaultMutableTreeNode workNode;
0662:                String localQualifier;
0663:                for (int i = 0; i < workTargetVector.size(); i++) {
0664:                    // Get the identifier leaf content from this ClassOrInterfaceType node:
0665:                    // Search and return the leaf with kind = <IDENTIFIER> : ( = class identifier )
0666:                    workNode = (DefaultMutableTreeNode) workTargetVector
0667:                            .elementAt(i);
0668:                    final TokenTreeUserObject classNameLeaf = this 
0669:                            .getChildLeafOfKind(workNode, "<IDENTIFIER>");
0670:                    if (classNameLeaf != null) {
0671:                        localQualifier = classNameLeaf.getContent();
0672:                        // However the identifiers found in the javacc tree can be non qualified
0673:                        // or partially qualified, so one must compare against all combinations
0674:                        // of possible import wildcards and also take complete import statements
0675:                        // without wildcards into account:
0676:                        final String[] inScopePossibleIdentifiers = CodeCompletionUtilities
0677:                                .CreatePossibleQualifiedClassIdentifiers(
0678:                                        candidateFSD, localQualifier);
0679:                        boolean found = false;
0680:                        for (int p = 0; p < inScopePossibleIdentifiers.length; p++) {
0681:                            if (inScopePossibleIdentifiers[p]
0682:                                    .equals(searchedFullyQualifiedClassName)) {
0683:                                found = true;
0684:                                break;
0685:                            }
0686:                        }
0687:                        if (found) {
0688:                            ClassReferenceEntry entry = new ClassReferenceEntry(
0689:                                    candidateFSD, new String(localQualifier),
0690:                                    classNameLeaf.getStartLine(), classNameLeaf
0691:                                            .getStartColumn(), classNameLeaf
0692:                                            .getEndLine(), classNameLeaf
0693:                                            .getEndColumn());
0694:                            classReferences.addElement(entry);
0695:                        }
0696:                    } // if
0697:                } // for
0698:                workTargetVector.setSize(0);
0699:                //
0700:                // 2 of 2 :
0701:                // Search occurences of the searchedFullyQualifiedClassName in
0702:                // name node leaf identifiers.
0703:                // For this purpose, one needs the first identifier leaf content of the name
0704:                // node and the concatenation of all following leafs of the name node.
0705:                // The first identifier is combined with all possible import statements
0706:                // and the concatenation of the following leafs is appended.
0707:                // If one of these starts with the searchedFullyQualifiedClassName,
0708:                // one has found a match [f.ex. a call of a public static method inside a method block]
0709:                workTargetVector.setSize(0);
0710:                this .deepScanForNodesWithName(workTargetVector, cbdNode,
0711:                        ParserOutputProcessor.NodeForName, true);
0712:                for (int i = 0; i < workTargetVector.size(); i++) {
0713:                    workNode = (DefaultMutableTreeNode) workTargetVector
0714:                            .elementAt(i);
0715:                    // Take the first identifier:
0716:                    final TokenTreeUserObject firstIdentifierLeaf = this 
0717:                            .getChildLeafOfKind(workNode, "<IDENTIFIER>");
0718:                    // and the concatenation of all:
0719:                    final StringWithPosition completeLine = this 
0720:                            .concatenateLeafContentsOf(workNode);
0721:
0722:                    if ((firstIdentifierLeaf != null) && (completeLine != null)) {
0723:                        boolean found = false;
0724:                        // If the completeLine starts with the searchedFullyQualifiedClassName
0725:                        // we have a match. The identifier is adressed absolutely in this case:
0726:                        if (completeLine.content
0727:                                .startsWith(searchedFullyQualifiedClassName)) {
0728:                            found = true;
0729:                        } else {
0730:                            String firstIdentifier = firstIdentifierLeaf
0731:                                    .getContent();
0732:                            // Combine this one with all import statement combinations:
0733:                            final String[] inScopePossibleIdentifiers = CodeCompletionUtilities
0734:                                    .CreatePossibleQualifiedClassIdentifiers(
0735:                                            candidateFSD, firstIdentifier);
0736:                            for (int p = 0; p < inScopePossibleIdentifiers.length; p++) {
0737:                                if (inScopePossibleIdentifiers[p]
0738:                                        .equals(searchedFullyQualifiedClassName)) {
0739:                                    found = true;
0740:                                    break;
0741:                                }
0742:                            }
0743:                        } // else
0744:                        if (found) {
0745:                            ClassReferenceEntry entry = new ClassReferenceEntry(
0746:                                    candidateFSD, new String(
0747:                                            firstIdentifierLeaf.getContent()),
0748:                                    firstIdentifierLeaf.getStartLine(),
0749:                                    firstIdentifierLeaf.getStartColumn(),
0750:                                    firstIdentifierLeaf.getEndLine(),
0751:                                    firstIdentifierLeaf.getEndColumn());
0752:                            classReferences.addElement(entry);
0753:                        }
0754:                    } // if
0755:                } // for
0756:                workTargetVector.setSize(0);
0757:            } // deepScanForClassIdentifierOccurences
0758:
0759:            /**
0760:             *  Returns the (first) leaf of the passed kind.
0761:             */
0762:            private TokenTreeUserObject getChildLeafOfKind(
0763:                    final DefaultMutableTreeNode parentNode,
0764:                    final String leafKind) {
0765:                final DefaultMutableTreeNode[] allChildren = this 
0766:                        .getChildren(parentNode);
0767:                TokenTreeUserObject foundLeaf = null;
0768:                for (int i = 0; i < allChildren.length; i++) {
0769:                    final DefaultMutableTreeNode this Child = allChildren[i];
0770:                    if (this Child.getUserObject() instanceof  TokenTreeUserObject) {
0771:                        final TokenTreeUserObject this UserObject = (TokenTreeUserObject) this Child
0772:                                .getUserObject();
0773:                        if (this UserObject.getKind().equals(leafKind)) {
0774:                            foundLeaf = this UserObject;
0775:                            break;
0776:                        }
0777:                    }
0778:                }
0779:                return foundLeaf;
0780:            }
0781:
0782:            /**
0783:             *  Takes all children of the passed node, and concatenates
0784:             *  all contents of the ones which are leafs to the content
0785:             *  of a StringWithPosition object.
0786:             *  Positioning numbers also are set.
0787:             */
0788:            private StringWithPosition concatenateLeafContentsOf(
0789:                    final DefaultMutableTreeNode node) {
0790:                final DefaultMutableTreeNode[] children = this 
0791:                        .getChildren(node);
0792:                final StringBuffer contents = new StringBuffer();
0793:                int startLine = -1;
0794:                int startColumn = -1;
0795:                int endLine = -1;
0796:                int endColumn = -1;
0797:                for (int i = 0; i < children.length; i++) {
0798:                    if (children[i].getUserObject() instanceof  TokenTreeUserObject) {
0799:                        final TokenTreeUserObject tokenContent = (TokenTreeUserObject) children[i]
0800:                                .getUserObject();
0801:                        contents.append(tokenContent.getContent());
0802:                        if (startLine == -1) // it hasn't been set yet
0803:                        {
0804:                            startLine = tokenContent.getStartLine();
0805:                            startColumn = tokenContent.getStartColumn();
0806:                        } else // start has been set, so extend the other side
0807:                        {
0808:                            endLine = tokenContent.getEndLine();
0809:                            endColumn = tokenContent.getEndColumn();
0810:                        }
0811:                    }
0812:                } // for
0813:                return new StringWithPosition(contents.toString(), startLine,
0814:                        startColumn, endLine, endColumn);
0815:            } // concatenateLeafContentsOf
0816:
0817:            /**
0818:             *  Search all locations everywhere (= in the src, additional libs and the whole project),
0819:             *  where the method given by the passed methodFSD inside the methodParentFSD inside the
0820:             *  topLevelSourceFileFSD is called.
0821:             *
0822:             *  The methodParentTree in all cases is the fsd which contains the methodfsd.
0823:             *
0824:             *  If the method is toplevel, methodParentFSD equals topLevelSourceFileFSD.
0825:             *
0826:             *  topLevelSourceFileFSD = the fsd, containing the passed methodfsd directly or
0827:             *  somewhere in its innerclasses or innerinterfaces tree, and:
0828:             *  topLevelSourceFileFSD is 1:1 related to the associated sourcefile.
0829:             *
0830:             */
0831:            public void searchMethodUsageLocationsFor(
0832:                    final SearchMethodFSDResult methodFSDResult,
0833:                    final FileStructureDescription[] selectedTargetFSDs) {
0834:                // Wait until the other popups have goone, so the
0835:                // way is cleared for a new progresswindow:
0836:                EventQueue.invokeLater(new Runnable() {
0837:                    public void run() {
0838:                        // We must call the dependencies updater and tell it to process all
0839:                        // pending entries. For this and other reasons, we must process this
0840:                        // in a user thread, otherwise one could produce deadlocks:
0841:                        Runnable searchRunnable = new Runnable() {
0842:                            public void run() {
0843:                                // Give Swing some time right now (to show the progressWindow):
0844:                                //try{ Thread.sleep(1199); } catch( Exception e2 ){}
0845:                                searchMethodUsageLocations_InThread(
0846:                                        methodFSDResult, selectedTargetFSDs);
0847:                            }
0848:                        };
0849:                        ThreadEngine.getInstance().addRunnable(searchRunnable,
0850:                                "searchMethodUsageLocationsFor");
0851:                    }
0852:                });
0853:            } // searchMethodUsageLocationsFor
0854:
0855:            /**
0856:             *  Carried out in a user thread, called by searchMethodUsageLocationsFor() above.
0857:             */
0858:            private void searchMethodUsageLocations_InThread(
0859:                    final SearchMethodFSDResult methodFSDResult,
0860:                    final FileStructureDescription[] selectedTargetFSDs) {
0861:                searchHasBeenCancelledByTheUser = false; // initialize
0862:                String searchName = "Method"; // is displayed as tab title in the search results panel
0863:                // Make sure, the searchresults tree displays some useful information
0864:                // while the search is running, and reset it, if the search didn't find anything.
0865:                this .projectFrame.initializeSearchResults(searchName,
0866:                        searchMessage);
0867:                // Give Swing some time right now:
0868:                try {
0869:                    Thread.sleep(44);
0870:                } catch (Exception e0) {
0871:                }
0872:                // Call the actual worker method:
0873:                boolean elementsHaveBeenFound = this 
0874:                        .search_Method_Usage_Locations_In_Thread(searchName,
0875:                                methodFSDResult, selectedTargetFSDs);
0876:                if (!elementsHaveBeenFound) {
0877:                    // Signalize it's ready for new searches:
0878:                    this .projectFrame.initializeSearchResults(searchName,
0879:                            Language.Translate("No hits"));
0880:                    // Give Swing some time right now:
0881:                    try {
0882:                        Thread.sleep(44);
0883:                    } catch (Exception e2) {
0884:                    }
0885:                }
0886:            } // searchMethodUsageLocations_InThread
0887:
0888:            private boolean search_Method_Usage_Locations_In_Thread(
0889:                    final String searchName,
0890:                    final SearchMethodFSDResult methodFSDResult,
0891:                    final FileStructureDescription[] selectedTargetFSDs) {
0892:                boolean elementsHaveBeenFound = false;
0893:                long startTime = System.currentTimeMillis();
0894:                String methodName = methodFSDResult.fsd.name.content;
0895:                // Make the progressWindow and show it, if the search
0896:                // has package or global scope, otherwise the search is so fast,
0897:                // that the progressWindow is not needed:
0898:                ProgressWindow progressWindowCandidate = null;
0899:                if (!methodFSDResult.fsd.isPrivate()) {
0900:                    String windowText = searchMessage + "\n"
0901:                            + searchInfoMessage;
0902:                    progressWindowCandidate = new ProgressWindow(windowText,
0903:                            null, projectFrame.getParentFrameForChildren(),
0904:                            projectFrame.getMainFrameProvider(), true);
0905:                    progressWindowCandidate.showCentered();
0906:                }
0907:                final ProgressWindow progressWindow = progressWindowCandidate;
0908:
0909:                FileStructureDescriptionManager fsdManager = this .projectFrame
0910:                        .getFileStructureDescriptionManager();
0911:                // We need the file dependencies list to be complete, so tell the
0912:                // dependencies updater to process all pending entries right now.
0913:                // The pc must be in a user thread context for this.
0914:                fsdManager.waitForUpdaters();
0915:
0916:                // Make the set of possible files to be searched smaller by useing
0917:                // the visibility of the method. If parentfsd's and interfaces are selected to,
0918:                // we still can use the leaf method visibility for all, because it's the
0919:                // biggest visibility.
0920:                Vector dependentFSDs = new Vector();
0921:                if (methodFSDResult.fsd.isPrivate()) {
0922:                    // The method is private, so we only have to search in
0923:                    // the basis FSD, which contains that method.
0924:                    // Nothing to do with the selectedTargetFSDs here (These contain
0925:                    // the methodFSDResult.basisFSD, possibly as the only element)
0926:                    dependentFSDs.addElement(methodFSDResult.basisFSD);
0927:                } else if (methodFSDResult.fsd.isPackageScope()) {
0928:                    // First add all files, which depend from the basisFSD
0929:                    // and any project class and its dependent classes in the parent chain:
0930:                    for (int k = 0; k < selectedTargetFSDs.length; k++) {
0931:                        this .addAllFSDsWhichDependFrom(selectedTargetFSDs[k],
0932:                                dependentFSDs, fsdManager);
0933:                    } // for k
0934:                    // but then exclude all, which are not in the same package:
0935:                    int exIndex = 0;
0936:                    FileStructureDescription workFSD = null;
0937:                    final String basisPackageName = methodFSDResult.basisFSD.packageName.content;
0938:                    if (basisPackageName.length() > 0) {
0939:                        while (exIndex < dependentFSDs.size()) {
0940:                            workFSD = (FileStructureDescription) dependentFSDs
0941:                                    .elementAt(exIndex);
0942:                            if (workFSD.packageName.content
0943:                                    .startsWith(basisPackageName)) {
0944:                                exIndex++; // ok proceed
0945:                            } else {
0946:                                dependentFSDs.removeElementAt(exIndex); // remove it
0947:                            }
0948:                        } // while
0949:                    } // if
0950:                } else {
0951:                    // Add all files, which depend from the basisFSD
0952:                    // and any project class and its dependent classes in the parent chain:
0953:                    for (int k = 0; k < selectedTargetFSDs.length; k++) {
0954:                        this .addAllFSDsWhichDependFrom(selectedTargetFSDs[k],
0955:                                dependentFSDs, fsdManager);
0956:                    }
0957:                } //else
0958:                //
0959:                // Jedes File in der obigen Liste muss auf Block parsernode level durchsucht werden
0960:                // nach relativen oder absoluten Referenzen der Basisklasse und dann nach
0961:                // expliziten Methodenaufrufen der obigen Zielmethode.
0962:                //
0963:                // Zunächst lasse ich die Vererbung beiseite und beruecksichtige nur
0964:                // Toplevel-Instanzen mit dynamischen oder statischen Methoden
0965:                // also folgende zwei Formen:
0966:                // instance.dynamicMethod( ... )   oder   Class.StaticMethod( ... )
0967:                //
0968:                // instance oder Class konnen relativ oder qualifiziert sein.
0969:                //
0970:                // instance kann Member Attribut oder lokale Variable sein.
0971:                //
0972:                // Zusätzlich sind auch "verdeckte" Calls möglich:
0973:                //
0974:                // anotherClassInstance.getMyInstance().dynamicMethod().sayHello()
0975:                //
0976:                //
0977:                FileStructureDescriptionParserTreePostProcessor postProcessor = new FileStructureDescriptionParserTreePostProcessor(
0978:                        fsdManager);
0979:                // Fill all hits into ClassReferenceEntry objects and add them to this vector:
0980:                Vector classReferences = new Vector();
0981:                if (progressWindow != null) {
0982:                    progressWindow.setProgressMaxValue(dependentFSDs.size());
0983:                }
0984:                for (int fsdIndex = 0; fsdIndex < dependentFSDs.size(); fsdIndex++) {
0985:                    if (progressWindow != null) {
0986:                        final int progressValue = fsdIndex;
0987:                        EventQueue.invokeLater(new Runnable() {
0988:                            public void run() {
0989:                                progressWindow.setProgressValue(progressValue);
0990:                            }
0991:                        });
0992:                        // Break the search, if the user has pushed the cancel button:
0993:                        if (progressWindow.getWasCancelled()) {
0994:                            searchHasBeenCancelledByTheUser = true;
0995:                            break;
0996:                        }
0997:                        try {
0998:                            Thread.yield();
0999:                        } catch (Exception e234986) {
1000:                        }
1001:                    }
1002:                    final FileStructureDescription candidateFSD = (FileStructureDescription) dependentFSDs
1003:                            .elementAt(fsdIndex);
1004:                    // Get the associated source text (can be from java files or from jar archives)
1005:                    final StringBuffer candidateSourceCode = fsdManager
1006:                            .getJavaSourceForFSD(candidateFSD);
1007:                    // Get the full parser tree:
1008:                    final ParserTreeNode compilationUnitNode = this 
1009:                            .getCompilationUnitNodeFor(candidateSourceCode,
1010:                                    candidateFSD.fullyQualifiedClassNameBuffer
1011:                                            .toString());
1012:                    // For the following scan, the fsd must have the local fields, which usually only
1013:                    // are parsed for fsd's of sources, which are going to be displayed in the source editor.
1014:                    // This actions here are made for many fsd's, which of course are not displayed in
1015:                    // the editor, so we have to update them to have the local fields information:
1016:                    // Note the two flags:
1017:                    // create local fields = true ( as mentionned above )
1018:                    // call dependency scanner = true : Because the dependency fields are cleared
1019:                    //                                  by the postProcessor, the dependencies
1020:                    //                                  ALWAYS must be recalculated.
1021:                    //                                  Because the postprocessor stores
1022:                    //                                  the compilationrootnode and the fsd in the entries
1023:                    //                                  sent to the dependency updater, this doesn't
1024:                    //                                  cost much time:
1025:                    // This all is done on the same fsd reference.
1026:                    postProcessor.updatePostProcessParserTree(candidateFSD,
1027:                            candidateFSD.belongsToProject, compilationUnitNode,
1028:                            candidateFSD.pathNameBuffer.toString(), true, /* create local fields */
1029:                            true /* call dependency scanner */);
1030:                    // Now deepscan the tree for occurences of calls of the searched method:
1031:                    // For any found location (defined by the line and column numbers) we do the same
1032:                    // like done, when the declaration of the method is searched and see, if we
1033:                    // land in the targetFSD or not. If we do land in the targetFSD, a call location
1034:                    // has been found.
1035:                    this .scanForMethodCallsOf(candidateFSD,
1036:                            compilationUnitNode, methodName, classReferences);
1037:                } // for
1038:
1039:                if (!this .searchHasBeenCancelledByTheUser) {
1040:                    // Not absolutely required, but more secure, because at least the queue of the
1041:                    // dependency updater will contain some entries: Force to perform all pending
1042:                    // entries again:
1043:                    fsdManager.waitForUpdaters();
1044:                    // If the "jump to declaration" procedure returns the methodFSDResult.basisFSD,
1045:                    // one can add a jump-to-method-call action to the searchresults tree:
1046:                    Vector searchResultsUserObjectVector = new Vector();
1047:                    for (int i = 0; i < classReferences.size(); i++) {
1048:                        final MethodReferenceEntry entry = (MethodReferenceEntry) classReferences
1049:                                .elementAt(i);
1050:                        // We need the SourceEditorDocument:
1051:                        EditableLeafObject leaf = fsdManager
1052:                                .getJavaSourceEditorLeafForFSD(entry
1053:                                        .getClassDescription());
1054:                        // On leaf level, one should unload the content, after having loaded and processed it.
1055:                        // But one shouldn't unload it, if it already was loaded by another one, when this method starts.
1056:                        // It's not serious, if this doesn't work some times, so no need for synchronization here.
1057:                        boolean leafWasLoadedInitially = leaf.isContentLoaded();
1058:                        Object leafContent = leaf.getContent();
1059:                        if (leafContent instanceof  SourceEditorDocument) {
1060:                            final SourceEditorDocument sourceDoc = (SourceEditorDocument) leafContent;
1061:                            if (this .getIsMethodDeclarationLocatedIn(sourceDoc,
1062:                                    entry, methodFSDResult, selectedTargetFSDs,
1063:                                    fsdManager)) {
1064:                                // Create a SearchResultsFileNodeUserObject and add it to the vector:
1065:                                final int docPosition = sourceDoc
1066:                                        .getPositionOfStartOfLine(entry
1067:                                                .getStartLine() - 1)
1068:                                        + (entry.getStartColumn() + entry
1069:                                                .getEndColumn()) / 2;
1070:                                final boolean breakAtPoints = false;
1071:                                final int[] nearestWordPosition = sourceDoc
1072:                                        .getNearestWordPositionTo(docPosition,
1073:                                                breakAtPoints);
1074:                                final int startOffset = nearestWordPosition[0];
1075:                                final int endOffset = nearestWordPosition[1];
1076:
1077:                                final SearchResultsUserObject resultUserObject = new SearchResultsUserObject(
1078:                                        leaf, entry.getStartLine() - 1,
1079:                                        docPosition, entry.getEndColumn()
1080:                                                - entry.getStartColumn() + 1);
1081:
1082:                                searchResultsUserObjectVector
1083:                                        .addElement(resultUserObject);
1084:                            } // if
1085:                            else {
1086:                                Log
1087:                                        .Info("getIsMethodDeclarationLocatedIn returned false for "
1088:                                                + entry.getClassDescription().fullyQualifiedClassNameBuffer
1089:                                                        .toString());
1090:                            }
1091:                        } // if
1092:                        else {
1093:                            Log
1094:                                    .Error("leafContent as NOT instanceof SourceEditorDocument");
1095:                        }
1096:                        // Be careful with unloading: One only is allowed to unload the leaf,
1097:                        // if it has not been loaded, when this method has started, otherwise we could
1098:                        // possibly unload a leaf, which currently is displayed in the editor, which
1099:                        // would cause the editor to crash soon after this.
1100:                        if (!leafWasLoadedInitially) {
1101:                            leaf.unloadContent(false); // make memory of this available sooner (gc)
1102:                        }
1103:                    } // for
1104:
1105:                    /*
1106:                    long elapsedTime = System.currentTimeMillis() - startTime;
1107:                    Log.Info("elapsedTime= " + elapsedTime );
1108:                    Log.Info("Found " + searchResultsUserObjectVector.size() + " hits.");
1109:                     */
1110:
1111:                    // Close and dipose the progressWindow, if it has been created:
1112:                    if (progressWindow != null) {
1113:                        EventQueue.invokeLater(new Runnable() {
1114:                            public void run() {
1115:                                progressWindow.setVisible(false);
1116:                                progressWindow.dispose();
1117:                            }
1118:                        });
1119:                        // Give Swing some time right now:
1120:                        try {
1121:                            Thread.sleep(88);
1122:                        } catch (Exception e1) {
1123:                        }
1124:                    } // if
1125:
1126:                    // Tell the searchresults tree to display action-entries for the
1127:                    // found results, if some were found:
1128:                    if (searchResultsUserObjectVector.size() > 0) {
1129:                        elementsHaveBeenFound = true;
1130:                        SearchResultsUserObject[] searchResultsUserObjects = new SearchResultsUserObject[searchResultsUserObjectVector
1131:                                .size()];
1132:                        searchResultsUserObjectVector
1133:                                .copyInto(searchResultsUserObjects);
1134:                        this .projectFrame
1135:                                .setSearchResultsTreeContentWithObjectSearchResults(
1136:                                        searchName, searchResultsUserObjects);
1137:                    } else {
1138:                        String title = Language
1139:                                .Translate("Object Search Results");
1140:                        String message = Language
1141:                                .Translate("The object search hasn't found any results.");
1142:                        JOptionPane
1143:                                .showMessageDialog(this .projectFrame, message,
1144:                                        title, JOptionPane.INFORMATION_MESSAGE);
1145:                    }
1146:                    classReferences.setSize(0); // GC assistance
1147:                }
1148:                return elementsHaveBeenFound;
1149:            } // searchMethodUsageLocations_InThread
1150:
1151:            /**
1152:             *  Like searchMethodUsageLocationsFor(), see explanations there.
1153:             *  This one operates on attributes.
1154:             *  The currentFSD and currentLineNumber are required for resolving
1155:             *  LOCAL attribute by scope comparison.
1156:             */
1157:            public void searchFieldUsageLocationsFor(
1158:                    final SearchFieldFSDResult fieldFSDResult,
1159:                    final FileStructureDescription[] selectedTargetFSDs,
1160:                    final FileStructureDescription currentFSD,
1161:                    final int currentLineNumber) {
1162:                // Note: We call the java parser below, which will clear some fields.
1163:                // Especially the field fsd in fieldFSDResult will not survive this and will
1164:                // have some null attributes after this.
1165:                // Therefore we must clone this here:                                        
1166:                fieldFSDResult.fsd = fieldFSDResult.fsd.cloneInstance();
1167:
1168:                //ystem.out.println("SymbolUsageLocationSearch:searchFieldUsageLocationsFor() starts...");
1169:
1170:                final String searchName = "Field"; // is displayed as tab title in the search results panel
1171:
1172:                // Wait until the other popups have goone, so the
1173:                // way is cleared for a new progresswindow:
1174:                EventQueue.invokeLater(new Runnable() {
1175:                    public void run() {
1176:                        // We must call the dependencies updater and tell it to process all
1177:                        // pending entries. For this and other reasons, we must process this
1178:                        // in a user thread, otherwise one could produce deadlocks:
1179:                        Runnable searchRunnable = new Runnable() {
1180:                            public void run() {
1181:                                // Give Swing some time right now (to show the progressWindow):
1182:                                //try{ Thread.sleep(1199); } catch( Exception e2 ){}
1183:                                searchFieldUsageLocations_InThread(searchName,
1184:                                        fieldFSDResult, selectedTargetFSDs,
1185:                                        currentFSD, currentLineNumber);
1186:                            }
1187:                        };
1188:                        ThreadEngine.getInstance().addRunnable(searchRunnable,
1189:                                "searchFieldUsageLocationsFor");
1190:                    }
1191:                });
1192:            } // searchFieldUsageLocationsFor
1193:
1194:            /**
1195:             *  Carried out in a user thread, called by searchFieldUsageLocationsFor() above.
1196:             */
1197:            private void searchFieldUsageLocations_InThread(
1198:                    final String searchName,
1199:                    final SearchFieldFSDResult fieldFSDResult,
1200:                    final FileStructureDescription[] selectedTargetFSDs,
1201:                    final FileStructureDescription currentFSD,
1202:                    final int currentLineNumber) {
1203:                searchHasBeenCancelledByTheUser = false; // initialize
1204:                // Make sure, the searchresults tree displays some useful information
1205:                // while the search is running, and reset it, if the search didn't find anything.
1206:                this .projectFrame.initializeSearchResults(searchName,
1207:                        searchMessage);
1208:                // Give Swing some time right now:
1209:                try {
1210:                    Thread.sleep(44);
1211:                } catch (Exception e0) {
1212:                }
1213:                // Call the actual worker method:
1214:                boolean elementsHaveBeenFound = this 
1215:                        .search_Field_Usage_Locations_In_Thread(searchName,
1216:                                fieldFSDResult, selectedTargetFSDs, currentFSD,
1217:                                currentLineNumber);
1218:                if (!elementsHaveBeenFound) {
1219:                    // Signalize it's ready for new searches:
1220:                    this .projectFrame.initializeSearchResults(searchName,
1221:                            Language.Translate("No hits"));
1222:                    // Give Swing some time right now:
1223:                    try {
1224:                        Thread.sleep(44);
1225:                    } catch (Exception e2) {
1226:                    }
1227:                }
1228:            } // searchFieldUsageLocations_InThread
1229:
1230:            private boolean search_Field_Usage_Locations_In_Thread(
1231:                    final String searchName,
1232:                    SearchFieldFSDResult fieldFSDResult,
1233:                    final FileStructureDescription[] selectedTargetFSDs,
1234:                    final FileStructureDescription currentFSD,
1235:                    final int currentLineNumber) {
1236:                /* Debug:
1237:                Log.Info("qqqq33> AttributeUsageLocationDialog: search_Field_Usage_Locations_In_Thread");
1238:                SearchFieldFSDResult theFieldFSDResult = fieldFSDResult;
1239:                FileStructureDescriptionForField fieldFSD = theFieldFSDResult.fsd;
1240:                Log.Info("qqqq33> fieldFSD.simpleClassName.content " +
1241:                         fieldFSD.simpleClassName.content );
1242:                Log.Info("qqqq33> fieldFSD.objectNameWithPosition.content " +
1243:                         fieldFSD.objectNameWithPosition.content );
1244:                 */
1245:
1246:                boolean elementsHaveBeenFound = false;
1247:                long startTime = System.currentTimeMillis();
1248:                String fieldName = fieldFSDResult.fsd.objectNameWithPosition.content;
1249:                // Make the progressWindow and show it, if the search   
1250:                // has package or global scope, otherwise the search is so fast,
1251:                // that the progressWindow is not needed:
1252:                ProgressWindow progressWindowCandidate = null;
1253:                if (!fieldFSDResult.fsd.isPrivate()) {
1254:                    String windowText = searchMessage + "\n"
1255:                            + searchInfoMessage;
1256:                    progressWindowCandidate = new ProgressWindow(windowText,
1257:                            null, projectFrame.getParentFrameForChildren(),
1258:                            projectFrame.getMainFrameProvider(), true);
1259:                    progressWindowCandidate.showCentered();
1260:                }
1261:                final ProgressWindow progressWindow = progressWindowCandidate;
1262:
1263:                FileStructureDescriptionManager fsdManager = this .projectFrame
1264:                        .getFileStructureDescriptionManager();
1265:                // We need the file dependencies list to be complete, so tell the
1266:                // dependencies updater to process all pending entries right now.
1267:                // The pc must be in a user thread context for this.
1268:                fsdManager.waitForUpdaters();
1269:
1270:                //ystem.out.println(">fs111> SymbolUsageLocationSearch: Search field for " +
1271:                //                   fieldFSDResult.fsd.objectNameWithPosition.content );
1272:
1273:                // Make the set of possible files to be searched smaller by useing
1274:                // the visibility of the field. If parentfsd's and interfaces are selected to,
1275:                // we still can use the leaf method visibility for all, because it's the
1276:                // biggest visibility.
1277:                Vector dependentFSDs = new Vector();
1278:                // Additional case for attributes: For member attributes, the scopeStartLine
1279:                // and scopeEndLine of the field fsd is set both to zero.
1280:                // IF these two parameters are not zero, the attribute isn't a member attribute,
1281:                // but is a LOCAL attribute with scope given by these two values.
1282:                if ((fieldFSDResult.fsd.scopeStartLine > 0)
1283:                        && (fieldFSDResult.fsd.scopeEndLine > 0)) {
1284:
1285:                    //ystem.out.println(">fs> is local");
1286:
1287:                    // In this case, the attribute is LOCAL, so we only have to search in
1288:                    // the basis FSD, which contains that method.
1289:                    // Nothing to do with the selectedTargetFSDs here (These contain
1290:                    // the methodFSDResult.basisFSD, possibly as the only element)
1291:                    dependentFSDs.addElement(fieldFSDResult.basisFSD);
1292:                } else if (fieldFSDResult.fsd.isPrivate()) {
1293:
1294:                    //ystem.out.println(">fs> is private");
1295:
1296:                    // The method is private, so we only have to search in
1297:                    // the basis FSD, which contains that method.
1298:                    // Nothing to do with the selectedTargetFSDs here (These contain
1299:                    // the methodFSDResult.basisFSD, possibly as the only element)
1300:                    dependentFSDs.addElement(fieldFSDResult.basisFSD);
1301:                } else if (fieldFSDResult.fsd.isPackageScope()) {
1302:
1303:                    //ystem.out.println(">fs> has package scope");
1304:
1305:                    // First add all files, which depend from the basisFSD
1306:                    // and any project class and its dependent classes in the parent chain:
1307:                    for (int k = 0; k < selectedTargetFSDs.length; k++) {
1308:                        this .addAllFSDsWhichDependFrom(selectedTargetFSDs[k],
1309:                                dependentFSDs, fsdManager);
1310:                    } // for k
1311:                    // but then exclude all, which are not in the same package:
1312:                    int exIndex = 0;
1313:                    FileStructureDescription workFSD = null;
1314:                    final String basisPackageName = fieldFSDResult.basisFSD.packageName.content;
1315:                    if (basisPackageName.length() > 0) {
1316:                        while (exIndex < dependentFSDs.size()) {
1317:                            workFSD = (FileStructureDescription) dependentFSDs
1318:                                    .elementAt(exIndex);
1319:                            if (workFSD.packageName.content
1320:                                    .startsWith(basisPackageName)) {
1321:                                exIndex++; // ok proceed
1322:                            } else {
1323:                                dependentFSDs.removeElementAt(exIndex); // remove it
1324:                            }
1325:                        } // while
1326:                    } // if
1327:                } else {
1328:
1329:                    //ystem.out.println(">fs> is public");
1330:
1331:                    // Add all files, which depend from the basisFSD
1332:                    // and any project class and its dependent classes in the parent chain:
1333:                    for (int k = 0; k < selectedTargetFSDs.length; k++) {
1334:                        this .addAllFSDsWhichDependFrom(selectedTargetFSDs[k],
1335:                                dependentFSDs, fsdManager);
1336:                    }
1337:                } //else
1338:
1339:                //ystem.out.println(">fs222> SymbolUsageLocationSearch: Search field for " +
1340:                //                   fieldFSDResult.fsd.objectNameWithPosition.content );
1341:
1342:                //
1343:                // Jedes File in der obigen Liste muss auf Block parsernode level durchsucht werden
1344:                // nach relativen oder absoluten Referenzen der Basisklasse und dann nach
1345:                // expliziten Methodenaufrufen der obigen Zielmethode.
1346:                //
1347:                // Zunächst lasse ich die Vererbung beiseite und beruecksichtige nur
1348:                // Toplevel-Instanzen mit dynamischen oder statischen Methoden
1349:                // also folgende zwei Formen:
1350:                // instance.dynamicMethod( ... )   oder   Class.StaticMethod( ... )
1351:                //
1352:                // instance oder Class konnen relativ oder qualifiziert sein.
1353:                //
1354:                // instance kann Member Attribut oder lokale Variable sein.
1355:                //
1356:                // Zusätzlich sind auch "verdeckte" Calls möglich:
1357:                //
1358:                // anotherClassInstance.getMyInstance().dynamicMethod().sayHello()
1359:                //
1360:                //
1361:                FileStructureDescriptionParserTreePostProcessor postProcessor = new FileStructureDescriptionParserTreePostProcessor(
1362:                        fsdManager);
1363:                // Fill all hits into ClassReferenceEntry objects and add them to this vector:
1364:                Vector classReferences = new Vector();
1365:                if (progressWindow != null) {
1366:                    progressWindow.setProgressMaxValue(dependentFSDs.size());
1367:                }
1368:                for (int fsdIndex = 0; fsdIndex < dependentFSDs.size(); fsdIndex++) {
1369:                    if (progressWindow != null) {
1370:                        final int progressValue = fsdIndex;
1371:                        EventQueue.invokeLater(new Runnable() {
1372:                            public void run() {
1373:                                progressWindow.setProgressValue(progressValue);
1374:                            }
1375:                        });
1376:                        // Break the search, if the user has pushed the cancel button:
1377:                        if (progressWindow.getWasCancelled()) {
1378:                            searchHasBeenCancelledByTheUser = true;
1379:                            break;
1380:                        }
1381:                        try {
1382:                            Thread.yield();
1383:                        } catch (Exception e234986) {
1384:                        }
1385:                    }
1386:
1387:                    final FileStructureDescription candidateFSD = (FileStructureDescription) dependentFSDs
1388:                            .elementAt(fsdIndex);
1389:                    // Get the associated source text (can be from java files or from jar archives)
1390:                    final StringBuffer candidateSourceCode = fsdManager
1391:                            .getJavaSourceForFSD(candidateFSD);
1392:                    // Get the full parser tree:
1393:                    final ParserTreeNode compilationUnitNode = this 
1394:                            .getCompilationUnitNodeFor(candidateSourceCode,
1395:                                    candidateFSD.fullyQualifiedClassNameBuffer
1396:                                            .toString());
1397:                    // For the following scan, the fsd must have the local fields, which usually only
1398:                    // are parsed for fsd's of sources, which are going to be displayed in the source editor.
1399:                    // This actions here are made for many fsd's, which of course are not displayed in
1400:                    // the editor, so we have to update them to have the local fields information:
1401:                    // Note the two flags:
1402:                    // create local fields = true ( as mentionned above )
1403:                    // call dependency scanner = true : Because the dependency fields are cleared
1404:                    //                                  by the postProcessor, the dependencies
1405:                    //                                  ALWAYS must be recalculated.
1406:                    //                                  Because the postprocessor stores
1407:                    //                                  the compilationrootnode and the fsd in the entries
1408:                    //                                  sent to the dependency updater, this doesn't
1409:                    //                                  cost much time:
1410:                    // This all is done on the same fsd reference.
1411:                    postProcessor.updatePostProcessParserTree(candidateFSD,
1412:                            candidateFSD.belongsToProject, compilationUnitNode,
1413:                            candidateFSD.pathNameBuffer.toString(), true, // create local fields
1414:                            true); // call dependency scanner
1415:                    // Now deepscan the tree for occurences of calls of the searched method:
1416:                    // For any found location (defined by the line and column numbers) we do the same
1417:                    // like done, when the declaration of the method is searched and see, if we
1418:                    // land in the targetFSD or not. If we do land in the targetFSD, a call location
1419:                    // has been found.
1420:                    this .scanForFieldCallsOf(candidateFSD, compilationUnitNode,
1421:                            fieldName, classReferences);
1422:                } // for
1423:
1424:                //ystem.out.println(">fs333> SymbolUsageLocationSearch: Search field for " +
1425:                //                   fieldFSDResult.fsd.objectNameWithPosition.content );
1426:
1427:                if (!this .searchHasBeenCancelledByTheUser) {
1428:                    // Not absolutely required, but more secure, because at least the queue of the
1429:                    // dependency updater will contain some entries: Force to perform all pending
1430:                    // entries again:
1431:                    fsdManager.waitForUpdaters();
1432:
1433:                    //ystem.out.println(">fs444> SymbolUsageLocationSearch: Search field for " +
1434:                    //                   fieldFSDResult.fsd.objectNameWithPosition.content );
1435:
1436:                    // If the "jump to declaration" procedure returns the methodFSDResult.basisFSD,
1437:                    // one can add a jump-to-method-call action to the searchresults tree:
1438:                    Vector searchResultsUserObjectVector = new Vector();
1439:                    for (int i = 0; i < classReferences.size(); i++) {
1440:                        final FieldReferenceEntry entry = (FieldReferenceEntry) classReferences
1441:                                .elementAt(i);
1442:                        // We need the SourceEditorDocument:
1443:                        EditableLeafObject leaf = fsdManager
1444:                                .getJavaSourceEditorLeafForFSD(entry
1445:                                        .getClassDescription());
1446:                        // On leaf level, one should unload the content, after having loaded and processed it.
1447:                        // But one shouldn't unload it, if it already was loaded by another one, when this method starts.
1448:                        // It's not serious, if this doesn't work some times, so no need for synchronization here.
1449:                        boolean leafWasLoadedInitially = leaf.isContentLoaded();
1450:                        Object leafContent = leaf.getContent();
1451:                        if (leafContent instanceof  SourceEditorDocument) {
1452:                            final SourceEditorDocument sourceDoc = (SourceEditorDocument) leafContent;
1453:                            // Test, if the sound attribute described in fieldFSDResult lies in
1454:                            // the selectedTargetFSDs, or if this attribute is
1455:                            // a local attribute, test, if it lies in the currentFSD and if
1456:                            // the currentLineNumber is in its local scope:
1457:                            boolean isValidField = false;
1458:                            if ((fieldFSDResult.fsd.scopeStartLine <= 0)
1459:                                    && (fieldFSDResult.fsd.scopeEndLine <= 0)) {
1460:                                // It's a MEMBER attribute
1461:                                isValidField = this 
1462:                                        .getIsFieldDeclarationLocatedIn(
1463:                                                sourceDoc, entry,
1464:                                                fieldFSDResult,
1465:                                                selectedTargetFSDs, fsdManager);
1466:
1467:                                if (!isValidField) {
1468:                                    Log
1469:                                            .Info("getIsFieldDeclarationLocatedIn returned false for "
1470:                                                    + entry
1471:                                                            .getClassDescription().fullyQualifiedClassNameBuffer
1472:                                                            .toString());
1473:                                }
1474:                            } else {
1475:                                // It's a LOCAL attribute - so we don't need the selectedTargetFSDs,
1476:                                // because only the currentFSD is allowed as basisFSD for possible hits.
1477:                                isValidField = this 
1478:                                        .getIsLocalFieldDeclarationInScope(
1479:                                                sourceDoc, entry,
1480:                                                fieldFSDResult, fsdManager,
1481:                                                currentFSD, currentLineNumber);
1482:                                if (!isValidField) {
1483:                                    Log
1484:                                            .Info("getIsLocalFieldDeclarationInScope returned false for "
1485:                                                    + entry
1486:                                                            .getClassDescription().fullyQualifiedClassNameBuffer
1487:                                                            .toString());
1488:                                }
1489:                            } // else
1490:                            if (isValidField) {
1491:                                // Create a SearchResultsFileNodeUserObject and add it to the vector:
1492:                                final int docPosition = sourceDoc
1493:                                        .getPositionOfStartOfLine(entry
1494:                                                .getStartLine() - 1)
1495:                                        + (entry.getStartColumn() + entry
1496:                                                .getEndColumn()) / 2;
1497:                                final boolean breakAtPoints = false;
1498:                                final int[] nearestWordPosition = sourceDoc
1499:                                        .getNearestWordPositionTo(docPosition,
1500:                                                breakAtPoints);
1501:                                final int startOffset = nearestWordPosition[0];
1502:                                final int endOffset = nearestWordPosition[1];
1503:
1504:                                final SearchResultsUserObject resultUserObject = new SearchResultsUserObject(
1505:                                        leaf, entry.getStartLine() - 1,
1506:                                        docPosition, entry.getEndColumn()
1507:                                                - entry.getStartColumn() + 1);
1508:
1509:                                searchResultsUserObjectVector
1510:                                        .addElement(resultUserObject);
1511:                            } // if
1512:                        } // if
1513:                        else {
1514:                            Log
1515:                                    .Warn("leafContent as NOT instanceof SourceEditorDocument");
1516:                        }
1517:                        // Be careful with unloading: One only is allowed to unload the leaf,
1518:                        // if it has not been loaded, when this method has started, otherwise we could
1519:                        // possibly unload a leaf, which currently is displayed in the editor, which
1520:                        // would cause the editor to crash soon after this.
1521:                        if (!leafWasLoadedInitially) {
1522:                            leaf.unloadContent(false); // make memory of this available sooner (gc)
1523:                        }
1524:                    } // for
1525:
1526:                    /*
1527:                    long elapsedTime = System.currentTimeMillis() - startTime;
1528:                    Log.Info("elapsedTime= " + elapsedTime );
1529:                    Log.Info("+ CheckResults: Found " + searchResultsUserObjectVector.size() + " hits.");
1530:                     */
1531:
1532:                    // Close and dipose the progressWindow, if it has been created:
1533:                    if (progressWindow != null) {
1534:                        EventQueue.invokeLater(new Runnable() {
1535:                            public void run() {
1536:                                progressWindow.setVisible(false);
1537:                                progressWindow.dispose();
1538:                            }
1539:                        });
1540:                        // Give Swing some time right now:
1541:                        try {
1542:                            Thread.sleep(88);
1543:                        } catch (Exception e1) {
1544:                        }
1545:                    } // if
1546:
1547:                    // Tell the searchresults tree to display action-entries for the
1548:                    // found results, if some were found:
1549:                    if (searchResultsUserObjectVector.size() > 0) {
1550:                        elementsHaveBeenFound = true;
1551:                        SearchResultsUserObject[] searchResultsUserObjects = new SearchResultsUserObject[searchResultsUserObjectVector
1552:                                .size()];
1553:                        searchResultsUserObjectVector
1554:                                .copyInto(searchResultsUserObjects);
1555:                        this .projectFrame
1556:                                .setSearchResultsTreeContentWithObjectSearchResults(
1557:                                        searchName, searchResultsUserObjects);
1558:                    } else {
1559:                        String title = Language
1560:                                .Translate("Object Search Results");
1561:                        String message = Language
1562:                                .Translate("The object search hasn't found any results.");
1563:                        JOptionPane
1564:                                .showMessageDialog(this .projectFrame, message,
1565:                                        title, JOptionPane.INFORMATION_MESSAGE);
1566:                    }
1567:                    classReferences.setSize(0); // GC assistance
1568:                }
1569:                return elementsHaveBeenFound;
1570:            } // search_Field_Usage_Locations_In_Thread
1571:
1572:            private void addAllFSDsWhichDependFrom(
1573:                    final FileStructureDescription basisFSD,
1574:                    final Vector dependentFSDs,
1575:                    final FileStructureDescriptionManager fsdManager) {
1576:
1577:                // Add the basisFSD itself:
1578:                this .addUniqueObjectToVector(basisFSD, dependentFSDs);
1579:
1580:                // The method is public:
1581:                // We only have to scan files, which depend in some way from
1582:                // the file given by the topLevelSourceFileFSD.
1583:                // This is is absoulutely important: If this information wouldn't be
1584:                // available, one could forget that, because searching all files
1585:                // in the src,libs and projects takes far too much time and resources.
1586:                FileStructureDescription[] allFSDs = fsdManager
1587:                        .getAllFileStructureDescriptions();
1588:                String sourceFileKeyName = basisFSD.fullyQualifiedClassNameBuffer
1589:                        .toString();
1590:                boolean onlySearchInProject = basisFSD.belongsToProject;
1591:                FileStructureDescription fsd = null;
1592:                for (int index = 0; index < allFSDs.length; index++) {
1593:                    fsd = allFSDs[index];
1594:                    // If the basis fsd is in the project, we don't have to search all the libraries too.
1595:                    // In searches of the libraries too, especially the amount of fsd's which need to be
1596:                    // compiled always, will increase.
1597:                    if (fsd.belongsToProject || (!onlySearchInProject)) {
1598:                        // Add the fsd, if the sourceFileKeyName is among the referenced targets,
1599:                        // or if the fsd has to be compiled always and therefore possibly
1600:                        // has dependencies to any file:
1601:                        if (fsd.hasToBeCompiledAlways) {
1602:                            this .addUniqueObjectToVector(fsd, dependentFSDs);
1603:                            //ystem.out.println("Method usage search fsd.hasToBeCompiledAlways: " +
1604:                            //                   fsd.fullyQualifiedClassNameBuffer.toString() );
1605:                        } else {
1606:                            for (int k = 0; k < fsd.referencedProjectFiles
1607:                                    .size(); k++) {
1608:                                if (((String) fsd.referencedProjectFiles
1609:                                        .elementAt(k))
1610:                                        .equals(sourceFileKeyName)) {
1611:                                    this .addUniqueObjectToVector(fsd,
1612:                                            dependentFSDs);
1613:                                    break;
1614:                                }
1615:                            }
1616:                        }
1617:                    } // if
1618:                } // for
1619:
1620:                // Recur:
1621:                // Add all parent files and their dependent files, but only
1622:                // as long as they are in the project:
1623:                if (basisFSD.super Class_fullyQualifiedClassName.content
1624:                        .length() > 0) {
1625:                    // Get that superclass fsd:
1626:                    final String super ClassQualifier = basisFSD.super Class_fullyQualifiedClassName.content;
1627:                    // Note: superClass_fullyQualifiedClassName only is qualified in the sense, that
1628:                    //       it's the qualifier as entered in the source. That means, that we still
1629:                    //       must combine it with all import statements :
1630:                    // Note: For the combination of import statements, it's always the toplevel currentFSD,
1631:                    //       which must be used, also if basisFSD points to a nested fsd.
1632:                    final String[] inScopePossibleIdentifiers = CodeCompletionUtilities
1633:                            .CreatePossibleQualifiedClassIdentifiers(basisFSD,
1634:                                    super ClassQualifier);
1635:                    FileStructureDescription parentFSD = null;
1636:                    for (int p = 0; p < inScopePossibleIdentifiers.length; p++) {
1637:                        parentFSD = fsdManager
1638:                                .searchFSD(inScopePossibleIdentifiers[p]);
1639:                        if (parentFSD != null) {
1640:                            break;
1641:                        }
1642:                    }
1643:                    if (parentFSD == null) // happens in presence of syntactical errors in the source
1644:                    {
1645:                        /*
1646:                        Log.Info("No fsd found for key: ");
1647:                        Log.Info("$" + basisFSD.superClass_fullyQualifiedClassName.content + "$" );
1648:                         */
1649:                    } else {
1650:                        // If it belongs to the project, add it and all its dependent fsd's too:
1651:                        if (parentFSD.belongsToProject) {
1652:                            this .addAllFSDsWhichDependFrom(parentFSD,
1653:                                    dependentFSDs, fsdManager);
1654:                        }
1655:                    }
1656:                }
1657:            } // addAllFSDsWhichDependFrom
1658:
1659:            /**
1660:             *  Traces back the method call defined in methodReferenceEntry to
1661:             *  the location, where the associated method is declared.
1662:             *  If that declaration point lies inside one the selectedTargetFSDs, true is returned.
1663:             */
1664:            private boolean getIsMethodDeclarationLocatedIn(
1665:                    final SourceEditorDocument sourceDoc,
1666:                    final MethodReferenceEntry methodReferenceEntry,
1667:                    final SearchMethodFSDResult methodFSDResult,
1668:                    final FileStructureDescription[] selectedTargetFSDs,
1669:                    final FileStructureDescriptionManager fsdManager) {
1670:                boolean isLocatedInSelectedTargetFSDs = false;
1671:                // Get the position of somewhere in the middle of the methodname:
1672:
1673:                // Important: Use the same document methods, as if the user would have rightclicked
1674:                // the methodname with the mouse. This way, changes on these searchroutines
1675:                // automatically change this search here too.
1676:                // See SourceEditorDocument.processCurrentMousePosition().
1677:                // The goal is, that we need the optional qualifiers before the methodname too
1678:                // for locating the declaration of that method.
1679:                // Take the average column position as doc position:
1680:                final int docPosition = sourceDoc
1681:                        .getPositionOfStartOfLine(methodReferenceEntry
1682:                                .getStartLine() - 1)
1683:                        + (methodReferenceEntry.getStartColumn() + methodReferenceEntry
1684:                                .getEndColumn()) / 2;
1685:                final boolean breakAtPoints = false;
1686:                final int[] nearestWordPosition = sourceDoc
1687:                        .getNearestWordPositionTo(docPosition, breakAtPoints);
1688:                final int startOffset = nearestWordPosition[0];
1689:                final int endOffset = nearestWordPosition[1];
1690:                try {
1691:                    final String searchIdentifier = sourceDoc.getText(
1692:                            startOffset, endOffset - startOffset + 1);
1693:
1694:                    //ystem.out.println("");
1695:                    //ystem.out.println("getIsMethod.. searchIdentifier= <" + searchIdentifier + ">");
1696:
1697:                    // Target Containers for the objectSearch results :
1698:                    Vector fieldFSDTargetResultsVector = new Vector();
1699:                    Vector methodFSDTargetResultsVector = new Vector();
1700:                    Vector classFSDTargetResultsVector = new Vector();
1701:
1702:                    ObjectSearch objectSearch = new ObjectSearch(docPosition,
1703:                            sourceDoc, this .projectFrame.getEditorPanel(),
1704:                            methodReferenceEntry.getClassDescription(),
1705:                            fsdManager);
1706:                    objectSearch.doSearch(searchIdentifier,
1707:                            fieldFSDTargetResultsVector,
1708:                            methodFSDTargetResultsVector,
1709:                            classFSDTargetResultsVector);
1710:                    // Now, the objectSearch results have been added to the passed vectors.
1711:
1712:                    // Translate the results into arrays :
1713:                    SearchFieldFSDResult[] searchFieldFSDTargetResults = new SearchFieldFSDResult[fieldFSDTargetResultsVector
1714:                            .size()];
1715:                    fieldFSDTargetResultsVector
1716:                            .copyInto(searchFieldFSDTargetResults);
1717:                    SearchMethodFSDResult[] searchMethodFSDTargetResults = new SearchMethodFSDResult[methodFSDTargetResultsVector
1718:                            .size()];
1719:                    methodFSDTargetResultsVector
1720:                            .copyInto(searchMethodFSDTargetResults);
1721:
1722:                    // Invert the order of class entries :
1723:                    SearchFSDResult[] searchFSDTargetResults = new SearchFSDResult[classFSDTargetResultsVector
1724:                            .size()];
1725:                    for (int i = 0; i < searchFSDTargetResults.length; i++) {
1726:                        searchFSDTargetResults[i] = (SearchFSDResult) classFSDTargetResultsVector
1727:                                .elementAt(searchFSDTargetResults.length - i
1728:                                        - 1);
1729:                    }
1730:
1731:                    // Here we actually dont need the vector element entry functionality as jump actions,
1732:                    // like used in the EditorTextSearch objects.
1733:                    // Here, we only test, if the jumps would land in the basis FSD or not.
1734:                    // If they do, the associated entry is a hit = is a method call, which has the
1735:                    // basis method as target:
1736:
1737:                    /* ----------- Debug Output Start ------------
1738:                    Log.Info("SymbolUsageLocationSearch:getIsMethod..  #searchFieldFSDResults = " +
1739:                             searchFieldFSDTargetResults.length );
1740:                    if( searchFieldFSDTargetResults.length > 0 )
1741:                     {
1742:                       Log.Info("which are:");
1743:                       for( int p=0; p < searchFieldFSDTargetResults.length; p++ )
1744:                        {
1745:                          final String name = searchFieldFSDTargetResults[p].fsd.objectNameWithPosition.content;
1746:                          Log.Info("- " + name);
1747:                        }
1748:                     }
1749:                    Log.Info("getIsMethod..  #searchMethodFSDResults = " +
1750:                             searchMethodFSDTargetResults.length );
1751:                    if( searchMethodFSDTargetResults.length > 0 )
1752:                     {
1753:                       Log.Info("which are:");
1754:                       for( int p=0; p < searchMethodFSDTargetResults.length; p++ )
1755:                        {
1756:                          final String name = searchMethodFSDTargetResults[p].fsd.name.content;
1757:                          final String parentFSDname = searchMethodFSDTargetResults[p].basisFSD.className.content;
1758:                          Log.Info("- " + name + "  in fsd: " + parentFSDname );
1759:                        }
1760:                     }
1761:                    Log.Info("SymbolUsageLocationSearch:getIsMethod..  #searchFSDResults = " +
1762:                             searchFSDTargetResults.length );
1763:                    if( searchFSDTargetResults.length > 0 )
1764:                     {
1765:                       Log.Info("which are:");
1766:                       for( int p=0; p < searchFSDTargetResults.length; p++ )
1767:                        {
1768:                          final String name = searchFSDTargetResults[p].fsd.className.content;
1769:                          Log.Info("- " + name);
1770:                        }
1771:                     }
1772:                    ----------- Debug Output End ------------ */
1773:
1774:                    // The selected sources containing the searched method are given by the array
1775:                    // selectedTargetFSDs.
1776:                    // searchMethodFSDTargetResults[i]
1777:                    // Now the fsd's, which describe files [containing the searched method]
1778:                    // and which are selected for the search, are given by the
1779:                    // selectedTargetFSDs fsd array.
1780:                    // With other words: Any methodFSDResult result, which has its basis fsd
1781:                    // equal to one of the selectedTargetFSDs is a hit:
1782:                    String s1, s2;
1783:                    for (int i = 0; i < searchMethodFSDTargetResults.length; i++) {
1784:                        for (int k = 0; k < selectedTargetFSDs.length; k++) {
1785:                            s1 = searchMethodFSDTargetResults[i].basisFSD.fullyQualifiedClassNameBuffer
1786:                                    .toString();
1787:                            s2 = selectedTargetFSDs[k].fullyQualifiedClassNameBuffer
1788:                                    .toString();
1789:
1790:                            //ystem.out.println("CMP> " + s1 + "  against  " + s2 );
1791:
1792:                            if (s1.equals(s2)) {
1793:                                isLocatedInSelectedTargetFSDs = true;
1794:                            }
1795:                        }
1796:                    } // for
1797:                    s1 = null;
1798:                    s2 = null;
1799:                } catch (Exception e) {
1800:                    Log
1801:                            .Info("Exception catched. This exception is not serious.");
1802:                    // Log.Error( e );
1803:                }
1804:                return isLocatedInSelectedTargetFSDs;
1805:            } // getIsMethodDeclarationLocatedIn
1806:
1807:            /**                  
1808:             *  Like getIsMethodDeclarationLocatedIn(), but this one works for attributes.
1809:             *  Traces back the field call defined in fieldReferenceEntry to
1810:             *  the location, where the associated field is declared.
1811:             *  If that declaration point lies inside one the selectedTargetFSDs, true is returned.
1812:             *  Note: For LOCAL attributes, one has to call getIsLocalFieldDeclarationInScope()
1813:             *        instead of this method.
1814:             */
1815:            private boolean getIsFieldDeclarationLocatedIn(
1816:                    final SourceEditorDocument sourceDoc,
1817:                    final FieldReferenceEntry fieldReferenceEntry,
1818:                    final SearchFieldFSDResult fieldFSDResult,
1819:                    final FileStructureDescription[] selectedTargetFSDs,
1820:                    final FileStructureDescriptionManager fsdManager) {
1821:
1822:                //ystem.out.println("Calling getIsFieldDeclarationLocatedIn for " +
1823:                //                   fieldFSDResult.fsd.objectNameWithPosition.content ); 
1824:
1825:                boolean isLocatedInSelectedTargetFSDs = false;
1826:                // Get the position of somewhere in the middle of the methodname:
1827:
1828:                // Important: Use the same document methods, as if the user would have rightclicked
1829:                // the methodname with the mouse. This way, changes on these searchroutines
1830:                // automatically change this search here too.
1831:                // See SourceEditorDocument.processCurrentMousePosition().
1832:                // The goal is, that we need the optional qualifiers before the methodname too
1833:                // for locating the declaration of that method.
1834:                // Take the average column position as doc position:
1835:                final int docPosition = sourceDoc
1836:                        .getPositionOfStartOfLine(fieldReferenceEntry
1837:                                .getStartLine() - 1)
1838:                        + (fieldReferenceEntry.getStartColumn() + fieldReferenceEntry
1839:                                .getEndColumn()) / 2;
1840:                final boolean breakAtPoints = false;
1841:                final int[] nearestWordPosition = sourceDoc
1842:                        .getNearestWordPositionTo(docPosition, breakAtPoints);
1843:                final int startOffset = nearestWordPosition[0];
1844:                final int endOffset = nearestWordPosition[1];
1845:                try {
1846:                    final String searchIdentifier = sourceDoc.getText(
1847:                            startOffset, endOffset - startOffset + 1);
1848:
1849:                    //ystem.out.println("SymbolUsageLocationSearch:getIsField.. searchIdentifier= <" + searchIdentifier + ">");
1850:
1851:                    // Target Containers for the objectSearch results :
1852:                    Vector fieldFSDTargetResultsVector = new Vector();
1853:                    Vector methodFSDTargetResultsVector = new Vector();
1854:                    Vector classFSDTargetResultsVector = new Vector();
1855:
1856:                    // If the symbol contains points, we add items for
1857:                    // all levels from the whole qualifier down to the root qualifier.
1858:                    String[] searchQualifiers = StringUtilities.SplitString(
1859:                            searchIdentifier, ".");
1860:
1861:                    //ystem.out.println("SymbolUsageLocationSearch: fieldName= " + fieldReferenceEntry.getFieldName() );
1862:
1863:                    // For the field search, we must start the ObjectSearch multiple times for
1864:                    // multiple searchQualifiers:
1865:                    // The first call is done for searchQualifiers[0] alone and for each following call
1866:                    // the following searchQualifiers element is added:
1867:                    // Call 1 : searchQualifiers[0]
1868:                    // Call 2 : searchQualifiers[0] + "." + searchQualifiers[1]
1869:                    // and so on.
1870:                    // This way, attribute usages in qualified terms are foung too.
1871:                    // Example: x.getY().myAttribute.getZ() -> here, myAtribute will be found,
1872:                    // when the object search is started with the first three searchQualifiers elements.
1873:                    ObjectSearch objectSearch = new ObjectSearch(docPosition,
1874:                            sourceDoc, this .projectFrame.getEditorPanel(),
1875:                            fieldReferenceEntry.getClassDescription(),
1876:                            fsdManager);
1877:                    for (int i = 0; i < searchQualifiers.length; i++) {
1878:                        StringBuffer cumulativeIdentifier = new StringBuffer("");
1879:                        for (int k = 0; k < i + 1; k++) {
1880:                            cumulativeIdentifier.append(searchQualifiers[k]);
1881:                            if (k < i)
1882:                                cumulativeIdentifier.append(".");
1883:                        }
1884:                        objectSearch.doSearch(cumulativeIdentifier.toString(),
1885:                                fieldFSDTargetResultsVector,
1886:                                methodFSDTargetResultsVector,
1887:                                classFSDTargetResultsVector);
1888:                    }
1889:                    // Now, the objectSearch results have been added to the passed vectors.
1890:
1891:                    // Translate the results into arrays :
1892:                    SearchFieldFSDResult[] searchFieldFSDTargetResults = new SearchFieldFSDResult[fieldFSDTargetResultsVector
1893:                            .size()];
1894:                    fieldFSDTargetResultsVector
1895:                            .copyInto(searchFieldFSDTargetResults);
1896:                    SearchMethodFSDResult[] searchMethodFSDTargetResults = new SearchMethodFSDResult[methodFSDTargetResultsVector
1897:                            .size()];
1898:                    methodFSDTargetResultsVector
1899:                            .copyInto(searchMethodFSDTargetResults);
1900:
1901:                    // Invert the order of class entries :
1902:                    SearchFSDResult[] searchFSDTargetResults = new SearchFSDResult[classFSDTargetResultsVector
1903:                            .size()];
1904:                    for (int i = 0; i < searchFSDTargetResults.length; i++) {
1905:                        searchFSDTargetResults[i] = (SearchFSDResult) classFSDTargetResultsVector
1906:                                .elementAt(searchFSDTargetResults.length - i
1907:                                        - 1);
1908:                    }
1909:
1910:                    // Here we actually dont need the vector element entry functionality as jump actions,
1911:                    // like used in the EditorTextSearch objects.
1912:                    // Here, we only test, if the jumps would land in the basis FSD or not.
1913:                    // If they do, the assoviated entry is a hit = is a method call, which has the
1914:                    // basis method as target:
1915:
1916:                    /* ----------  Debug Output Start -----------
1917:                    Log.Info("SymbolUsageLocationSearch:getIsField..  #searchFieldFSDResults = " +
1918:                             searchFieldFSDTargetResults.length );
1919:                    if( searchFieldFSDTargetResults.length > 0 )
1920:                     {
1921:                       Log.Info("which are:");
1922:                       for( int p=0; p < searchFieldFSDTargetResults.length; p++ )
1923:                        {
1924:                          final String name = searchFieldFSDTargetResults[p].fsd.objectNameWithPosition.content;
1925:                          Log.Info("- " + name);
1926:                        }
1927:                     }
1928:                    Log.Info("SymbolUsageLocationSearch:getIsField..  #searchMethodFSDResults = " +
1929:                             searchMethodFSDTargetResults.length );
1930:                    if( searchMethodFSDTargetResults.length > 0 )
1931:                     {
1932:                       Log.Info("which are:");
1933:                       for( int p=0; p < searchMethodFSDTargetResults.length; p++ )
1934:                        {
1935:                          final String name = searchMethodFSDTargetResults[p].fsd.name.content;
1936:                          final String parentFSDname = searchMethodFSDTargetResults[p].basisFSD.className.content;
1937:                          Log.Info("- " + name + "  in fsd: " + parentFSDname );
1938:                        }
1939:                     }
1940:                    Log.Info("SymbolUsageLocationSearch:getIsField..  #searchFSDResults = " +
1941:                             searchFSDTargetResults.length );
1942:                    if( searchFSDTargetResults.length > 0 )
1943:                     {
1944:                       Log.Info("which are:");
1945:                       for( int p=0; p < searchFSDTargetResults.length; p++ )
1946:                        {
1947:                          final String name = searchFSDTargetResults[p].fsd.className.content;
1948:                          Log.Info("- " + name);
1949:                        }
1950:                     }
1951:                    ----------  Debug Output End ----------- */
1952:
1953:                    // The selected sources containing the searched method are given by the array
1954:                    // selectedTargetFSDs.
1955:                    // searchMethodFSDTargetResults[i]
1956:                    // Now the fsd's, which describe files [containing the searched method]
1957:                    // and which are selected for the search, are given by the
1958:                    // selectedTargetFSDs fsd array.
1959:                    // With other words: Any fieldFSDResult result, which has its basis fsd
1960:                    // equal to one of the selectedTargetFSDs is a hit:
1961:                    String s1, s2;
1962:                    for (int i = 0; i < searchFieldFSDTargetResults.length; i++) {
1963:                        for (int k = 0; k < selectedTargetFSDs.length; k++) {
1964:                            s1 = searchFieldFSDTargetResults[i].basisFSD.fullyQualifiedClassNameBuffer
1965:                                    .toString();
1966:                            s2 = selectedTargetFSDs[k].fullyQualifiedClassNameBuffer
1967:                                    .toString();
1968:                            if (s1.equals(s2)) {
1969:                                isLocatedInSelectedTargetFSDs = true;
1970:                                break;
1971:                            }
1972:                        } // for
1973:                    } // for
1974:                    s1 = null;
1975:                    s2 = null;
1976:                } catch (Exception e) {
1977:                    Log
1978:                            .Info("Exception catched. This exception is not serious.");
1979:                    // Log.Error( e );
1980:                }
1981:                return isLocatedInSelectedTargetFSDs;
1982:            } // getIsFieldDeclarationLocatedIn
1983:
1984:            /**                  
1985:             *  Like getIsFieldDeclarationLocatedIn(), but this one is made for
1986:             *  LOCAL attributes.
1987:             *  If this attribute is a local attribute, test, if it lies in the currentFSD and if
1988:             *  the currentLineNumber is in its local scope.
1989:             */
1990:            private boolean getIsLocalFieldDeclarationInScope(
1991:                    final SourceEditorDocument sourceDoc,
1992:                    final FieldReferenceEntry fieldReferenceEntry,
1993:                    final SearchFieldFSDResult fieldFSDResult,
1994:                    final FileStructureDescriptionManager fsdManager,
1995:                    final FileStructureDescription currentFSD,
1996:                    final int currentLineNumber) {
1997:
1998:                if (fieldFSDResult == null) {
1999:                    Log.Warn("fieldFSDResult == null");
2000:                }
2001:                if (fieldFSDResult.fsd == null) {
2002:                    Log.Warn("fieldFSDResult.fsd == null");
2003:                }
2004:                if (fieldFSDResult.fsd.objectNameWithPosition == null) {
2005:                    Log
2006:                            .Warn("fieldFSDResult.fsd.objectNameWithPosition == null");
2007:                    Log.Warn("for fsd " + fieldFSDResult.fsd.simpleClassName);
2008:                }
2009:
2010:                // Log.Info("Calling getIsLocalFieldDeclarationInScope for " +
2011:                //          fieldFSDResult.fsd.objectNameWithPosition.content );
2012:
2013:                boolean isLocatedIncurrentFSDAndIsInScope = false;
2014:                // Get the position of somewhere in the middle of the methodname:
2015:
2016:                // Important: Use the same document methods, as if the user would have rightclicked
2017:                // the methodname with the mouse. This way, changes on these searchroutines
2018:                // automatically change this search here too.
2019:                // See SourceEditorDocument.processCurrentMousePosition().
2020:                // The goal is, that we need the optional qualifiers before the methodname too
2021:                // for locating the declaration of that method.
2022:                // Take the average column position as doc position:
2023:                final int docPosition = sourceDoc
2024:                        .getPositionOfStartOfLine(fieldReferenceEntry
2025:                                .getStartLine() - 1)
2026:                        + (fieldReferenceEntry.getStartColumn() + fieldReferenceEntry
2027:                                .getEndColumn()) / 2;
2028:                final boolean breakAtPoints = false;
2029:                final int[] nearestWordPosition = sourceDoc
2030:                        .getNearestWordPositionTo(docPosition, breakAtPoints);
2031:                final int startOffset = nearestWordPosition[0];
2032:                final int endOffset = nearestWordPosition[1];
2033:                try {
2034:                    final String searchIdentifier = sourceDoc.getText(
2035:                            startOffset, endOffset - startOffset + 1);
2036:
2037:                    //ystem.out.println("SymbolUsageLocationSearch:getIsField.. searchIdentifier= <" + searchIdentifier + ">");
2038:
2039:                    // Target Containers for the objectSearch results :
2040:                    Vector fieldFSDTargetResultsVector = new Vector();
2041:                    Vector methodFSDTargetResultsVector = new Vector();
2042:                    Vector classFSDTargetResultsVector = new Vector();
2043:
2044:                    // If the symbol contains points, we add items for
2045:                    // all levels from the whole qualifier down to the root qualifier.
2046:                    String[] searchQualifiers = StringUtilities.SplitString(
2047:                            searchIdentifier, ".");
2048:
2049:                    //ystem.out.println("SymbolUsageLocationSearch: fieldName= " + fieldReferenceEntry.getFieldName() );
2050:
2051:                    // For the field search, we must start the ObjectSearch multiple times for
2052:                    // multiple searchQualifiers:
2053:                    // The first call is done for searchQualifiers[0] alone and for each following call
2054:                    // the following searchQualifiers element is added:
2055:                    // Call 1 : searchQualifiers[0]
2056:                    // Call 2 : searchQualifiers[0] + "." + searchQualifiers[1]
2057:                    // and so on.         
2058:                    // This way, attribute usages in qualified terms are foung too.
2059:                    // Example: x.getY().myAttribute.getZ() -> here, myAtribute will be found,
2060:                    // when the object search is started with the first three searchQualifiers elements.
2061:                    ObjectSearch objectSearch = new ObjectSearch(docPosition,
2062:                            sourceDoc, this .projectFrame.getEditorPanel(),
2063:                            fieldReferenceEntry.getClassDescription(),
2064:                            fsdManager);
2065:                    for (int i = 0; i < searchQualifiers.length; i++) {
2066:                        StringBuffer cumulativeIdentifier = new StringBuffer("");
2067:                        for (int k = 0; k < i + 1; k++) {
2068:                            cumulativeIdentifier.append(searchQualifiers[k]);
2069:                            if (k < i)
2070:                                cumulativeIdentifier.append(".");
2071:                        }
2072:                        objectSearch.doSearch(cumulativeIdentifier.toString(),
2073:                                fieldFSDTargetResultsVector,
2074:                                methodFSDTargetResultsVector,
2075:                                classFSDTargetResultsVector);
2076:                    }
2077:                    // Now, the objectSearch results have been added to the passed vectors.
2078:
2079:                    // Translate the results into arrays :
2080:                    SearchFieldFSDResult[] searchFieldFSDTargetResults = new SearchFieldFSDResult[fieldFSDTargetResultsVector
2081:                            .size()];
2082:                    fieldFSDTargetResultsVector
2083:                            .copyInto(searchFieldFSDTargetResults);
2084:                    SearchMethodFSDResult[] searchMethodFSDTargetResults = new SearchMethodFSDResult[methodFSDTargetResultsVector
2085:                            .size()];
2086:                    methodFSDTargetResultsVector
2087:                            .copyInto(searchMethodFSDTargetResults);
2088:
2089:                    // Invert the order of class entries :
2090:                    SearchFSDResult[] searchFSDTargetResults = new SearchFSDResult[classFSDTargetResultsVector
2091:                            .size()];
2092:                    for (int i = 0; i < searchFSDTargetResults.length; i++) {
2093:                        searchFSDTargetResults[i] = (SearchFSDResult) classFSDTargetResultsVector
2094:                                .elementAt(searchFSDTargetResults.length - i
2095:                                        - 1);
2096:                    }
2097:
2098:                    // Here we actually dont need the vector element entry functionality as jump actions,
2099:                    // like used in the EditorTextSearch objects.
2100:                    // Here, we only test, if the jumps would land in the basis FSD or not.
2101:                    // If they do, the assoviated entry is a hit = is a method call, which has the
2102:                    // basis method as target:
2103:
2104:                    /* ----------- Debug Output Start ------------          
2105:                    Log.Info("SymbolUsageLocationSearch:getIsLocalFieldDeclarationInScope..  #searchFieldFSDResults = " +
2106:                             searchFieldFSDTargetResults.length );
2107:                    if( searchFieldFSDTargetResults.length > 0 )
2108:                     {
2109:                       Log.Info("which are:");
2110:                       for( int p=0; p < searchFieldFSDTargetResults.length; p++ )
2111:                        {
2112:                          final String name = searchFieldFSDTargetResults[p].fsd.objectNameWithPosition.content;
2113:                          Log.Info("- " + name);
2114:                        }
2115:                     }
2116:                    Log.Info("SymbolUsageLocationSearch:getIsLocalFieldDeclarationInScope..  #searchMethodFSDResults = " +
2117:                             searchMethodFSDTargetResults.length );
2118:                    if( searchMethodFSDTargetResults.length > 0 )
2119:                     {
2120:                       Log.Info("which are:");
2121:                       for( int p=0; p < searchMethodFSDTargetResults.length; p++ )
2122:                        {
2123:                          final String name = searchMethodFSDTargetResults[p].fsd.name.content;
2124:                          final String parentFSDname = searchMethodFSDTargetResults[p].basisFSD.className.content;
2125:                          Log.Info("- " + name + "  in fsd: " + parentFSDname );
2126:                        }
2127:                     }
2128:                    Log.Info("SymbolUsageLocationSearch:getIsLocalFieldDeclarationInScope..  #searchFSDResults = " +
2129:                             searchFSDTargetResults.length );
2130:                    if( searchFSDTargetResults.length > 0 )
2131:                     {
2132:                       Log.Info("which are:");
2133:                       for( int p=0; p < searchFSDTargetResults.length; p++ )
2134:                        {
2135:                          final String name = searchFSDTargetResults[p].fsd.className.content;
2136:                          Log.Info("- " + name);
2137:                        }
2138:                     }
2139:                    ----------- Debug Output End ------------ */
2140:
2141:                    // The selected sources containing the searched attribute are given by the array
2142:                    // selectedTargetFSDs.
2143:                    // searchMethodFSDTargetResults[i]
2144:                    // Special for LOCAL attribute search:
2145:                    // basisFSD must be the currentFSD
2146:                    String s1, s2;
2147:                    for (int i = 0; i < searchFieldFSDTargetResults.length; i++) {
2148:                        s1 = searchFieldFSDTargetResults[i].basisFSD.fullyQualifiedClassNameBuffer
2149:                                .toString();
2150:                        s2 = currentFSD.fullyQualifiedClassNameBuffer
2151:                                .toString();
2152:
2153:                        //Log.Info("Check1 " + s1 + "  against  " + s2 );
2154:
2155:                        if (s1.equals(s2)) {
2156:
2157:                            /* Debug
2158:                            Log.Info("Check1 [2] equal scopeStartLine 1");
2159:                            boolean aa = ( searchFieldFSDTargetResults[i].fsd.scopeStartLine > 0 );
2160:                            boolean bb = ( searchFieldFSDTargetResults[i].fsd.scopeEndLine   > 0 );
2161:                            Log.Info("Check1 [2] aa= " + aa + "  bb = " + bb);
2162:                             */
2163:
2164:                            // The basisFSD of searchFieldFSDTargetResults[i] is the currentFSD, but
2165:                            // a class can have declared local attributes of the same name multiple
2166:                            // times, always with different scopes. The scopes cannot overlap, but they
2167:                            // either don't share anything, or one contains the other completely.
2168:                            // So check the scopes:
2169:                            if ((searchFieldFSDTargetResults[i].fsd.scopeStartLine > 0)
2170:                                    && (searchFieldFSDTargetResults[i].fsd.scopeEndLine > 0)) {
2171:                                // scope numbers are one based, so inrement the currentLineNumber:
2172:                                final int currentLineNumberOneBased = currentLineNumber + 1;
2173:
2174:                                /* Debug
2175:                                Log.Info("Check1 [3] check against linenumber");
2176:                                Log.Info("Check1 [3] scopeStartLine= " +
2177:                                         searchFieldFSDTargetResults[i].fsd.scopeStartLine);
2178:                                Log.Info("Check1 [3] scopeEndLine= " +
2179:                                         searchFieldFSDTargetResults[i].fsd.scopeEndLine);
2180:                                Log.Info("Check1 [3] currentLineNumberOneBased= " +
2181:                                         currentLineNumberOneBased);
2182:                                 */
2183:
2184:                                // It's local, so check scopes and if they are different,
2185:                                // clear isLocatedInSelectedTargetFSDs again.
2186:                                if ((searchFieldFSDTargetResults[i].fsd.scopeStartLine <= currentLineNumberOneBased)
2187:                                        && (searchFieldFSDTargetResults[i].fsd.scopeEndLine >= currentLineNumberOneBased)) {
2188:                                    //Log.Info("isLocatedIncurrentFSDAndIsInScope[1]");
2189:                                    isLocatedIncurrentFSDAndIsInScope = true;
2190:                                    break;
2191:                                } else {
2192:                                    isLocatedIncurrentFSDAndIsInScope = false;
2193:                                }
2194:                            } // if
2195:                        } // if
2196:
2197:                        //Log.Info("Check1 negative");
2198:
2199:                    } // for
2200:                    s1 = null;
2201:                    s2 = null;
2202:                } catch (Exception e) {
2203:                    Log
2204:                            .Info("Catched an exception. This exception is not serious.");
2205:                    Log.Warn(e);
2206:                }
2207:
2208:                //Log.Info("returns with success= " +
2209:                //         isLocatedIncurrentFSDAndIsInScope );
2210:
2211:                return isLocatedIncurrentFSDAndIsInScope;
2212:            } // getIsLocalFieldDeclarationInScope   
2213:
2214:            private boolean getIsStringContainedIn(String s, String[] a) {
2215:                boolean isContained = false;
2216:                for (int i = 0; i < a.length; i++) {
2217:                    if (a[i].equals(s)) {
2218:                        isContained = true;
2219:                        break;
2220:                    }
2221:                }
2222:                return isContained;
2223:            }
2224:
2225:            /**
2226:             *  Scans the passed fsd for calling locations of the
2227:             *  method defined by the passed methodFSDResult.
2228:             */
2229:            public void scanForMethodCallsOf(
2230:                    final FileStructureDescription fsd,
2231:                    final DefaultMutableTreeNode javaCCBasisNode,
2232:                    final String methodName, final Vector classReferences) {
2233:                // Simple first task:
2234:                // Search the javac tree after "LocalVariableDeclaration" nodes
2235:                // in constructor as well as method nodes.
2236:                // Then call a worker method, which parses these
2237:                // LocalVariableDeclaration, creates (or updates) ReferencedFileEntry
2238:                // classes and adds them to the referencedProjectFiles vector
2239:                // of the passed fsd:
2240:
2241:                // NOTE: We do NOT include dependencies of the parent tree or
2242:                //       implemented interface tree, because this can go out of sync easily.
2243:                //       These dependencies are added on demand in fsdManager.getDependentFilePathesOf()
2244:                //       right before the dependent files are added to the compilerlists.
2245:
2246:                // Collect all "TypeDeclaration" nodes, and deepscan for nodes named:
2247:                // 1.1     - LocalVariableDeclaration
2248:                // 1.2     - FormalParameters
2249:                // 1.3     - FieldDeclaration
2250:                // 1.4     - ClassReference sequences in static and dynamic reference sequences
2251:                //           like a.getB().getC().getD()  dynamic, or
2252:                //                A.getB().getC().getD()  static
2253:
2254:                // NOTE: For a simple class, we only have one TypeDeclaration node at
2255:                //       level zero. Having multiple TypeDeclaration nodes at this level
2256:                //       means, we have some inner classes at toplevel, which isn't
2257:                //       standard but somehow allowed.
2258:                //       In the fsd postprocessor this is properly decoded. The inner class
2259:                //       objects are filled into the inner class fsd's.
2260:                //       However for the reference scan, inner class structures play no role,
2261:                //       so we put all reference links into the toplevel fsd, which
2262:                //       stands for the sourcefile.
2263:
2264:                // classReferences: Holds statements, which reference classes. They can occure
2265:                // anywhere (in for loops, in comparisons..) in local blocks as statements,
2266:                // which return void, or they can occure in the *RIGHT SIDE* of all declarations
2267:                // described above.
2268:
2269:                // Fill them:
2270:                // The basisNode = CompilationUnit isn't interesting, so get its children :
2271:                final DefaultMutableTreeNode[] basisNodeChildren = this 
2272:                        .getChildren(javaCCBasisNode);
2273:                for (int basisNodeIndex = 0; basisNodeIndex < basisNodeChildren.length; basisNodeIndex++) {
2274:                    // Nodes have String user objects:
2275:                    final DefaultMutableTreeNode this Child = basisNodeChildren[basisNodeIndex];
2276:                    final Object userObject = this Child.getUserObject();
2277:                    if (userObject instanceof  Integer) {
2278:                        // Integer reference comparison is ok here.
2279:                        if ((Integer) userObject == ParserOutputProcessor.NodeForTypeDeclaration) {
2280:                            // Get the ClassDeclaration children:
2281:                            DefaultMutableTreeNode[] classDeclarationNodes = this 
2282:                                    .getAllChildNodesWithName(
2283:                                            this Child,
2284:                                            ParserOutputProcessor.NodeForClassOrInterfaceDeclaration);
2285:                            for (int classDecIndex = 0; classDecIndex < classDeclarationNodes.length; classDecIndex++) {
2286:                                // Get the ClassBody node children:
2287:                                DefaultMutableTreeNode[] classBodyNodes = this 
2288:                                        .getAllChildNodesWithName(
2289:                                                classDeclarationNodes[classDecIndex],
2290:                                                ParserOutputProcessor.NodeForClassOrInterfaceBody);
2291:                                for (int classBodyIndex = 0; classBodyIndex < classBodyNodes.length; classBodyIndex++) {
2292:                                    // Get the ClassBodyDeclaration node children:
2293:                                    DefaultMutableTreeNode[] classBodyDeclarationNodes = this 
2294:                                            .getAllChildNodesWithName(
2295:                                                    classBodyNodes[classBodyIndex],
2296:                                                    ParserOutputProcessor.NodeForClassOrInterfaceBodyDeclaration);
2297:                                    for (int classBodyDeclarationIndex = 0; classBodyDeclarationIndex < classBodyDeclarationNodes.length; classBodyDeclarationIndex++) {
2298:                                        // The children of the classBodyDeclarationNodes are
2299:                                        // FieldDeclaration, ConstructorDeclaration or MethodDeclaration nodes.
2300:                                        final DefaultMutableTreeNode cbdNode = classBodyDeclarationNodes[classBodyDeclarationIndex];
2301:                                        // The following calls already perform a few simple filterings :
2302:                                        this .deepScanForClassMethodReferences(
2303:                                                fsd, classReferences, cbdNode,
2304:                                                methodName);
2305:                                    }
2306:                                }
2307:                            } // for classDecIndex
2308:                        } // if
2309:                    } // if
2310:                } // for basisNodeIndex                       
2311:            } // scanForMethodCallsOf
2312:
2313:            /**
2314:             *  Scans for the "left sides" and void statements and additionally
2315:             *  prefilters the raw results.
2316:             *  See explanations in scanReferencedObjects.
2317:             */
2318:            private void deepScanForClassMethodReferences(
2319:                    final FileStructureDescription candidateFSD,
2320:                    final Vector targetVector,
2321:                    final DefaultMutableTreeNode classBodyChildNode,
2322:                    final String methodName) {
2323:                // Deepscan for PrimaryExpression nodes, which have children of the form
2324:                // PrimaryPrefix followed by one or multiple PrimarySuffix nodes,
2325:                // where the PrimaryPrefix node does *NOT* contain an AllocationExpression node.
2326:                //
2327:                // NOTE: There are PrimaryExpression nodes, which contain                                        
2328:                // an PrimaryPrefix node with an AllocationExpression childnode, but these ones are scanned by the
2329:                // the special FieldDeclaration scan in scanReferencedObjects(), where they catch the type
2330:                // of the attribute and collect it, if it's not a simple type or the type of an inner class.
2331:                // Note: The last parameter treescan=true is required. This onecauses the scan to
2332:                //       continue reqursion after each hit, so it catches all objects in the tree.
2333:                //       Example: for the expression a.getx( b.getB() ), it will generate TWO entries:
2334:                //       1) a.getx( b.getB() )   [=the full expression]
2335:                //       2) b.getB()             [=the child in the tree]
2336:                //                    
2337:                Vector primaryExpressionNodes = new Vector();
2338:                this 
2339:                        .deepScanForNodesWithName(primaryExpressionNodes,
2340:                                classBodyChildNode,
2341:                                ParserOutputProcessor.NodeForPrimaryExpression,
2342:                                true /* treescan */);
2343:                for (int i = 0; i < primaryExpressionNodes.size(); i++) {
2344:                    final DefaultMutableTreeNode this PrimaryExpressionNode = (DefaultMutableTreeNode) primaryExpressionNodes
2345:                            .elementAt(i);
2346:                    // Only continue, if it has at least one PrimaryPrefix node:
2347:                    boolean containsPrimaryPrefixNode = false;
2348:                    for (int childIndex = 0; childIndex < this PrimaryExpressionNode
2349:                            .getChildCount(); childIndex++) {
2350:                        final DefaultMutableTreeNode this Child = (DefaultMutableTreeNode) this PrimaryExpressionNode
2351:                                .getChildAt(childIndex);
2352:                        if (this Child.getUserObject() instanceof  Integer) // it's a node
2353:                        {
2354:                            final Integer this NodeNameIdentifier = (Integer) this Child
2355:                                    .getUserObject();
2356:                            // reference comparison is ok here.
2357:                            if (this NodeNameIdentifier == ParserOutputProcessor.NodeForPrimaryPrefix) {
2358:                                // Ok, it contains a PrimaryPrefix node, so we use scan the
2359:                                // primary expression node:
2360:                                containsPrimaryPrefixNode = true;
2361:                                break;
2362:                            }
2363:                        }
2364:                    } // childIndex
2365:                    if (containsPrimaryPrefixNode) {
2366:                        final MethodReferenceEntry entry = this 
2367:                                .scanPrimaryExpressionForMethodCalls(
2368:                                        candidateFSD,
2369:                                        this PrimaryExpressionNode, methodName);
2370:                        if (entry != null) {
2371:                            this .addUniqueMethodReferenceEntryToVector(entry,
2372:                                    targetVector);
2373:                        }
2374:                    }
2375:                } // for i
2376:            } // deepScanForClassMethodReferences
2377:
2378:            /**
2379:             *   Like scanForMethodCallsOf(), but works for member attributes.
2380:             */
2381:            public void scanForFieldCallsOf(final FileStructureDescription fsd,
2382:                    final DefaultMutableTreeNode javaCCBasisNode,
2383:                    final String fieldName, final Vector classReferences) {
2384:                // Identifier deep scan for left and right sides.
2385:                // The basisNode = CompilationUnit isn't interesting, so get its children :
2386:                final DefaultMutableTreeNode[] basisNodeChildren = this 
2387:                        .getChildren(javaCCBasisNode);
2388:                for (int basisNodeIndex = 0; basisNodeIndex < basisNodeChildren.length; basisNodeIndex++) {
2389:                    // Nodes have String user objects:
2390:                    final DefaultMutableTreeNode this Child = basisNodeChildren[basisNodeIndex];
2391:                    final Object userObject = this Child.getUserObject();
2392:                    if (userObject instanceof  Integer) {
2393:                        // Integer reference comparison is ok here.
2394:                        if ((Integer) userObject == ParserOutputProcessor.NodeForTypeDeclaration) {
2395:                            // Get the ClassDeclaration children:
2396:                            DefaultMutableTreeNode[] classDeclarationNodes = this 
2397:                                    .getAllChildNodesWithName(
2398:                                            this Child,
2399:                                            ParserOutputProcessor.NodeForClassOrInterfaceDeclaration);
2400:                            for (int classDecIndex = 0; classDecIndex < classDeclarationNodes.length; classDecIndex++) {
2401:                                // Get the ClassBody node children:
2402:                                DefaultMutableTreeNode[] classBodyNodes = this 
2403:                                        .getAllChildNodesWithName(
2404:                                                classDeclarationNodes[classDecIndex],
2405:                                                ParserOutputProcessor.NodeForClassOrInterfaceBody);
2406:                                for (int classBodyIndex = 0; classBodyIndex < classBodyNodes.length; classBodyIndex++) {
2407:                                    // Get the ClassBodyDeclaration node children:
2408:                                    DefaultMutableTreeNode[] classBodyDeclarationNodes = this 
2409:                                            .getAllChildNodesWithName(
2410:                                                    classBodyNodes[classBodyIndex],
2411:                                                    ParserOutputProcessor.NodeForClassOrInterfaceBodyDeclaration);
2412:                                    for (int classBodyDeclarationIndex = 0; classBodyDeclarationIndex < classBodyDeclarationNodes.length; classBodyDeclarationIndex++) {
2413:                                        // The children of the classBodyDeclarationNodes are
2414:                                        // FieldDeclaration, ConstructorDeclaration or MethodDeclaration nodes.
2415:                                        final DefaultMutableTreeNode cbdNode = classBodyDeclarationNodes[classBodyDeclarationIndex];
2416:                                        // The following calls already perform a few simple filterings :
2417:                                        this .deepScanForClassFieldReferences(
2418:                                                fsd, classReferences, cbdNode,
2419:                                                fieldName);
2420:                                    }
2421:                                }
2422:                            } // for classDecIndex
2423:                        } // if
2424:                    } // if
2425:                } // for basisNodeIndex
2426:            } // scanForFieldCallsOf
2427:
2428:            /**
2429:             *  Scans for the left and right sides and void statements and additionally
2430:             *  prefilters the raw results.
2431:             */
2432:            private void deepScanForClassFieldReferences(
2433:                    final FileStructureDescription candidateFSD,
2434:                    final Vector targetVector,
2435:                    final DefaultMutableTreeNode classBodyChildNode,
2436:                    final String fieldName) {
2437:
2438:                // Left side scans:
2439:
2440:                // Deepscan for PrimaryExpression nodes, which have children of the form
2441:                // PrimaryPrefix followed by one or multiple PrimarySuffix nodes,
2442:                // where the PrimaryPrefix node does *NOT* contain an AllocationExpression node.
2443:                //
2444:                // NOTE: There are PrimaryExpression nodes, which contain
2445:                // an PrimaryPrefix node with an AllocationExpression childnode, but these ones are scanned by the
2446:                // the special FieldDeclaration scan in scanReferencedObjects(), where they catch the type
2447:                // of the attribute and collect it, if it's not a simple type or the type of an inner class.
2448:                // Note: The last parameter treescan=true is required. This onecauses the scan to
2449:                //       continue reqursion after each hit, so it catches all objects in the tree.
2450:                //       Example: for the expression a.getx( b.getB() ), it will generate TWO entries:
2451:                //       1) a.getx( b.getB() )   [=the full expression]
2452:                //       2) b.getB()             [=the child in the tree]
2453:                //
2454:
2455:                Vector targetNodes = new Vector();
2456:                // Add name hits in primary expressions [ left sides ]
2457:                this 
2458:                        .deepScanForNodesWithName(targetNodes,
2459:                                classBodyChildNode,
2460:                                ParserOutputProcessor.NodeForPrimaryExpression,
2461:                                true /* treescan */);
2462:                // Add name hits in expressions [ right sides ]
2463:                this 
2464:                        .deepScanForNodesWithName(targetNodes,
2465:                                classBodyChildNode,
2466:                                ParserOutputProcessor.NodeForExpression, true /* treescan */);
2467:                // Add name hits in VariableInitializer nodes [ right sides ]
2468:                this 
2469:                        .deepScanForNodesWithName(
2470:                                targetNodes,
2471:                                classBodyChildNode,
2472:                                ParserOutputProcessor.NodeForVariableInitializer,
2473:                                true /* treescan */);
2474:
2475:                for (int i = 0; i < targetNodes.size(); i++) {
2476:                    final DefaultMutableTreeNode this SearchStartNode = (DefaultMutableTreeNode) targetNodes
2477:                            .elementAt(i);
2478:
2479:                    // This here has been changed compared to the search for method calls.
2480:                    // Here we don't only search PrimaryExpressionNode's with at least
2481:                    // one PrimaryPrefix, but we search in a bigger scope so far.
2482:
2483:                    /* Debug
2484:                    if( thisSearchStartNode.getUserObject() instanceof Integer )
2485:                     {
2486:                       Log.Info("deepScanForClassFieldReferences> hit in fsd " +
2487:                                candidateFSD.className.content +
2488:                                " for node " +
2489:                                ParserTreeNode.GetStringRepresentationForNodeIdentifier(
2490:                                             (Integer)thisSearchStartNode.getUserObject()) );
2491:                     }
2492:                     */
2493:
2494:                    final FieldReferenceEntry entry = this 
2495:                            .scanNodeForFieldCalls(candidateFSD,
2496:                                    this SearchStartNode, fieldName);
2497:                    if (entry != null) {
2498:                        this .addUniqueFieldReferenceEntryToVector(entry,
2499:                                targetVector);
2500:                    }
2501:                } // for i
2502:            } // deepScanForClassFieldReferences
2503:
2504:            /**
2505:             *  Recursive method which scans the passed parentNode down to all
2506:             *  levels and adds any node with the passed nodeName to the targetVector.
2507:             *
2508:             *  treeScan = true: One assumes we have a tree structure, which means
2509:             *                   that nodes with this name can contain children at any level
2510:             *                   with that name again. Therefore the recursion will not stop,
2511:             *                   when a node with the passed name is found.
2512:             *  treeScan = false: Once a node with the passed name is found, the recursion
2513:             *                    stops there and the children of this node (the subtree)
2514:             *                    is not searched.
2515:             *
2516:             */
2517:            private void deepScanForNodesWithName(final Vector targetVector,
2518:                    final DefaultMutableTreeNode parentNode,
2519:                    final Integer nodeNameIdentifier, final boolean treeScan) {
2520:                // Get all level one children:
2521:                final DefaultMutableTreeNode[] allChildren = this 
2522:                        .getChildren(parentNode);
2523:                final Vector searchedNodes = new Vector();
2524:                for (int i = 0; i < allChildren.length; i++) {
2525:                    final DefaultMutableTreeNode this Child = allChildren[i];
2526:                    final Object userObject = this Child.getUserObject();
2527:                    if (userObject instanceof  Integer) // it's a node
2528:                    {
2529:                        // Integer reference comparison is ok here.
2530:                        if ((Integer) userObject == nodeNameIdentifier) {
2531:                            targetVector.addElement(this Child);
2532:                            if (treeScan) {
2533:                                this 
2534:                                        .deepScanForNodesWithName(targetVector,
2535:                                                this Child, nodeNameIdentifier,
2536:                                                treeScan);
2537:                            }
2538:                        } else {
2539:                            this .deepScanForNodesWithName(targetVector,
2540:                                    this Child, nodeNameIdentifier, treeScan);
2541:                        }
2542:                    }
2543:                } // for
2544:            }
2545:
2546:            /**
2547:             *   Concatenates the PrimaryExpression children into one String and
2548:             *   returns it together with the linenumber in a ReferenceEntry.
2549:             */
2550:            private MethodReferenceEntry scanPrimaryExpressionForMethodCalls(
2551:                    final FileStructureDescription candidateFSD,
2552:                    final DefaultMutableTreeNode primaryExpressionNode,
2553:                    final String methodName) {
2554:                MethodReferenceEntry result = null;
2555:                StringWithPosition stringWithPosition = this 
2556:                        .deepScanForIdentifier(primaryExpressionNode,
2557:                                methodName);
2558:                if (stringWithPosition != null) {
2559:                    result = new MethodReferenceEntry(candidateFSD, methodName,
2560:                            stringWithPosition.startLine,
2561:                            stringWithPosition.startColumn,
2562:                            stringWithPosition.endLine,
2563:                            stringWithPosition.endColumn);
2564:                }
2565:                return result;
2566:            } // scanPrimaryExpressionForMethodCalls
2567:
2568:            private FieldReferenceEntry scanNodeForFieldCalls(
2569:                    final FileStructureDescription candidateFSD,
2570:                    final DefaultMutableTreeNode parentNode,
2571:                    final String fieldName) {
2572:                FieldReferenceEntry result = null;
2573:                StringWithPosition stringWithPosition = this 
2574:                        .deepScanForIdentifier(parentNode, fieldName);
2575:                if (stringWithPosition != null) {
2576:                    result = new FieldReferenceEntry(candidateFSD, fieldName,
2577:                            stringWithPosition.startLine,
2578:                            stringWithPosition.startColumn,
2579:                            stringWithPosition.endLine,
2580:                            stringWithPosition.endColumn);
2581:                }
2582:                return result;
2583:            } // scanNodeForFieldCalls
2584:
2585:            private StringWithPosition deepScanForIdentifier(
2586:                    final DefaultMutableTreeNode parentNode,
2587:                    final String identifierName) {
2588:                StringWithPosition stringWithPosition = null;
2589:                final DefaultMutableTreeNode[] children = this 
2590:                        .getChildren(parentNode);
2591:                int lineNumber = -1;
2592:                for (int i = 0; i < children.length; i++) {
2593:                    if (children[i].getUserObject() instanceof  TokenTreeUserObject) {
2594:                        final TokenTreeUserObject tokenContent = (TokenTreeUserObject) children[i]
2595:                                .getUserObject();
2596:                        if (tokenContent.getKind().equals("<IDENTIFIER>")) {
2597:                            if (tokenContent.getContent()
2598:                                    .equals(identifierName)) {
2599:                                stringWithPosition = new StringWithPosition(
2600:                                        identifierName, tokenContent
2601:                                                .getStartLine(), tokenContent
2602:                                                .getStartColumn(), tokenContent
2603:                                                .getEndLine(), tokenContent
2604:                                                .getEndColumn());
2605:                            }
2606:                        }
2607:                    }
2608:                    if (stringWithPosition == null) // recur
2609:                    {
2610:                        stringWithPosition = this .deepScanForIdentifier(
2611:                                children[i], identifierName);
2612:                    }
2613:                    if (stringWithPosition != null) {
2614:                        break;
2615:                    }
2616:                } // for
2617:                return stringWithPosition;
2618:            } // deepScanForIdentifier
2619:
2620:            /**
2621:             *  Recursive version - dives down to any level.
2622:             *  Takes all children of the passed node, and concatenates
2623:             *  all contents.
2624:             *  Additionally, the editor linenumber is returned too.
2625:             *
2626:             *  PrimaryExpression specific:  "new" tokens are skipped.
2627:             */
2628:            private int concatenateLeafContentsOfPrimaryExpression(
2629:                    final DefaultMutableTreeNode primaryExpressionNode,
2630:                    final StringBuffer buffer) {
2631:                final DefaultMutableTreeNode[] children = this 
2632:                        .getChildren(primaryExpressionNode);
2633:                int lineNumber = -1;
2634:                for (int i = 0; i < children.length; i++) {
2635:                    if (children[i].getUserObject() instanceof  TokenTreeUserObject) {
2636:                        final TokenTreeUserObject tokenContent = (TokenTreeUserObject) children[i]
2637:                                .getUserObject();
2638:                        final String content = tokenContent.getContent();
2639:                        lineNumber = tokenContent.getStartLine();
2640:                        // Prefilter:
2641:                        // - The keyword "new" must be skipped
2642:                        if ((!content.equals("new"))) {
2643:                            buffer.append(content);
2644:                        }
2645:                    } else {
2646:                        lineNumber = this 
2647:                                .concatenateLeafContentsOfPrimaryExpression(
2648:                                        children[i], buffer);
2649:                    }
2650:                } // for
2651:                return lineNumber;
2652:            } // concatenateLeafContentsOfPrimaryExpression
2653:
2654:            /**
2655:             *  Starts the parser and returns its output = the compilationRootNode.
2656:             */
2657:            private ParserTreeNode getCompilationUnitNodeFor(
2658:                    final StringBuffer fileTextBuffer, final String fsdClassName) {
2659:                boolean allWasParsedWithSuccess = true;
2660:                // Create a new currentNode, which we will set as
2661:                // new rootnode, once the whole parser operations has been
2662:                // completed. This allows building the whole tree without
2663:                // gui update slowdowns. The current node then is used
2664:                // by the ParserOutputProcessor methods for the build up
2665:                // of the tree :
2666:                // The constructor with an int parameter automatically creates a node
2667:                // which can have children.
2668:                final ParserTreeNode rawParserNode = new ParserTreeNode(
2669:                        ParserOutputProcessor.NodeForRoot);
2670:                this .currentNode = rawParserNode; // now the parser adds the structure here
2671:                final CharArrayReader in = new CharArrayReader(fileTextBuffer
2672:                        .toString().toCharArray());
2673:                final JavaCharStream javaCharStream = new JavaCharStream(in);
2674:                final JavaParserTokenManager tm = new JavaParserTokenManager(
2675:                        javaCharStream);
2676:                // Create a parser and pass this class as ParserOutputProcessor :
2677:                final JavaParser p = new JavaParser(tm, this );
2678:                // Now tell the parser to do its work, which will make the
2679:                // parser call the ParserOutputProcessor methods :
2680:                try {
2681:                    p.CompilationUnit();
2682:                    // When we come here, the parser token tree has been
2683:                    // fully constructed on the rawParserNode.
2684:                    // Now we process that token tree and transform it to
2685:                    // the simplier tree, which is visible to the user and whose
2686:                    // entry objects will tell the editor to jump to the
2687:                    // corresponding editor line.
2688:                } catch (Exception pe) {
2689:                    allWasParsedWithSuccess = false;
2690:                    // The view then will set a red point in the title label.
2691:                    //ystem.out.println("FileComponentsTreeModel: ParseException \n" + pe.getMessage() );
2692:                } catch (Error pError) // The tokenmanager creates errors, not exceptions
2693:                {
2694:
2695:                    //ystem.out.println("SymbolUsageLocationSearch: Parser reports: " + pError.getMessage() +
2696:                    //                   " for " + fsdClassName );
2697:
2698:                    allWasParsedWithSuccess = false;
2699:                    // The view then will set a red point in the title label.
2700:                    //ystem.out.println("FileComponentsTreeModel: ParseException \n" + pe.getMessage() );
2701:                }
2702:                // If we encountered an exception, we still can evaulate
2703:                // at least the parsed elements upto the line, which
2704:                // has caused this exception.
2705:
2706:                // return postprocessed node :
2707:                // The rawParserNode has one child called CompilationUnit,
2708:                // so we pass directly this one :
2709:                return (ParserTreeNode) rawParserNode.getChildAt(0);
2710:            } // getCompilationRootNode
2711:
2712:            /**                            
2713:             *  Implementation of ParserOutputProcessor.
2714:             *  Called by the parser when it encounters a new node.
2715:             */
2716:            public void addNode(final Integer nodeIdentifier) {
2717:                // Insert a new node at the currentnode:
2718:                // Note: The constructor with an int parameter automatically creates
2719:                //       a node, which can have children.
2720:                ParserTreeNode newNode = new ParserTreeNode(nodeIdentifier);
2721:                this .currentNode.add(newNode);
2722:                // and update the currentNode :
2723:                this .currentNode = newNode;
2724:            }
2725:
2726:            /**
2727:             *  Implementation of ParserOutputProcessor.
2728:             *  Called by the parser when it returns from a previously
2729:             *  encountered node (for which it has called addNode)
2730:             */
2731:            public void returnFromNode(final Integer nodeIdentifier) {
2732:                // Just update the currentNode :
2733:                if (this .currentNode.getParent() != null) {
2734:                    this .currentNode = (ParserTreeNode) this .currentNode
2735:                            .getParent();
2736:                }
2737:            }
2738:
2739:            /**
2740:             *  Implementation of ParserOutputProcessor.
2741:             *  Called by the parser when it has encountered a token
2742:             *  at the current treeposition, which is defined by all
2743:             *  already received calls of addNode() and returnFromNode().
2744:             */
2745:            public void addLeaf(final Token token) {
2746:                // tokenImage is defined in the implemented JavaParserConstants Interface.
2747:                String kindString = tokenImage[token.kind];
2748:                TokenTreeUserObject userObject = new TokenTreeUserObject(
2749:                        token.image,
2750:                        kindString,
2751:                        true, // always display kind for token tree's
2752:                        token.beginLine, token.endLine, token.beginColumn,
2753:                        token.endColumn,
2754:                        FileComponentsTreeCellRenderer.UseTokenLeafIcon);
2755:                // The constructor with a TokenTreeUserObject parameter automatically
2756:                // creates a leaf.
2757:                ParserTreeNode newNode = new ParserTreeNode(userObject);
2758:                this .currentNode.add(newNode);
2759:            }
2760:
2761:            /**    
2762:             *  Adds the passed reference to the vector, if the vector doesn't
2763:             *  contain an equal reference already.
2764:             */
2765:            private void addUniqueObjectToVector(final Object object,
2766:                    final Vector vector) {
2767:                boolean isAlreadyExisting = false;
2768:                for (int i = 0; i < vector.size(); i++) {
2769:                    final Object s = vector.elementAt(i);
2770:                    if (s.equals(object)) {
2771:                        isAlreadyExisting = true;
2772:                        break;
2773:                    }
2774:                }
2775:                if (!isAlreadyExisting) {
2776:                    vector.addElement(object);
2777:                }
2778:            } // addUniqueObjectToVector
2779:
2780:            /**
2781:             *  Adds the passed reference to the vector, if the vector doesn't
2782:             *  contain an equal reference already.
2783:             */
2784:            private void addUniqueMethodReferenceEntryToVector(
2785:                    final MethodReferenceEntry entry, final Vector vector) {
2786:                boolean isAlreadyExisting = false;
2787:                for (int i = 0; i < vector.size(); i++) {
2788:                    final MethodReferenceEntry s = (MethodReferenceEntry) vector
2789:                            .elementAt(i);
2790:                    if (s.equals(entry)) {
2791:                        isAlreadyExisting = true;
2792:                        break;
2793:                    }
2794:                }
2795:                if (!isAlreadyExisting) {
2796:                    vector.addElement(entry);
2797:                }
2798:            } // addUniqueMethodReferenceEntryToVector
2799:
2800:            /**
2801:             *  Adds the passed reference to the vector, if the vector doesn't
2802:             *  contain an equal reference already.
2803:             */
2804:            private void addUniqueFieldReferenceEntryToVector(
2805:                    final FieldReferenceEntry entry, final Vector vector) {
2806:                boolean isAlreadyExisting = false;
2807:                for (int i = 0; i < vector.size(); i++) {
2808:                    final FieldReferenceEntry s = (FieldReferenceEntry) vector
2809:                            .elementAt(i);
2810:                    if (s.equals(entry)) {
2811:                        isAlreadyExisting = true;
2812:                        break;
2813:                    }
2814:                }
2815:                if (!isAlreadyExisting) {
2816:                    vector.addElement(entry);
2817:                }
2818:            } // addUniqueFieldReferenceEntryToVector
2819:
2820:            private DefaultMutableTreeNode[] getAllChildNodesWithName(
2821:                    final DefaultMutableTreeNode parentNode,
2822:                    final Integer nodeNameIdentifier) {
2823:                final DefaultMutableTreeNode[] allChildren = this 
2824:                        .getChildren(parentNode);
2825:                final Vector searchedNodes = new Vector();
2826:                for (int i = 0; i < allChildren.length; i++) {
2827:                    final DefaultMutableTreeNode this Child = allChildren[i];
2828:                    final Object userObject = this Child.getUserObject();
2829:                    if (userObject instanceof  Integer) {
2830:                        // Integer reference comparison is ok here.
2831:                        if ((Integer) userObject == nodeNameIdentifier) {
2832:                            searchedNodes.addElement(this Child);
2833:                        }
2834:                    }
2835:                }
2836:                final DefaultMutableTreeNode[] searchedNodeArray = new DefaultMutableTreeNode[searchedNodes
2837:                        .size()];
2838:                searchedNodes.copyInto(searchedNodeArray);
2839:                return searchedNodeArray;
2840:            }
2841:
2842:            /**
2843:             *  Returns all first level children
2844:             */
2845:            private DefaultMutableTreeNode[] getChildren(
2846:                    final DefaultMutableTreeNode parentNode) {
2847:                int childCount = parentNode.getChildCount();
2848:                DefaultMutableTreeNode[] children = new DefaultMutableTreeNode[childCount];
2849:                for (int i = 0; i < childCount; i++) {
2850:                    children[i] = (DefaultMutableTreeNode) parentNode
2851:                            .getChildAt(i);
2852:                } // for
2853:                return children;
2854:            } // getChildren
2855:
2856:            /**
2857:             * A utility method, used for method call location search.
2858:             *
2859:             * It gets all classes of the inheritance tree and all interfaces, which explicitly contain the
2860:             * searched method.
2861:             * @param fsdManager the fsd manager
2862:             * @param basisTargetFSD  one FSD, which contains the searched method explicitly.
2863:             * @param methodName  the name of the searched method. Signatures are not considered here.
2864:             */
2865:            public FileStructureDescription[] getRelatedFSDsContainingMethod(
2866:                    FileStructureDescriptionManager fsdManager,
2867:                    FileStructureDescription basisTargetFSD, String methodName) {
2868:
2869:                // The method, which is searched, is coded inside the source associated with the basisTargetFSD:
2870:                FileStructureDescription[] basisTargetParentFSDs = fsdManager
2871:                        .getParentChainForFSD(basisTargetFSD);
2872:                Vector classesContainingTheSearchedMethod = new Vector();
2873:                classesContainingTheSearchedMethod.addElement(basisTargetFSD);
2874:                // Step one:
2875:                // Search and add all classes, which inherit from the basisTarget class,
2876:                // because these one either are capable of calling the super method of
2877:                // the basisTarget class, or if they have overwritten it, we add them
2878:                // also [easier and less errorprone in general - the programmer could
2879:                // have forgotten, that the method is overwritten and this way
2880:                // is informed about this in some way ]:
2881:                // We need all project fsd's:
2882:                FileStructureDescription[] allProjectFSDs = fsdManager
2883:                        .getAllProjectFSDs();
2884:                FileStructureDescription[] workParentChainFSDs = null;
2885:                // take the highest parent of the basisTargetFSD as reference:
2886:                FileStructureDescription highestParentFSD = basisTargetFSD;
2887:                if (basisTargetParentFSDs != null) {
2888:                    // Follow the chain to get the highest parent, which still lies in the project space:
2889:                    for (int k = 0; k < basisTargetParentFSDs.length; k++) {
2890:                        if (basisTargetParentFSDs[k].belongsToProject) {
2891:                            highestParentFSD = basisTargetParentFSDs[k];
2892:                        } else {
2893:                            break; // left project space
2894:                        }
2895:                    }
2896:                }
2897:                // Search:
2898:                for (int i = 0; i < allProjectFSDs.length; i++) {
2899:                    workParentChainFSDs = fsdManager
2900:                            .getParentChainForFSD_ProjectOnly(allProjectFSDs[i]);
2901:                    if (workParentChainFSDs != null) {
2902:                        for (int k = 0; k < workParentChainFSDs.length; k++) {
2903:                            // reference comparison
2904:                            if (workParentChainFSDs[k] == basisTargetFSD) {
2905:                                // The allProjectFSD[i] is a child of basisTargetFSD, in any level.
2906:                                this .addUniqueObjectToVector(allProjectFSDs[i],
2907:                                        classesContainingTheSearchedMethod);
2908:                            }
2909:                        }
2910:                    }
2911:                } // for
2912:                workParentChainFSDs = null; // assist the GC finally
2913:                allProjectFSDs = null; // assist the GC finally
2914:
2915:                // We make the parentclasses / [mutliple] possible interfaces - tree flat,
2916:                // but only add parentclasses/interfaces, which do contain the searched method [with
2917:                // ANY signature] too:
2918:                // Step two: Just add the basis class, all parents and all interfaces [check for the method after this]:
2919:                Vector allInterfaces = new Vector(0);
2920:                fsdManager.addImplementedInterfaceFSDsOf(basisTargetFSD,
2921:                        allInterfaces);
2922:                // Go back the parentchain and for each parent fsd, test/add implemented
2923:                // interfaces, which contain the method (any signature) too:
2924:                for (int i = 0; i < basisTargetParentFSDs.length; i++) {
2925:                    final FileStructureDescription parentFSD = basisTargetParentFSDs[i];
2926:                    // Only for projectfiles:
2927:                    if (parentFSD.belongsToProject) {
2928:                        this .addUniqueObjectToVector(parentFSD,
2929:                                classesContainingTheSearchedMethod);
2930:                        // Add all implemented interfaces:
2931:                        fsdManager.addImplementedInterfaceFSDsOf(parentFSD,
2932:                                allInterfaces);
2933:                    }
2934:                } // for
2935:                // Now add all interface fsd's to the classesContainingTheSearchedMethod vector,
2936:                // IF they contain a method (with any signature) of the wanted name:
2937:                for (int k = 0; k < allInterfaces.size(); k++) {
2938:                    if (this .hasMemberMethodWithName(
2939:                            (FileStructureDescription) allInterfaces
2940:                                    .elementAt(k), methodName)) {
2941:                        classesContainingTheSearchedMethod
2942:                                .addElement(allInterfaces.elementAt(k));
2943:                        //final FileStructureDescription iface = (FileStructureDescription)allInterfaces.elementAt(k);
2944:                        //ystem.out.println("Interface " + iface.fullyQualifiedClassNameBuffer.toString() +
2945:                        //                   "  contains method  " + methodName );
2946:                    }
2947:                }
2948:                // Copy them into an array:
2949:                final FileStructureDescription[] targetClassFSDs = new FileStructureDescription[classesContainingTheSearchedMethod
2950:                        .size()];
2951:                classesContainingTheSearchedMethod.copyInto(targetClassFSDs);
2952:                return targetClassFSDs;
2953:            } // getRelatedFSDsContainingMethod
2954:
2955:            private boolean hasMemberMethodWithName(
2956:                    final FileStructureDescription fsd, final String methodName) {
2957:                boolean methodNameFound = false;
2958:                for (int i = 0; i < fsd.methodDescriptions.size(); i++) {
2959:                    final FileStructureDescriptionForMethod methodFSD = (FileStructureDescriptionForMethod) fsd.methodDescriptions
2960:                            .elementAt(i);
2961:                    if (methodFSD.name.content.equals(methodName)) {
2962:                        methodNameFound = true;
2963:                        break;
2964:                    }
2965:                } // for
2966:                return methodNameFound;
2967:            } // hasMethodWithName 
2968:
2969:            /**
2970:             * A utility method, used for attribute call location search.
2971:             *
2972:             * It gets all classes of the inheritance tree and all interfaces, which explicitly contain the
2973:             * searched attribute.
2974:             * @param fsdManager the fsd manager
2975:             * @param basisTargetFSD  one FSD, which contains the searched method explicitly.
2976:             * @param attributeName  the name of the searched attribute.
2977:             */
2978:            public FileStructureDescription[] getRelatedFSDsContainingAttribute(
2979:                    FileStructureDescriptionManager fsdManager,
2980:                    FileStructureDescription basisTargetFSD,
2981:                    String attributeName) {
2982:                FileStructureDescription[] basisTargetParentFSDs = fsdManager
2983:                        .getParentChainForFSD(basisTargetFSD);
2984:                Vector classesContainingTheSearchedAttribute = new Vector();
2985:                classesContainingTheSearchedAttribute
2986:                        .addElement(basisTargetFSD);
2987:                // Step one:
2988:                // Search and add all classes, which inherit from the basisTarget class,
2989:                // because these one either are capable of calling the super method of
2990:                // the basisTarget class, or if they have overwritten it, we add them
2991:                // also [easier and less errorprone in general - the programmer could
2992:                // have forgotten, that the method is overwritten and this way
2993:                // is informed about this in some way ]:
2994:                // We need all project fsd's:
2995:                FileStructureDescription[] allProjectFSDs = fsdManager
2996:                        .getAllProjectFSDs();
2997:                FileStructureDescription[] workParentChainFSDs = null;
2998:                // take the highest parent of the basisTargetFSD as reference:
2999:                FileStructureDescription highestParentFSD = basisTargetFSD;
3000:                if (basisTargetParentFSDs != null) {
3001:                    // Follow the chain to get the highest parent, which still lies in the project space:
3002:                    for (int k = 0; k < basisTargetParentFSDs.length; k++) {
3003:                        if (basisTargetParentFSDs[k].belongsToProject) {
3004:                            highestParentFSD = basisTargetParentFSDs[k];
3005:                        } else {
3006:                            break; // left project space
3007:                        }
3008:                    }
3009:                }
3010:                // Search:
3011:                for (int i = 0; i < allProjectFSDs.length; i++) {
3012:                    workParentChainFSDs = fsdManager
3013:                            .getParentChainForFSD_ProjectOnly(allProjectFSDs[i]);
3014:                    if (workParentChainFSDs != null) {
3015:                        for (int k = 0; k < workParentChainFSDs.length; k++) {
3016:                            // reference comparison
3017:                            if (workParentChainFSDs[k] == basisTargetFSD) {
3018:                                // The allProjectFSD[i] is a child of basisTargetFSD, in any level.
3019:                                this .addUniqueObjectToVector(allProjectFSDs[i],
3020:                                        classesContainingTheSearchedAttribute);
3021:                            }
3022:                        }
3023:                    }
3024:                } // for
3025:                workParentChainFSDs = null; // assist the GC finally
3026:                allProjectFSDs = null; // assist the GC finally
3027:
3028:                // We make the parentclasses / [mutliple] possible interfaces - tree flat,
3029:                // but only add parentclasses/interfaces, which do contain the searched method [with
3030:                // ANY signature] too:
3031:                // Step two: Just add the basis class, all parents and all interfaces [check for the method after this]:
3032:                Vector allInterfaces = new Vector(0);
3033:                fsdManager.addImplementedInterfaceFSDsOf(basisTargetFSD,
3034:                        allInterfaces);
3035:                // Go back the parentchain and for each parent fsd, test/add implemented
3036:                // interfaces, which contain the attribute as member :
3037:                for (int i = 0; i < basisTargetParentFSDs.length; i++) {
3038:                    final FileStructureDescription parentFSD = basisTargetParentFSDs[i];
3039:                    // Only for projectfiles:
3040:                    if (parentFSD.belongsToProject) {
3041:                        this .addUniqueObjectToVector(parentFSD,
3042:                                classesContainingTheSearchedAttribute);
3043:                        // Add all implemented interfaces:
3044:                        fsdManager.addImplementedInterfaceFSDsOf(parentFSD,
3045:                                allInterfaces);
3046:                    }
3047:                } // for
3048:                // Now add all interface fsd's to the classesContainingTheSearchedAttribute vector,
3049:                // IF they contain an attribute  the wanted name:
3050:                for (int k = 0; k < allInterfaces.size(); k++) {
3051:                    if (this .hasMemberAttributeWithName(
3052:                            (FileStructureDescription) allInterfaces
3053:                                    .elementAt(k), attributeName)) {
3054:                        classesContainingTheSearchedAttribute
3055:                                .addElement(allInterfaces.elementAt(k));
3056:                        //final FileStructureDescription iface = (FileStructureDescription)allInterfaces.elementAt(k);
3057:                        //ystem.out.println("Interface " + iface.fullyQualifiedClassNameBuffer.toString() +
3058:                        //                   "  contains method  " + methodName );
3059:                    }
3060:                }
3061:                // Copy them into an array:
3062:                final FileStructureDescription[] targetClassFSDs = new FileStructureDescription[classesContainingTheSearchedAttribute
3063:                        .size()];
3064:                classesContainingTheSearchedAttribute.copyInto(targetClassFSDs);
3065:                return targetClassFSDs;
3066:            }
3067:
3068:            private boolean hasMemberAttributeWithName(
3069:                    final FileStructureDescription fsd,
3070:                    final String attributeName) {
3071:                boolean attributeNameFound = false;
3072:                for (int i = 0; i < fsd.fieldDescriptions.size(); i++) {
3073:                    final FileStructureDescriptionForField fieldFSD = (FileStructureDescriptionForField) fsd.fieldDescriptions
3074:                            .elementAt(i);
3075:                    if (fieldFSD.objectNameWithPosition.content
3076:                            .equals(attributeName)) {
3077:                        attributeNameFound = true;
3078:                        break;
3079:                    }
3080:                } // for
3081:                return attributeNameFound;
3082:            } // hasMemberAttributeWithName
3083:
3084:            /**
3085:             *  GC assistance
3086:             */
3087:            public void freeMemory() {
3088:                this .projectFrame = null;
3089:                if (this .currentNode != null) {
3090:                    this .currentNode.removeAllChildren();
3091:                    this .currentNode = null;
3092:                }
3093:            } // freeMemory
3094:
3095:        } // SymbolUsageLocationSearch
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.