Source Code Cross Referenced for CodeCompletionSearch.java in  » IDE » Schmortopf » Schmortopf » JavaSourceEditor » CodeCompletion » 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.CodeCompletion 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package Schmortopf.JavaSourceEditor.CodeCompletion;
0002:
0003:        /**                                                                                         
0004:         *  This is the worker class of the CodeCompletion.                
0005:         *                                                                                      
0006:         *  An instance of this class is created by the               
0007:         *  CodeCompletion object for each search.                           
0008:         *                                                      
0009:         */
0010:
0011:        import java.util.*;
0012:        import java.awt.*;
0013:        import java.awt.event.*;
0014:        import javax.swing.*;
0015:        import javax.swing.event.*;
0016:        import javax.swing.text.*;
0017:        import java.lang.reflect.Modifier;
0018:
0019:        import Schmortopf.FileStructure.*;
0020:        import Schmortopf.FileStructure.Descriptions.*;
0021:        import Schmortopf.JavaSourceEditor.*;
0022:        import Schmortopf.JavaSourceEditor.DocumentStyle.*;
0023:        import Schmortopf.Utility.BooleanInteger;
0024:        import Schmortopf.Utility.StringUtilities;
0025:        import Language.Language;
0026:        import Shared.Logging.Log;
0027:
0028:        public class CodeCompletionSearch {
0029:
0030:            private final String basisIdentifier;
0031:            private int insertPosition;
0032:            private EditorPanel editorPanel;
0033:            private FileStructureDescription toplevelBasisFSD;
0034:            private FileStructureDescriptionManager fileStructureDescriptionManager;
0035:
0036:            private String foundIdentifierName = "";
0037:            private FSDSearchResult fsdSearchResult = null;
0038:            // This is set and can be obtained, after performSearch() has found a result.
0039:            // Depending on the search type, this can be an objectname or a classname
0040:
0041:            // All fsd's for which we updated their transient fields are added to
0042:            // this Vector, so we can release all transient fields before this object
0043:            // is disposed. Prevents memory explosions.
0044:            // See freeAllTransientFields().                                                             
0045:            private Vector fsdsWithUpdatedTransientFields = new Vector();
0046:
0047:            /**
0048:             *  Constructor.
0049:             *              
0050:             *  NOTE: You MUST call freeAllTransientFields(), when the object isn't used anymore,
0051:             *  so that any updated transient fields are released.
0052:             *  Otherwise the memory explodes.
0053:             *
0054:             */
0055:            public CodeCompletionSearch(
0056:                    final String basisIdentifier,
0057:                    final int insertPosition,
0058:                    final EditorPanel editorPanel,
0059:                    final FileStructureDescription currentlyEditedFSD,
0060:                    final FileStructureDescriptionManager fileStructureDescriptionManager) {
0061:                this .basisIdentifier = basisIdentifier;
0062:                this .insertPosition = insertPosition;
0063:                this .editorPanel = editorPanel;
0064:                this .toplevelBasisFSD = currentlyEditedFSD;
0065:                this .fileStructureDescriptionManager = fileStructureDescriptionManager;
0066:            } // Constructor                                          
0067:
0068:            /**
0069:             *  The method, which performs the search using the
0070:             *  parameters passed to the constructor.
0071:             *
0072:             *  Note: This is called from OUTSIDE the eventdispatch thread.
0073:             */
0074:            public CodeCompletionListEntry[] performSearch(
0075:                    final int caretLineNumber) {
0076:
0077:                //Log.Info("started for basisIdentifier = " + this.basisIdentifier );
0078:                //long startTime = System.currentTimeMillis();    
0079:                //new Throwable().printStackTrace();
0080:
0081:                CodeCompletionListEntry[] codeCompletionListEntryArray = null; // the return type
0082:
0083:                // This is used for storing the search result of this search.
0084:                // It can be fetched later using this.getFoundFSDSearchResult().
0085:                this .fsdSearchResult = null;
0086:
0087:                // The caret can lie in one or multiple anonymous classes.
0088:                // Therefore we create the chain of anonymous classes containing the caret position,
0089:                // which then is used for tracking additional visible objects in the
0090:                // deepest anonymous class the caret is in, and for limiting the scope of all
0091:                // pther classes including the toplevel class, which still is the one containing
0092:                // the outer scope given by the package scope and the import statements.
0093:                // Chain order: The deepest anonymous class is the last entry.
0094:                FileStructureDescription[] anonymousClassChain = this 
0095:                        .createTheAnonymousClassChainFor(this .toplevelBasisFSD,
0096:                                caretLineNumber);
0097:
0098:                // One exception: If the basisIdentifier starts with a " sign, it is a String literal
0099:                // and we don't have to search :
0100:                if (this .basisIdentifier.length() > 0) {
0101:                    if (this .basisIdentifier.charAt(0) == '"') {
0102:                        // It is a String literal, so we don't have to search :
0103:                        FileStructureDescription fsd = this .fileStructureDescriptionManager
0104:                                .searchFSD("java.lang.String");
0105:                        // Like in the (usual) case below, where we actually search the fsd, we also have
0106:                        // to update the transient fields here :
0107:                        if (fsd != null) {
0108:                            // Set it :
0109:                            this .fsdSearchResult = new FSDSearchResult(fsd,
0110:                                    false);
0111:                            // Caution: Always use this member method for updating the transient fields,
0112:                            //          so they are released again when freeAllTransientFields() is called.
0113:                            this .updateTransientFieldsFor(fsd);
0114:                            //ystem.out.println("CC> String literal detected");
0115:                        }
0116:                    }
0117:                }
0118:                // Search ( if it hasn't been found above already ):
0119:                if (this .fsdSearchResult == null) {
0120:                    this .fsdSearchResult = this 
0121:                            .search_FileStructureDescription(caretLineNumber,
0122:                                    anonymousClassChain);
0123:                }
0124:
0125:                // Create the codeCompletionListEntryArray, if the FSDSearchResult contains an fsd.
0126:                // If it only contains a simpletype we are finished here. The result still is used
0127:                // in this case by calls to this.getFoundFSDSearchResult() at a later time maybe.
0128:
0129:                // Continue, if we have found a result with an fsd :
0130:
0131:                //boolean debuuug = (this.fsdSearchResult != null);
0132:                //ystem.out.println(" this.fsdSearchResult != null is " + debuuug );
0133:
0134:                if (this .fsdSearchResult != null) {
0135:                    if ((this .fsdSearchResult.getFileStructureDescription() != null)
0136:                            && (!this .fsdSearchResult.getIsJavaArrayObject())) {
0137:
0138:                        //ystem.out.println("CCSearch.performSearch(): fsd result has been found.");
0139:
0140:                        // Set the name of the found class, so that it can be retrieved later by the caller:
0141:                        this .foundIdentifierName = this .fsdSearchResult
0142:                                .getFileStructureDescription().className.content;
0143:                        // If the basisIdentifier is a point-delimited identifier, where
0144:                        // the last token has the name of the class, or if it's a simple string
0145:                        // which is the same as the simple classname, it's a
0146:                        // class reference and in this case, we ONLY must show its
0147:                        // static class attributes and methods :
0148:                        boolean onlyShowStaticAttributesAndMethods = false;
0149:                        String[] tokens = this .decompose(this .basisIdentifier);
0150:                        String lastToken = tokens[tokens.length - 1];
0151:                        //ystem.out.println("CCSearch LastToken = " + lastToken );
0152:                        if (lastToken
0153:                                .equals(this .fsdSearchResult
0154:                                        .getFileStructureDescription().className.content)) {
0155:                            onlyShowStaticAttributesAndMethods = true;
0156:                            // For better user feedback, we tell the user in the title, that only
0157:                            // static members will be displayed :
0158:                            this .foundIdentifierName += "   ["
0159:                                    + Language.Translate("class contents")
0160:                                    + "]";
0161:                        }
0162:                        // Collect the entries :
0163:                        codeCompletionListEntryArray = this 
0164:                                .selectVisibleEntriesFrom(this .fsdSearchResult
0165:                                        .getFileStructureDescription(),
0166:                                        onlyShowStaticAttributesAndMethods,
0167:                                        anonymousClassChain);
0168:                    } else {
0169:                        if (this .fsdSearchResult.getIsJavaArrayObject()) {
0170:                            // A Java array object just has one single member attribute, which is length :
0171:                            // Set the name of the found class, so that it can be retrieved later by the caller:
0172:                            this .foundIdentifierName = Language
0173:                                    .Translate("Java Array Object");
0174:
0175:                            FileStructureDescriptionForField arrayAttribute = new FileStructureDescriptionForField(
0176:                                    0, true, new BooleanInteger(false, 0), "",
0177:                                    "int", "length");
0178:                            codeCompletionListEntryArray = new CodeCompletionListEntry[1];
0179:                            codeCompletionListEntryArray[0] = new CodeCompletionListEntry(
0180:                                    this .fsdSearchResult
0181:                                            .getFileStructureDescription(),
0182:                                    this .fileStructureDescriptionManager,
0183:                                    arrayAttribute, true) {
0184:                                public void run() {
0185:                                    try {
0186:                                        final int offset = insertPosition;
0187:                                        final String string = "length";
0188:                                        final Style style = StylesFactory
0189:                                                .GetEditorTextStyle();
0190:                                        editorPanel.getEditor().getDocument()
0191:                                                .insertString(offset, string,
0192:                                                        style);
0193:                                    } catch (Exception ouiwermnb) {
0194:                                        ouiwermnb.printStackTrace();
0195:                                    }
0196:                                }
0197:                            };
0198:                        }
0199:                    }
0200:                } // if fsdSearchResult != null
0201:
0202:                /* Debug Output Start -----------------
0203:                Log.Info("CC>> CCSearch.performSearch() Result:");
0204:                if( codeCompletionListEntryArray == null )
0205:                 {
0206:                   Log.Info("CC>> codeCompletionListEntryArray is null.");
0207:                 }
0208:                else
0209:                 {
0210:                   for( int i=0; i < codeCompletionListEntryArray.length; i++ )
0211:                    {
0212:                      Log.Info("CC>> Entry " + i + " : ");
0213:                      CodeCompletionListEntry entry = (CodeCompletionListEntry)codeCompletionListEntryArray[i];
0214:                      if( entry.parentFSD == null )
0215:                       {
0216:                         Log.Info("CC>> parentFSD: null");
0217:                       }
0218:                      else
0219:                       {
0220:                         Log.Info("CC>> parentFSD: " + entry.parentFSD.fullyQualifiedClassNameBuffer.toString() );
0221:                       }
0222:
0223:                      if( entry.methodFSD == null )
0224:                       {
0225:                         Log.Info("CC>> methodFSD: null");
0226:                       }
0227:                      else
0228:                       {
0229:                         Log.Info("CC>> methodFSD: " + entry.methodFSD.getShortTextDescription( false,true ) );
0230:                       }
0231:
0232:                      if( entry.fieldFSD == null )
0233:                       {
0234:                         Log.Info("CC>> fieldFSD: null");
0235:                       }
0236:                      else
0237:                       {
0238:                         Log.Info("CC>> fieldFSD: " + entry.fieldFSD.getFullyQualifiedClassName() );
0239:                       }
0240:
0241:                      if( entry.parameters == null )
0242:                       {
0243:                         Log.Info("CC>> parameters: null");
0244:                       }
0245:                      else
0246:                       {
0247:                         Log.Info("CC>> parameters: #elements= " + entry.parameters.length );
0248:                       }
0249:                      Log.Info("CC>> isTopLevel: " + entry.getIsTopLevel() );
0250:                    }
0251:                 } // else
0252:                // Debug Output End ----------------- */
0253:
0254:                //long elapsedTime = System.currentTimeMillis() - startTime;
0255:                //Log.Info("ends. elapsed time [ms] " + elapsedTime );
0256:                return codeCompletionListEntryArray;
0257:            } // performSearch
0258:
0259:            /**
0260:             *  The caret can lie in one or multiple anonymous classes.
0261:             *  Therefore we create the chain of anonymous classes containing the caret position,
0262:             *  which then is used for tracking additional visible objects in the
0263:             *  deepest anonymous class the caret is in, and for limiting the scope of all
0264:             *  other classes including the toplevel class, which still is the one containing
0265:             *  the outer scope given by the package scope and the import statements.
0266:             *  Chain order: The deepest anonymous class is the last entry.
0267:             *
0268:             *  toplevelBasisFSD must be an FSD associated with a file displayed int the editor,
0269:             *  with associated caretLineNumber.
0270:             */
0271:            public FileStructureDescription[] createTheAnonymousClassChainFor(
0272:                    FileStructureDescription toplevelBasisFSD,
0273:                    int caretLineNumber) {
0274:                Vector anonymousClassChainVectorForCaretPosition = new Vector();
0275:                // First just add all, which contain the caretposition :
0276:                for (int i = 0; i < this .toplevelBasisFSD.localBlockAnonymousClasses
0277:                        .size(); i++) {
0278:                    FileStructureDescription anonymousFSD = (FileStructureDescription) this .toplevelBasisFSD.localBlockAnonymousClasses
0279:                            .elementAt(i);
0280:                    if ((caretLineNumber >= anonymousFSD.scopeStartLine)
0281:                            && (caretLineNumber <= anonymousFSD.scopeEndLine)) {
0282:                        anonymousClassChainVectorForCaretPosition
0283:                                .addElement(anonymousFSD);
0284:                    }
0285:                } // for
0286:                // Then sort them : [on the fly - normally its only one or two anonymous classes..]
0287:                FileStructureDescription iFSD = null;
0288:                int iSpan = 0;
0289:                FileStructureDescription kFSD = null;
0290:                int kSpan = 0;
0291:                for (int i = 0; i < anonymousClassChainVectorForCaretPosition
0292:                        .size(); i++) {
0293:                    iFSD = (FileStructureDescription) anonymousClassChainVectorForCaretPosition
0294:                            .elementAt(i);
0295:                    iSpan = iFSD.scopeEndLine - iFSD.scopeStartLine;
0296:                    for (int k = anonymousClassChainVectorForCaretPosition
0297:                            .size() - 1; k > i; k--) {
0298:                        kFSD = (FileStructureDescription) anonymousClassChainVectorForCaretPosition
0299:                                .elementAt(k);
0300:                        kSpan = kFSD.scopeEndLine - kFSD.scopeStartLine;
0301:                        if (kSpan > iSpan) {
0302:                            anonymousClassChainVectorForCaretPosition
0303:                                    .setElementAt(kFSD, i);
0304:                            anonymousClassChainVectorForCaretPosition
0305:                                    .setElementAt(iFSD, k);
0306:                            iFSD = kFSD;
0307:                            iSpan = kSpan;
0308:                        }
0309:                    }
0310:                }
0311:                // Put it into an array :
0312:                FileStructureDescription[] anonymousClassChain = new FileStructureDescription[anonymousClassChainVectorForCaretPosition
0313:                        .size()];
0314:                anonymousClassChainVectorForCaretPosition
0315:                        .copyInto(anonymousClassChain);
0316:                anonymousClassChainVectorForCaretPosition.setSize(0);
0317:                return anonymousClassChain;
0318:            } // createTheAnonymousClassChainFor
0319:
0320:            /**
0321:             *  Once performSearch has been called, this will return the
0322:             *  name of the class or object associated with the found fsd.
0323:             *  It is used for the CC popup title.
0324:             */
0325:            public String getFoundIdentifierName() {
0326:                return this .foundIdentifierName;
0327:            }
0328:
0329:            /**
0330:             *  Once performSearch() has been called, this will return the
0331:             *  found fsd search result.
0332:             */
0333:            public FSDSearchResult getFoundFSDSearchResult() {
0334:                return this .fsdSearchResult;
0335:            }
0336:
0337:            /**
0338:             *  Searches the FSD given by the basisIdentifier taking into account
0339:             *  the scopes given by the caretLineNumber in the currentlyEditedFSD.
0340:             *
0341:             *  Note: The returned fsd will have transient fields set, and the
0342:             *        caller MUST release them, otherwise the memory will
0343:             *        increase on every call unnecessarily.
0344:             */
0345:            public FSDSearchResult search_FileStructureDescription(
0346:                    final int caretLineNumber,
0347:                    FileStructureDescription[] anonymousClassChain) {
0348:                // Caution: Always use this member method for updating the transient fields,
0349:                //          so they are released again when freeAllTransientFields() is called.
0350:                this .updateTransientFieldsFor(this .toplevelBasisFSD);
0351:
0352:                FileStructureDescription currentResultDescription = null;
0353:                String simpletype = null;
0354:
0355:                boolean isJavaArrayObject = false;
0356:                // The raw basisIdentifier can have the form a.b.c
0357:                // where all tokens can require translation.
0358:                // Easy Example :   System.
0359:                // Complex but still easy :  System.out.
0360:                // Example which needs translation :  MyClass.GetMemberAttribute().
0361:                // where getMemberAttribute() returns the class util.TestClass
0362:                // is translated into class util.TestClass.
0363:                // Same goes for just a nonstatic method getMemberAttribute().
0364:                // -> Methods have to be replaced by their returntypes.
0365:                //
0366:                // Additionally the first few tokens can form a package name.
0367:                //
0368:                // Note, that typecasts at the beginning will be removed :
0369:                // If the identifier has the form (type)a.b.c, the typecast (type)
0370:                // just will be removed, because it is of no interest for the CodeCompletion
0371:                // and of course would deny proper operation.
0372:                //
0373:                // Additionally the identifier can start with "new XXX", which means that
0374:                // XXX is created.
0375:
0376:                // decompose() decomposes after point delimiters, but is able to distinguish
0377:                // the parser tree levels created by openening/closing brackets. It only
0378:                // decomposes the toplevel.
0379:                final String[] basisIdentifierTokens = this 
0380:                        .decompose(basisIdentifier);
0381:
0382:                /*
0383:                for( int i=0; i < basisIdentifierTokens.length; i++ )
0384:                 {
0385:                   Log.Info("basisIdentifierTokens["+i+"]= " + basisIdentifierTokens[i] );
0386:                 }
0387:                 */
0388:
0389:                // Create an array which informs for each identifier, if a cast has priority,
0390:                // or if just the last token gives the result for the CC:
0391:                boolean[] castHasPriority = new boolean[basisIdentifierTokens.length];
0392:                String id;
0393:                for (int i = 0; i < basisIdentifierTokens.length; i++) {
0394:                    // If one of the elements starts with an opening bracket, which
0395:                    // only is closed at the end of the string, remove both brackets:
0396:                    id = basisIdentifierTokens[i];
0397:                    castHasPriority[i] = false;
0398:                    while (id.startsWith("(")
0399:                            && this .getPositionOfClosingBracket(id, 0) == id
0400:                                    .length() - 1) {
0401:                        id = id.substring(1, id.length() - 1);
0402:                        castHasPriority[i] = true;
0403:                    }
0404:                    basisIdentifierTokens[i] = id;
0405:                    // If castHasPriority is false and there is a typecast, remove it,
0406:                    // so the detection works:
0407:                    if (!castHasPriority[i]) {
0408:                        // In this case, possible typecasts at the beginning of the line have no
0409:                        // effect for the CC, because the FSD is determined by the type of the last
0410:                        // identifier, so remove the typecast, otherwise it would make the detections fail:
0411:                        basisIdentifierTokens[i] = this 
0412:                                .checkRemoveCastIn(basisIdentifierTokens[i]);
0413:                    }
0414:                } // for
0415:
0416:                FSDSearchResult fsdSearchResult = null;
0417:                if (basisIdentifierTokens.length > 0) {
0418:                    final StringBuffer currentIdentifier = new StringBuffer(
0419:                            this .basisIdentifier.length());
0420:                    currentIdentifier.append(basisIdentifierTokens[0]);
0421:                    FileStructureDescription currentScopeDescription = this .toplevelBasisFSD; // scope init
0422:                    // Flag: Once an FSD has been found (after we went through a complete
0423:                    //       qualifier part, like java.lang.System, all subsequent loop
0424:                    //       runs must find an FSD as well - if one subsequent FSD search
0425:                    //       fails, the basisIdentifier does not point to an existent
0426:                    //       FSD and we must break.
0427:                    boolean initialFSDHasBeenFound = false;
0428:
0429:                    //ystem.out.println("CCSearch: nr of tokens = " + basisIdentifierTokens.length );
0430:
0431:                    // Accumulate: Pass the tokens one after each other while following
0432:                    // with the FileStructureDescriptions. In each run, the algorithm tries
0433:                    // to localize the current single token (without points) in the
0434:                    // FileStructureDescription found on the previous runs.
0435:
0436:                    // previousIdentifier is used for detecting scope extensions of the form
0437:                    // <Class>this.
0438:                    // which is used in inner classes or anonymous classes for
0439:                    // accessing member objects of the enclosing toplevel class.
0440:                    String previousIdentifier = ""; // empty string initially
0441:
0442:                    for (int tokenIndex = 0; tokenIndex < basisIdentifierTokens.length; tokenIndex++) {
0443:
0444:                        if (tokenIndex > 0) // see comments above for the meaning of previousIdentifier
0445:                        {
0446:                            previousIdentifier = basisIdentifierTokens[tokenIndex - 1];
0447:                        }
0448:
0449:                        //ystem.out.println("++++++++++++++++++++++++++++++ search_FileStructureDescription run ++++++++++++++ ");
0450:                        //ystem.out.println("+> basisIdentifierTokens[tokenIndex] = " + basisIdentifierTokens[tokenIndex] );
0451:                        //ystem.out.println("+>  castHasPriority[ tokenIndex ] = " +  castHasPriority[ tokenIndex ] );
0452:
0453:                        fsdSearchResult = null; // reset for each loop run
0454:
0455:                        // Special processing for anonymous classes:
0456:                        // The passed anonymousClassChain is related to (caretpositions of) the
0457:                        // toplevelBasisFSD, therefore we MUST clear it, when the current scope
0458:                        // leaves that FSD inside this loop :
0459:                        if (currentScopeDescription != this .toplevelBasisFSD) {
0460:                            // Setting zero length signalizes no anynomous chain :
0461:                            anonymousClassChain = new FileStructureDescription[0];
0462:                        }
0463:
0464:                        // Special case for a term enclosed by brackets, which contains a typecast
0465:                        // at its beginning: In this case, the FSD is given by the typecast,
0466:                        // and additionally:
0467:                        // The enclosing brackets have already been removed below and castHasPriority[i] is true:
0468:                        if (castHasPriority[tokenIndex]) {
0469:
0470:                            //ystem.out.println(".....................................castHasPriority TRUE");
0471:
0472:                            // 0) Test, if the identifier statement starts with a typecast.
0473:                            //    If it does, try to resolve the FSD of the typecast and take it as result:
0474:                            //    The number of the typeCast attribute is the array dimension. 1 for single types.
0475:                            NumberedString typeCast = this 
0476:                                    .checkReturnCastIn(basisIdentifierTokens[tokenIndex]);
0477:                            if (typeCast.content != null) {
0478:
0479:                                //ystem.out.println("CCSearch: search_FileStructureDescription: CAST DETECTED.");
0480:
0481:                                // Although we don't have a field here, getFSDForField() does right what one wants:
0482:                                FileStructureDescription castFSD = this .fileStructureDescriptionManager
0483:                                        .getFSDForField(typeCast.content,
0484:                                                currentScopeDescription);
0485:                                if (castFSD != null) {
0486:
0487:                                    //ystem.out.println("CCSearch: search_FileStructureDescription: CAST RESOLVED: class= " +
0488:                                    //                   castFSD.fullyQualifiedClassNameBuffer.toString() );
0489:
0490:                                    // typeCast.number == array dimension [ 0 for single types ]
0491:                                    boolean is_Array = (typeCast.number > 0);
0492:                                    fsdSearchResult = new FSDSearchResult(
0493:                                            castFSD, is_Array);
0494:                                }
0495:                            } // if
0496:                            else {
0497:                                //ystem.out.println("CCSearch: search_FileStructureDescription: checkReturnCastIn returned FALSE");
0498:                            }
0499:                        } else {
0500:                            //ystem.out.println(".....................................castHasPriority FALSE");
0501:                        }
0502:
0503:                        // 1) Test, if the identifier statement is an object creation and starts
0504:                        //    with the keyword "new" followed by a non java identifier character.
0505:                        //    If this is the case, we get the classname directly :
0506:                        if (fsdSearchResult == null) {
0507:                            fsdSearchResult = this 
0508:                                    .searchForClassCreatorStatement(
0509:                                            caretLineNumber,
0510:                                            currentScopeDescription,
0511:                                            currentIdentifier.toString());
0512:                        }
0513:
0514:                        // 2) not found ? -> Search for an FSD in the current scope (includes importstatements) :
0515:                        //    The scope is given by currentDescription ( = currentlyEditedFSD initially, see above)
0516:                        //    If the cursor is inside anonymous classes, the scope is updated accordingly.
0517:                        if ((fsdSearchResult == null)
0518:                                && (previousIdentifier != null)) {
0519:                            fsdSearchResult = this .searchForClassFSD(
0520:                                    caretLineNumber, currentScopeDescription,
0521:                                    currentIdentifier.toString(),
0522:                                    anonymousClassChain, previousIdentifier);
0523:                            /* Debug:
0524:                            if( foundClassFSD != null )
0525:                             {
0526:                               ystem.out.println("XX searchForClassFSD->fsd= " + foundClassFSD.className.content );
0527:                               ystem.out.println("XX searchForClassFSD->inheritedmethods= " + foundClassFSD.inheritedMethodDescriptions.size() );
0528:                               ystem.out.println("XX searchForClassFSD->inheritedfields= " + foundClassFSD.inheritedFieldDescriptions.size() );
0529:                             }
0530:                            else
0531:                             {
0532:                               ystem.out.println("XX searchForClassFSD->No fsd found");
0533:                             }
0534:                             */
0535:
0536:                        } // if
0537:
0538:                        // 3) not found ? -> Search for a local or a member attribute class in the current scope :
0539:                        if (fsdSearchResult == null) {
0540:                            //ystem.out.println("CC: Search for member attribute class");
0541:                            fsdSearchResult = this .searchForAttributeClassFSD(
0542:                                    currentScopeDescription,
0543:                                    currentScopeDescription, currentIdentifier
0544:                                            .toString(), caretLineNumber,
0545:                                    anonymousClassChain);
0546:                        }
0547:
0548:                        // 4) not found ? -> Search for a method in the current scope :
0549:                        if (fsdSearchResult == null) {
0550:                            //ystem.out.println("CC: Search for method returntype class");
0551:                            fsdSearchResult = this 
0552:                                    .searchForMethodReturnTypeFSD(
0553:                                            currentScopeDescription,
0554:                                            currentIdentifier.toString(),
0555:                                            caretLineNumber,
0556:                                            anonymousClassChain);
0557:                        }
0558:
0559:                        // Search completed - adjust parameters for the next run,
0560:                        // if we have found a non-simple result :
0561:                        if ((fsdSearchResult != null)
0562:                                && (fsdSearchResult
0563:                                        .getFileStructureDescription() != null)) {
0564:
0565:                            //ystem.out.println("CCSearch: search_FileStructureDescription: fsdSearchResult FOUND");
0566:
0567:                            // Update the transient fields, as stated in the method comment.
0568:                            // This is needed for tasks of the caller, as well as for tasks
0569:                            // in one of the above methods, when this fsd comes in as argument
0570:                            // in the next for loop run :
0571:                            // Caution: Always use this member method for updating the transient fields,
0572:                            //          so they are released again when freeAllTransientFields() is called.
0573:                            this .updateTransientFieldsFor(fsdSearchResult
0574:                                    .getFileStructureDescription());
0575:                            // Set flag:
0576:                            initialFSDHasBeenFound = true;
0577:                            // Reset the current scope FSD :
0578:                            currentScopeDescription = fsdSearchResult
0579:                                    .getFileStructureDescription();
0580:                            currentResultDescription = fsdSearchResult
0581:                                    .getFileStructureDescription();
0582:                            // and reset the current identifier :
0583:                            currentIdentifier.setLength(0);
0584:                            // and initialize it for the next run :
0585:                            if (tokenIndex < basisIdentifierTokens.length - 1) {
0586:                                currentIdentifier
0587:                                        .append(basisIdentifierTokens[tokenIndex + 1]);
0588:                            }
0589:                        } else {
0590:                            if (!initialFSDHasBeenFound) {
0591:                                // We are still accumulating the tokens (of a package statement)
0592:                                // until a complete qualifier will be found in one of the next loop runs possibly.
0593:                                if (tokenIndex < basisIdentifierTokens.length - 1) {
0594:                                    currentIdentifier
0595:                                            .append("."
0596:                                                    + basisIdentifierTokens[tokenIndex + 1]);
0597:                                }
0598:                            } else {
0599:                                // Means, that an invalid qualifier follows after some valid qualifiers,
0600:                                // so we have to break without success :
0601:                                break; // with a null result - The search has failed.
0602:                            }
0603:                        }
0604:                    } // for tokenIndex
0605:                } // if
0606:
0607:                /* Debug:
0608:                if( fsdSearchResult != null )
0609:                 {
0610:                   if( fsdSearchResult.getSimpleTypeName() != null )
0611:                    {
0612:                      Log.Info("Returns result with simpletype= " +
0613:                               fsdSearchResult.getSimpleTypeName() );
0614:                    }
0615:                   else
0616:                   if( fsdSearchResult.getFileStructureDescription() != null )
0617:                    {
0618:                      Log.Info("Returns result with fsd= " +
0619:                               fsdSearchResult.getFileStructureDescription().className.content );
0620:                    }
0621:                   else
0622:                    {
0623:                      Log.Info("Returns an INVALID result");
0624:                    }
0625:                 }
0626:                else
0627:                 {
0628:                   Log.Info("returns a NULL result");
0629:                 }
0630:                ----------- end debug */
0631:
0632:                return fsdSearchResult;
0633:            } // search_FileStructureDescription
0634:
0635:            /**
0636:             *  Test, if the identifier statement is an object creation and starts
0637:             *  with the keyword "new" followed by a non java identifier character.
0638:             *  If this is the case, we get the classname directly and return the associated FSD.
0639:             */
0640:            private FSDSearchResult searchForClassCreatorStatement(
0641:                    final int caretLineNumber,
0642:                    final FileStructureDescription currentFSD,
0643:                    final String currentIdentifier) {
0644:
0645:                //ystem.out.println("searchForClassCreatorStatement in with " + currentIdentifier );
0646:
0647:                FileStructureDescription resultFSD = null; // returnvalue
0648:                if (currentIdentifier.startsWith("new")) {
0649:                    if (currentIdentifier.length() > 4) {
0650:                        int position = 3;
0651:                        if (!Character.isJavaIdentifierPart(currentIdentifier
0652:                                .charAt(position))) {
0653:                            // "new  XX()" statement detected
0654:                            while ((!Character
0655:                                    .isJavaIdentifierPart(currentIdentifier
0656:                                            .charAt(position)))
0657:                                    && (position < currentIdentifier.length() - 1)) {
0658:                                position++;
0659:                            }
0660:                            if (position < currentIdentifier.length() - 1) {
0661:                                int classNameStartPosition = position;
0662:                                while ((Character
0663:                                        .isJavaIdentifierPart(currentIdentifier
0664:                                                .charAt(position)))
0665:                                        && (position < currentIdentifier
0666:                                                .length())) {
0667:                                    position++;
0668:                                    // Break from the loop, if we have reached the last character,
0669:                                    // otherwise the while test above would produce an exception :
0670:                                    if (position == currentIdentifier.length()) {
0671:                                        break;
0672:                                    }
0673:                                }
0674:                                String className = currentIdentifier.substring(
0675:                                        classNameStartPosition, position);
0676:
0677:                                //ystem.out.println("searchForClassCreatorStatement className= " + className );
0678:
0679:                                // First check, if it's an inner class creation (has priority):          
0680:                                // If it was an inner class, its fullyQualified class name had to be:
0681:                                String targetCandidateName = currentFSD.fullyQualifiedClassNameBuffer
0682:                                        .toString()
0683:                                        + "." + className;
0684:                                boolean isNestedClass = false;
0685:                                for (int iNested = 0; iNested < currentFSD.innerClasses
0686:                                        .size(); iNested++) {
0687:                                    FileStructureDescription nestedFSD = (FileStructureDescription) currentFSD.innerClasses
0688:                                            .elementAt(iNested);
0689:                                    if (nestedFSD.fullyQualifiedClassNameBuffer
0690:                                            .toString().equals(
0691:                                                    targetCandidateName)) {
0692:                                        resultFSD = nestedFSD;
0693:                                        isNestedClass = true;
0694:                                        break;
0695:                                    }
0696:                                }
0697:                                if (!isNestedClass) // else search globally
0698:                                {
0699:                                    // Search the FSD associated with that classname in the import scope
0700:                                    // of the currentFSD (trying all combinations):
0701:                                    final String[] inScopePossibleIdentifiers = CodeCompletionUtilities
0702:                                            .CreatePossibleQualifiedClassIdentifiers(
0703:                                                    currentFSD, className);
0704:                                    for (int p = 0; p < inScopePossibleIdentifiers.length; p++) {
0705:                                        resultFSD = this .fileStructureDescriptionManager
0706:                                                .searchFSD(inScopePossibleIdentifiers[p]);
0707:                                        if (resultFSD != null) {
0708:                                            break;
0709:                                        }
0710:                                    }
0711:                                }
0712:                            }
0713:                        }
0714:                    }
0715:                }
0716:                FSDSearchResult fsdSearchResult = null;
0717:                if (resultFSD != null) {
0718:                    fsdSearchResult = new FSDSearchResult(resultFSD, false);
0719:                }
0720:                return fsdSearchResult;
0721:            } // searchForClassCreatorStatement
0722:
0723:            /**
0724:             *  Private helper method. Called from performSearch().
0725:             *  This one assumes, that the passed currentIdentifier is a class name.
0726:             */
0727:            private FSDSearchResult searchForClassFSD(
0728:                    final int caretLineNumber,
0729:                    final FileStructureDescription currentFSD,
0730:                    final String currentIdentifier,
0731:                    final FileStructureDescription[] anonymousClassChain,
0732:                    final String previousIdentifier) {
0733:
0734:                /*
0735:                ystem.out.println("XXXXXXXXXXX searchForClassFSD: for current= " +
0736:                                   currentFSD.className.content  );
0737:                ystem.out.println("XXXXXXXXXXX searchForClassFSD: for id= " +
0738:                                   currentIdentifier  );
0739:                boolean isAnonymous = ( anonymousClassChain.length > 0 );
0740:                ystem.out.println("XXXXXXXXXXX searchForClassFSD: isAnonymous=" + isAnonymous );
0741:                 */
0742:                FileStructureDescription resultFSD = null;
0743:
0744:                // Some special cases for simple not segmented currentIdentifiers:
0745:                if (currentIdentifier.equals("this")) {
0746:
0747:                    //ystem.out.println("CCS> +++++++ this detected.");
0748:                    //ystem.out.println("CCS> +++++++ currentFSD = " + currentFSD.className.content );
0749:                    //ystem.out.println("CCS> +++++++ previousIdentifier= " + previousIdentifier );
0750:
0751:                    // Special case for this. : Return the currentFSD itself, or if the
0752:                    // caret is inside a nested class, return the fsd of that nested class :
0753:                    // Default :
0754:                    FileStructureDescription this FSD = currentFSD; // default, if not in a nested class
0755:                    // If the previous identifier has been the classname of the current FSD,
0756:                    // The scope is the current FSD. This is the case, if one writes
0757:                    // <classname>.this inside a nested or anonymous class for having access
0758:                    // to member objects of the toplevel class.
0759:                    // In all other cases, the nested class determines the scope:
0760:                    if (previousIdentifier.equals(currentFSD.className.content)) {
0761:                        // Scope extension by a <class>.this term -> return the toplevel FSD:
0762:                        resultFSD = currentFSD;
0763:                        //ystem.out.println("CCS> +++++++ scope extended ");
0764:                    } else // The scope is restricted by nested or anonymous classes:
0765:                    {
0766:                        //ystem.out.println("CCS> +++++++ scope conserved -> testing nested classes ");
0767:                        // Nested class: Overwites default :
0768:                        for (int i = 0; i < currentFSD.innerClasses.size(); i++) {
0769:                            FileStructureDescription nestedFSD = (FileStructureDescription) currentFSD.innerClasses
0770:                                    .elementAt(i);
0771:                            if ((caretLineNumber >= nestedFSD.scopeStartLine)
0772:                                    && (caretLineNumber <= nestedFSD.scopeEndLine)) {
0773:                                this FSD = nestedFSD;
0774:                                break;
0775:                            }
0776:                        }
0777:                        // If the caret is inside an anonymous class chain, take the deepest (=last) anonymous class :
0778:                        // Anonymous class: Overwrites all [highest priority] :
0779:                        if (anonymousClassChain.length > 0) {
0780:                            this FSD = anonymousClassChain[anonymousClassChain.length - 1];
0781:                        }
0782:                        resultFSD = this FSD;
0783:                    }
0784:                } else if (currentIdentifier.equals("super")) {
0785:                    // Special case for super.
0786:                    FileStructureDescription super ClassFSD = null;
0787:                    FileStructureDescription basisFSD = currentFSD;
0788:                    // Like in the "this" case: If the caret is inside a nested class, that
0789:                    // nested class defines the result of the super operator :
0790:                    for (int i = 0; i < currentFSD.innerClasses.size(); i++) {
0791:                        FileStructureDescription nestedFSD = (FileStructureDescription) currentFSD.innerClasses
0792:                                .elementAt(i);
0793:                        if ((caretLineNumber >= nestedFSD.scopeStartLine)
0794:                                && (caretLineNumber <= nestedFSD.scopeEndLine)) {
0795:                            basisFSD = nestedFSD;
0796:                            break;
0797:                        }
0798:                    }
0799:                    // If the caret is inside an anonymous class chain, take the deepest (=last) anonymous class
0800:                    // Anonymous class: Overwrites all [highest priority] :
0801:                    if (anonymousClassChain.length > 0) {
0802:                        basisFSD = anonymousClassChain[anonymousClassChain.length - 1];
0803:                    }
0804:                    if (basisFSD.super Class_fullyQualifiedClassName.content
0805:                            .length() > 0) {
0806:                        final String super ClassQualifier = basisFSD.super Class_fullyQualifiedClassName.content;
0807:                        // Note: superClass_fullyQualifiedClassName only is qualified in the sense, that
0808:                        //       it's the qualifier as entered in the source. That means, that we still
0809:                        //       must combine it with all import statements :
0810:                        // Note: For the combination of import statements, it's always the toplevel currentFSD,
0811:                        //       which must be used, also if basisFSD points to a nested fsd.
0812:                        final String[] inScopePossibleIdentifiers = CodeCompletionUtilities
0813:                                .CreatePossibleQualifiedClassIdentifiers(
0814:                                        currentFSD, super ClassQualifier);
0815:                        for (int p = 0; p < inScopePossibleIdentifiers.length; p++) {
0816:                            super ClassFSD = this .fileStructureDescriptionManager
0817:                                    .searchFSD(inScopePossibleIdentifiers[p]);
0818:                            if (super ClassFSD != null) {
0819:                                break;
0820:                            }
0821:                        }
0822:                    } else {
0823:                        // The considered class does not explicitly extend another class, but
0824:                        // in Java, all classes always extend the basisclass object, so return
0825:                        // this one, if the basisFSD isn't already the class Object :
0826:                        if (!basisFSD.className.content.equals("Object")) {
0827:                            final String super ClassQualifier = "java.lang.Object";
0828:                            super ClassFSD = this .fileStructureDescriptionManager
0829:                                    .searchFSD(super ClassQualifier);
0830:                        }
0831:                    }
0832:                    resultFSD = super ClassFSD;
0833:                } else {
0834:                    if (currentFSD.innerClasses != null) {
0835:                        // Local Search in the currentFSD: Search for an inner class first, because this has priority:
0836:                        if (currentFSD.innerClasses.size() > 0) {
0837:                            // The fullyQualifiedClassName is preceeded with the fullyQualifiedClassName
0838:                            // of the parentclass.
0839:                            // If the name of the parentclass is MyPackage.MyApplication and the classname
0840:                            // of the innerclass is MyFrame, then the fullyQualifiedClassName of
0841:                            // the innerclass is: MyPackage.MyApplication.MyFrame
0842:                            // In this case, MyFrame would be the currentIdentifier.
0843:                            // Create the target search identifier as explained above:
0844:                            final String targetQualifier = currentFSD.fullyQualifiedClassNameBuffer
0845:                                    .toString()
0846:                                    + "." + currentIdentifier;
0847:                            for (int i = 0; i < currentFSD.innerClasses.size(); i++) {
0848:                                final FileStructureDescription this InnerClassFSD = (FileStructureDescription) currentFSD.innerClasses
0849:                                        .elementAt(i);
0850:                                if (this InnerClassFSD.fullyQualifiedClassNameBuffer
0851:                                        .toString().equals(targetQualifier)) {
0852:                                    resultFSD = this InnerClassFSD;
0853:                                    break;
0854:                                }
0855:                            }
0856:                        } // if
0857:                    } // if
0858:                    if (resultFSD == null) {
0859:                        // Local Search in the currentFSD: Check inner interfaces, if still not found:
0860:                        if (currentFSD.innerInterfaces.size() > 0) {
0861:                            // The fullyQualifiedClassName is preceeded with the fullyQualifiedClassName
0862:                            // of the parentclass.
0863:                            // If the name of the parentclass is MyPackage.MyApplication and the classname
0864:                            // of the inner interface is MyInterface, then the fullyQualifiedClassName of
0865:                            // the inner interface is: MyPackage.MyApplication.MyInterface
0866:                            // In this case, MyInterface would be the currentIdentifier.
0867:                            // Create the target search identifier as explained above:
0868:                            final String targetQualifier = currentFSD.fullyQualifiedClassNameBuffer
0869:                                    .toString()
0870:                                    + "." + currentIdentifier;
0871:                            for (int i = 0; i < currentFSD.innerInterfaces
0872:                                    .size(); i++) {
0873:                                final FileStructureDescription this InnerInterfaceFSD = (FileStructureDescription) currentFSD.innerInterfaces
0874:                                        .elementAt(i);
0875:                                if (this InnerInterfaceFSD.fullyQualifiedClassNameBuffer
0876:                                        .toString().equals(targetQualifier)) {
0877:                                    resultFSD = this InnerInterfaceFSD;
0878:                                    break;
0879:                                }
0880:                            }
0881:                        } // if
0882:                    } // if
0883:                    // General case, if still not found: We have to search on gobal scope:
0884:                    if (resultFSD == null) {
0885:                        FileStructureDescription foundFSD = null;
0886:                        // We must combine the currentIdentifier with all wildcard-importstatements
0887:                        // of the current FSD, and also take into account, that one importstatement
0888:                        // could be the exact statement for the searched class, this
0889:                        // is done in the following inner loop :
0890:                        // Search a class description, which matches the currentIdentifier :
0891:                        final String[] possibleQualifiedClassIdentifiers = CodeCompletionUtilities
0892:                                .CreatePossibleQualifiedClassIdentifiers(
0893:                                        currentFSD, currentIdentifier);
0894:                        for (int searchIndex = 0; searchIndex < possibleQualifiedClassIdentifiers.length; searchIndex++) {
0895:                            foundFSD = this .fileStructureDescriptionManager
0896:                                    .searchFSD(possibleQualifiedClassIdentifiers[searchIndex]);
0897:                            // Break, if we have found the FSD, otherwise continue :
0898:                            if (foundFSD != null) {
0899:                                break;
0900:                            }
0901:                        } // for possibleQualifierIndex
0902:                        resultFSD = foundFSD;
0903:                    } // if
0904:                } // else
0905:                FSDSearchResult fsdSearchResult = null;
0906:                if (resultFSD != null) {
0907:                    fsdSearchResult = new FSDSearchResult(resultFSD, false);
0908:                }
0909:                return fsdSearchResult;
0910:            } // searchForClassFSD
0911:
0912:            /**                                       
0913:             *  Private helper method. Called from performSearch().
0914:             *
0915:             *  This one assumes, that the passed currentIdentfier is the name of an attribute.
0916:             *
0917:             *  The method goes recursively through nested class fsds. But the required import statements
0918:             *  always have to be fetched from the topLevel fsd, which mustn't change when diving into
0919:             *  nested classes.
0920:             *
0921:             *  For a first call of this method with a toplevel fsd, pass topLevelFSD = currentFSD.
0922:             */
0923:            private FSDSearchResult searchForAttributeClassFSD(
0924:                    final FileStructureDescription topLevelFSD,
0925:                    final FileStructureDescription currentFSD,
0926:                    String currentIdentifier, final int caretLineNumber,
0927:                    final FileStructureDescription[] anonymousClassChain) {
0928:                FSDSearchResult fsdSearchResult = null;
0929:
0930:                //ystem.out.println("CCSearch: searchForAttributeClassFSD starts with currentFSD= " +
0931:                //                   currentFSD.className.content +
0932:                //                   " and currentIdentifier= " + currentIdentifier );
0933:
0934:                // If the caret is inside a nested class, attributes of that nested class
0935:                // have highest priority, so add these first.
0936:                // We use recursion for this:
0937:                for (int i = 0; i < currentFSD.innerClasses.size(); i++) {
0938:                    FileStructureDescription nestedFSD = (FileStructureDescription) currentFSD.innerClasses
0939:                            .elementAt(i);
0940:
0941:                    //ystem.out.println("searchForAttributeClassFSD: check nested class " +
0942:                    //                   nestedFSD.fullyQualifiedClassName );
0943:
0944:                    if ((caretLineNumber >= nestedFSD.scopeStartLine)
0945:                            && (caretLineNumber <= nestedFSD.scopeEndLine)) {
0946:                        fsdSearchResult = this .searchForAttributeClassFSD(
0947:                                topLevelFSD, nestedFSD, currentIdentifier,
0948:                                caretLineNumber, anonymousClassChain);
0949:
0950:                        //ystem.out.println("searchForAttributeClassFSD: caret inside -> search RECURSIVELY nested class " +
0951:                        //                   nestedFSD.fullyQualifiedClassName );
0952:
0953:                        if (fsdSearchResult != null) {
0954:                            break;
0955:                        }
0956:                    }
0957:                }
0958:                // Local attributes have higher priority than [inherited]member attributes,
0959:                // therefore search these first :
0960:                // Search locals (can be in a nested fsd, cause we use recursion above),
0961:                // if no nested fsd result has been found already :
0962:                if (fsdSearchResult == null) {
0963:                    // 2nd) search for an inscope local attribute FSD
0964:                    final Vector localFieldFSDVector = currentFSD.localBlockFieldDescriptions;
0965:
0966:                    // If the caret lies in a chain of anonymous classes,
0967:                    // add all toplevel-member and inherited-member attributes of them :
0968:                    if (anonymousClassChain.length > 0) {
0969:                        for (int i = 0; i < anonymousClassChain.length; i++) {
0970:                            FileStructureDescription aFSD = (FileStructureDescription) anonymousClassChain[i];
0971:                            /* Debug output:
0972:                            ystem.out.println("XXX searchForAttributeClassFSD() anonymous fsd: " +
0973:                                               aFSD.className.content );
0974:                            ystem.out.println("XXX searchForAttributeClassFSD() scopestart= " +
0975:                                               aFSD.scopeStartLine + "  scopeend= " + aFSD.scopeEndLine );
0976:                            ystem.out.println("XXX searchForAttributeClassFSD() number of member attributes= " +
0977:                                               aFSD.fieldDescriptions.size() );
0978:                            ystem.out.println("XXX searchForAttributeClassFSD() number of localblock attributes= " +
0979:                                               aFSD.localBlockFieldDescriptions.size() );
0980:                             */
0981:                            // anonymous local attributes :
0982:                            for (int k = 0; k < anonymousClassChain[i].localBlockFieldDescriptions
0983:                                    .size(); k++) {
0984:                                localFieldFSDVector
0985:                                        .addElement(anonymousClassChain[i].localBlockFieldDescriptions
0986:                                                .elementAt(k));
0987:                                /*
0988:                                FileStructureDescriptionForField af = (FileStructureDescriptionForField)anonymousClassChain[i].localBlockFieldDescriptions.elementAt(k);
0989:                                ystem.out.println("XXX searchForAttributeClassFSD() local field: " +
0990:                                                   af.objectName );
0991:                                 */
0992:                            }
0993:                        } // for i
0994:                    } // if anonymousClassChain.length > 0
0995:
0996:                    // Get the field FSD's in array form:
0997:                    final FileStructureDescriptionForField[] localFieldFSDs = new FileStructureDescriptionForField[localFieldFSDVector
0998:                            .size()];
0999:                    localFieldFSDVector.copyInto(localFieldFSDs);
1000:
1001:                    //ystem.out.println("XXX searchForAttributeClassFSD(): SEARCHING LOCAL ATTRIBUTE... There are " +
1002:                    //                    localFieldFSDs.length + " local fields in current fsd= " +
1003:                    //                    currentFSD.className.content );
1004:
1005:                    fsdSearchResult = this .searchForSpecialAttributeClassFSD(
1006:                            topLevelFSD, currentFSD, localFieldFSDs,
1007:                            currentIdentifier, caretLineNumber);
1008:                } // if
1009:
1010:                // Search members (can be in a nested fsd, cause we use recursion above),
1011:                // if no nested fsd result has been found already :
1012:                if (fsdSearchResult == null) {
1013:                    // CAUTION: DO not change the content of the fieldDescriptions or
1014:                    //          localBlockFieldDescriptions Vectors.
1015:
1016:                    final Vector allFieldFSDVector = new Vector(); // Collect all here
1017:                    // Get the member field FSD's:
1018:                    final Vector memberFieldFSDVector = currentFSD.fieldDescriptions;
1019:                    // Add them to the allFieldFSDVector Vector :
1020:                    for (int i = 0; i < memberFieldFSDVector.size(); i++) {
1021:                        allFieldFSDVector.addElement(memberFieldFSDVector
1022:                                .elementAt(i));
1023:                    }
1024:                    // Get all inherited field FSD's:
1025:                    final Vector inheritedMemberFieldFSDVector = currentFSD.inheritedFieldDescriptions;
1026:                    // Add them to the allFieldFSDVector Vector :
1027:                    for (int i = 0; i < inheritedMemberFieldFSDVector.size(); i++) {
1028:                        allFieldFSDVector
1029:                                .addElement(inheritedMemberFieldFSDVector
1030:                                        .elementAt(i));
1031:                    }
1032:
1033:                    // Additionally attributes defined in a declared interface also are
1034:                    // visible in this class [ an asymmetry, cause methods have to be "implemented",
1035:                    // but attributes in an interface don't make sense basically, because
1036:                    // it makes no sense to "implement an attribute" in the target class like
1037:                    // one would have to do with methods, but..]
1038:                    Vector interfaceFieldsVector = CodeCompletionUtilities
1039:                            .GetAllFieldsFromAllInterfacesFor(currentFSD,
1040:                                    this .fileStructureDescriptionManager);
1041:                    for (int i = 0; i < interfaceFieldsVector.size(); i++) {
1042:                        FileStructureDescriptionForField f = (FileStructureDescriptionForField) interfaceFieldsVector
1043:                                .elementAt(i);
1044:                        allFieldFSDVector.addElement(f);
1045:                    }
1046:
1047:                    // If the caret lies in a chain of anonymous classes,
1048:                    // add all toplevel-member and inherited-member attributes of them :
1049:                    if (anonymousClassChain.length > 0) {
1050:
1051:                        for (int i = 0; i < anonymousClassChain.length; i++) {
1052:                            FileStructureDescription aFSD = (FileStructureDescription) anonymousClassChain[i];
1053:                            /* Debug output:
1054:                            ystem.out.println("XXX searchForAttributeClassFSD() anonymous fsd: " +
1055:                                               aFSD.className.content );
1056:                            ystem.out.println("XXX searchForAttributeClassFSD() scopestart= " +
1057:                                               aFSD.scopeStartLine + "  scopeend= " + aFSD.scopeEndLine );
1058:                            ystem.out.println("XXX searchForAttributeClassFSD() number of member attributes= " +
1059:                                               aFSD.fieldDescriptions.size() );
1060:                            ystem.out.println("XXX searchForAttributeClassFSD() number of localblock attributes= " +
1061:                                               aFSD.localBlockFieldDescriptions.size() );
1062:                            for( int qq=0; qq < aFSD.localBlockFieldDescriptions.size(); qq++ )
1063:                             {
1064:                               FileStructureDescriptionForField fsdf =
1065:                                 (FileStructureDescriptionForField)aFSD.localBlockFieldDescriptions.elementAt(qq);
1066:                               ystem.out.println("XXX searchForAttributeClassFSD() localblock attribute: " +
1067:                                                  fsdf.objectName +
1068:                                                  "  scopestart= " + fsdf.scopeStartLine +
1069:                                                  "  scopeend= " + fsdf.scopeEndLine );
1070:                             }
1071:                             */
1072:
1073:                            // anonymous members :
1074:                            for (int k = 0; k < anonymousClassChain[i].fieldDescriptions
1075:                                    .size(); k++) {
1076:                                allFieldFSDVector
1077:                                        .addElement(anonymousClassChain[i].fieldDescriptions
1078:                                                .elementAt(k));
1079:                                /*
1080:                                FileStructureDescriptionForField af = (FileStructureDescriptionForField)anonymousClassChain[i].fieldDescriptions.elementAt(k);
1081:                                ystem.out.println("XXX searchForAttributeClassFSD() anonymous field: " +
1082:                                                   af.objectName );
1083:                                 */
1084:                            }
1085:                            // anonymous inherited members :
1086:                            for (int k = 0; k < anonymousClassChain[i].inheritedFieldDescriptions
1087:                                    .size(); k++) {
1088:                                allFieldFSDVector
1089:                                        .addElement(anonymousClassChain[i].inheritedFieldDescriptions
1090:                                                .elementAt(k));
1091:                                /*
1092:                                FileStructureDescriptionForField af = (FileStructureDescriptionForField)anonymousClassChain[i].inheritedFieldDescriptions.elementAt(k);
1093:                                ystem.out.println("XXX searchForAttributeClassFSD() inherited anonymous field: " +
1094:                                                   af.objectName );
1095:                                 */
1096:                            }
1097:                        }
1098:                    }
1099:
1100:                    // Copy all into one array :
1101:                    final FileStructureDescriptionForField[] allFieldFSDs = new FileStructureDescriptionForField[allFieldFSDVector
1102:                            .size()];
1103:                    allFieldFSDVector.copyInto(allFieldFSDs);
1104:
1105:                    //ystem.out.println("XXX searchForAttributeClassFSD(): SEARCHING MEMBER ATTRIBUTES...");
1106:                    fsdSearchResult = this .searchForSpecialAttributeClassFSD(
1107:                            topLevelFSD, currentFSD, allFieldFSDs,
1108:                            currentIdentifier, caretLineNumber);
1109:
1110:                } // if
1111:
1112:                /* Debug:
1113:                if( fsdSearchResult != null )
1114:                 {
1115:                   if( fsdSearchResult.getSimpleTypeName() != null )
1116:                    {
1117:                      ystem.out.println("searchForAttributeClassFSD: Returns fsdSearchResult with simpletype= " +
1118:                                         fsdSearchResult.getSimpleTypeName() +
1119:                                         "  array= " + fsdSearchResult.getIsJavaArrayObject() );
1120:                    }
1121:                   else
1122:                   if( fsdSearchResult.getFileStructureDescription() != null )
1123:                    {
1124:                      ystem.out.println("searchForAttributeClassFSD: Returns fsdSearchResult with fsd= " +
1125:                                         fsdSearchResult.getFileStructureDescription().className.content +
1126:                                         "  array= " + fsdSearchResult.getIsJavaArrayObject() );
1127:                    }
1128:                   else
1129:                    {
1130:                      ystem.out.println("searchForAttributeClassFSD: Returns an INVALID fsdSearchResult");
1131:                    }
1132:                 }
1133:                else
1134:                 {
1135:                   ystem.out.println("searchForAttributeClassFSD: returns a NULL fsdSearchResult");
1136:                 }
1137:                 */
1138:
1139:                return fsdSearchResult;
1140:            } // searchForAttributeClassFSD
1141:
1142:            /**
1143:             *  Private helper method. Called from searchForAttributeClassFSD().
1144:             *
1145:             *  It is used for the search for a member attribute FSD as well as
1146:             *  for a local attribute FSD, depending on the content of fieldFSDs.
1147:             *
1148:             *  It also gets called with nested class fsd's as currentFSD. Therefore
1149:             *  the possible package statement combinations always have to be fetched
1150:             *  from the also passed topLevelFSD.
1151:             *  If the currentFSD is a toplevel fsd, we have topLevelFSD = currentFSD.
1152:             *
1153:             */
1154:            private FSDSearchResult searchForSpecialAttributeClassFSD(
1155:                    final FileStructureDescription topLevelFSD,
1156:                    final FileStructureDescription currentFSD,
1157:                    final FileStructureDescriptionForField[] fieldFSDs,
1158:                    String currentIdentifier, final int caretLineNumber) {
1159:
1160:                //ystem.out.println("x>>> CCSearch.searchForSpecialAttributeClassFSD() called for: ");
1161:                //ystem.out.println("x>>> currentIdentifier= " + currentIdentifier );
1162:
1163:                // Simplification 1 : If the currentIdentifier ends with
1164:                // array brackets, skip the brackets incl. content for getting
1165:                // the fsd first.
1166:                // If no brackets were detected, but below a java array type is found,
1167:                // the flag isJavaArrayObject in the returned object is set for signaling,
1168:                // that it's a simple java array (with only one attribute, which is length )
1169:                boolean isArrayElement = false;
1170:                final int squareBracketIndex = currentIdentifier.indexOf("[");
1171:                if (squareBracketIndex >= 0) {
1172:                    isArrayElement = true;
1173:                    currentIdentifier = currentIdentifier.substring(0,
1174:                            squareBracketIndex);
1175:                    //ystem.out.println("CC: Methodsearch: searchForSpecialAttributeClassFSD:  SIMPLIFIED 1 (squarebracket) currentIdentifier = " + currentIdentifier );
1176:                }
1177:
1178:                FileStructureDescription resultFSD = null;
1179:                String simpletype = null;
1180:                boolean resultAttributeHasArrayType = false;
1181:
1182:                for (int i = 0; i < fieldFSDs.length; i++) {
1183:                    final FileStructureDescriptionForField this FieldFSD = fieldFSDs[i];
1184:                    if (this FieldFSD.objectNameWithPosition.content
1185:                            .equals(currentIdentifier)) {
1186:
1187:                        //ystem.out.println("x>>> CCSearch.searchForSpecialAttributeClassFSD(): Attribute FOUND");
1188:                        //ystem.out.println("x>>> caretLineNumber= " + caretLineNumber );
1189:                        //ystem.out.println("x>>> thisFieldFSD.scopeStartLine= " + thisFieldFSD.scopeStartLine );
1190:                        //ystem.out.println("x>>> thisFieldFSD.scopeEndLine= " + thisFieldFSD.scopeEndLine );
1191:
1192:                        boolean inScope = true;
1193:                        // If it's a local attribute, test, if we are in scope :
1194:                        if (this FieldFSD.scopeEndLine > 0) // it's a local attribute FSD
1195:                        {
1196:                            inScope = ((this FieldFSD.scopeStartLine <= caretLineNumber) && (this FieldFSD.scopeEndLine >= caretLineNumber));
1197:                        }
1198:                        // else it's a member attribute FSD.
1199:
1200:                        //ystem.out.println("x>>> CCSearch.searchForSpecialAttributeClassFSD(): Attribute inScope= " + inScope);
1201:
1202:                        if (inScope) {
1203:                            // We have found an inscope attribute description with the requested name,
1204:                            // so now, we only have to get the FSD for the class type,
1205:                            // which should exist, unless it's not programmed in the targetsource,
1206:                            // or unless its a primitive type :
1207:                            String classQualifier = null;
1208:                            if (this FieldFSD.packageName.length() > 0) {
1209:                                classQualifier = this FieldFSD.packageName + "."
1210:                                        + this FieldFSD.simpleClassName.content;
1211:                            } else {
1212:                                classQualifier = this FieldFSD.simpleClassName.content;
1213:                            }
1214:                            resultAttributeHasArrayType = this FieldFSD.isArrayType.booleanValue;
1215:                            // If the type is not primitive, we have to search the fsd, otherwise
1216:                            // we have all we need.
1217:                            if (this FieldFSD.isPrimitiveType) {
1218:                                // Note: simpletype will be used for creating the returned FSDResult below, if its set.
1219:                                simpletype = classQualifier;
1220:
1221:                                //ystem.out.println("---->searchForSpecialAttributeClassFSD: Simple type detected and returned in FSDResult: " +
1222:                                //                   simpletype );
1223:
1224:                                // all done - break the loop
1225:                                break;
1226:                            } else {
1227:                                // Seen by tests: Nested classes have higher priority, than toplevel classes.
1228:                                // Means: If you have a nested class named MyClass, and a toplevel class of
1229:                                // the same name MyClass (but with other methods and attributes), the compiler
1230:                                // will associate an attribute of class MyClass with the *nested class* and not
1231:                                // with the toplevel class. This gives the order here :
1232:                                // First search the nested classes :
1233:                                for (int iNested = 0; iNested < currentFSD.innerClasses
1234:                                        .size(); iNested++) {
1235:                                    FileStructureDescription nestedFSD = (FileStructureDescription) currentFSD.innerClasses
1236:                                            .elementAt(iNested);
1237:                                    if (nestedFSD.className.content
1238:                                            .equals(classQualifier)) {
1239:                                        resultFSD = nestedFSD;
1240:                                        break;
1241:                                    }
1242:                                }
1243:                                // Go search this-level fsd's (can be nested too), if no nested class inside currentFSD
1244:                                // has been found:
1245:                                if (resultFSD == null) {
1246:                                    // Note: classQualifier only is qualified in the sense, that
1247:                                    //       its the qualifier as entered in the source. That means, that we still
1248:                                    //       must combine it with all import statements :
1249:                                    // Always use the topLevelFSD for getting these combinations, which is required,
1250:                                    // when currentFSD itseld is a nested fsd :
1251:                                    resultFSD = this 
1252:                                            .searchFSDForClassQualifierIncludingParentChainOf(
1253:                                                    topLevelFSD, classQualifier);
1254:                                } // if
1255:                                if (resultFSD != null) // keep it for returning and break this outer loop too
1256:                                {
1257:                                    break;
1258:                                }
1259:                            } // else
1260:                        } // if inScope
1261:                    } // if
1262:                } // for i
1263:
1264:                //   If neither an fsd (of a complex type) nor a simpletype has been found,
1265:                //   test the currentIdentifier, wether it's a constant value and identify it :
1266:                //   234  -> int                                 
1267:                //   1.2  -> double
1268:                //   1.3f -> float
1269:                //   'd'  -> char                              
1270:                //   true, false -> boolean
1271:                //  
1272:                //   Exception: No action for null :
1273:                //   null -> null ( identity - this must be handled later, its like an object wildcard )
1274:                if ((resultFSD == null) && (simpletype == null)) {
1275:
1276:                    //ystem.out.println("x>>> CodeCompletionSearch: Neither field fsd nor simple type found -> Checking for constant value."); 
1277:
1278:                    simpletype = identifySimpleType(currentIdentifier);
1279:
1280:                    /*
1281:                    if( simpletype != null )
1282:                     {
1283:                       ystem.out.println("x>>> CodeCompletionSearch: Constant value identified: " + simpletype );
1284:                     }
1285:                    else
1286:                     {
1287:                       ystem.out.println("x>>> CodeCompletionSearch: NO Constant value identified.");
1288:                     }
1289:                     */
1290:
1291:                } // if (constant identification)
1292:
1293:                // It's an abstract java array type (with only a length attribute), if no square
1294:                // brackets were detected above, but the attribute was marked as array.
1295:                boolean isJavaArrayObject = (resultAttributeHasArrayType && !isArrayElement);
1296:                // Switch depending on simple or object type, return null if nothing has been found :
1297:                FSDSearchResult result = null; // default, if nothing found
1298:                if (simpletype != null) {
1299:                    result = new FSDSearchResult(simpletype, isJavaArrayObject);
1300:                } else if (resultFSD != null) {
1301:                    result = new FSDSearchResult(resultFSD, isJavaArrayObject);
1302:                }
1303:                return result;
1304:            } // searchForSpecialAttributeClassFSD
1305:
1306:            /**
1307:             *   Tries to identify the passed identifier as constant value and 
1308:             *   returns its simple type, or null if it couldn't identify it.
1309:             *
1310:             *   Called by searchForSpecialAttributeClassFSD() above.
1311:             *
1312:             *   Examples:
1313:             *   234  -> int
1314:             *   1.2  -> double
1315:             *   1.3f -> float
1316:             *   'd'  -> char
1317:             *   true, false -> boolean
1318:             */
1319:            private String identifySimpleType(String identifier) {
1320:                String simpletype = null; // Return value. It's null, if nothing has been found.
1321:                if (identifier.length() > 0) {
1322:                    char lastCharacter = identifier
1323:                            .charAt(identifier.length() - 1);
1324:                    if (lastCharacter == 'd') {
1325:                        try {
1326:                            Double.parseDouble(identifier); // throws an exception, if it doesn't work
1327:                            simpletype = "double";
1328:                        } catch (Exception e1) {
1329:                        }
1330:                    } else if (lastCharacter == 'f') {
1331:                        try {
1332:                            Float.parseFloat(identifier); // throws an exception, if it doesn't work
1333:                            simpletype = "float";
1334:                        } catch (Exception e2) {
1335:                        }
1336:                    } else if (identifier.equals("true")
1337:                            || identifier.equals("false")) {
1338:                        simpletype = "boolean";
1339:                    } else if (identifier.startsWith("'")) {
1340:                        simpletype = "char";
1341:                    } else {
1342:                        try {
1343:                            Integer.parseInt(identifier); // throws an exception, if it doesn't work
1344:                            simpletype = "int";
1345:                        } catch (Exception e3) {
1346:                        }
1347:                    }
1348:                } // if length > 0
1349:                return simpletype;
1350:            } // identifySimpleType
1351:
1352:            /**
1353:             *  Private helper method. Called from performSearch().
1354:             */
1355:            private FSDSearchResult searchForMethodReturnTypeFSD(
1356:                    final FileStructureDescription currentFSD,
1357:                    String currentIdentifier, final int caretLineNumber,
1358:                    final FileStructureDescription[] anonymousClassChain) {
1359:                // Parameter signature : Initialized as an empty String, which is correct for
1360:                // methods with an empty parameter list.
1361:                final int roundBracketStartIndex = currentIdentifier
1362:                        .indexOf("(");
1363:                if (roundBracketStartIndex >= 0) {
1364:                    // The method parameter list ends at the LAST closing bracket. Of course
1365:                    // there can be many brackets inside (which should be balanced, if the syntax
1366:                    // happens to be correct )
1367:                    final int roundBracketEndIndex = currentIdentifier
1368:                            .lastIndexOf(")");
1369:                    // Try to calculate the parameter signature, if we have at last one character between
1370:                    // the brackets. The parameter signature consists of all parameter classnames, separated
1371:                    // by commas.
1372:                    if ((roundBracketEndIndex >= 0)
1373:                            && (roundBracketEndIndex > roundBracketStartIndex + 1)) {
1374:                        String plainMethodName = currentIdentifier.substring(0,
1375:                                roundBracketStartIndex);
1376:                        String parameterListText = currentIdentifier.substring(
1377:                                roundBracketStartIndex + 1,
1378:                                roundBracketEndIndex);
1379:                        // Call the recursive method, which parses the parameterlist and tries to
1380:                        // resolve the signature for it :
1381:                        String parameterSignature = this 
1382:                                .calculateParameterSignatureForParameterList(
1383:                                        parameterListText, currentFSD,
1384:                                        caretLineNumber);
1385:                        // Add it, if one has been found at all :
1386:                        if (parameterSignature.length() > 0) {
1387:                            currentIdentifier = plainMethodName + "("
1388:                                    + parameterSignature + ")";
1389:                        } else {
1390:                            currentIdentifier = plainMethodName + "()";
1391:                        }
1392:
1393:                        //ystem.out.println("CC> searchForMethodReturnTypeFSD: identifier with signature = " +
1394:                        //                    currentIdentifier );
1395:
1396:                    } else {
1397:                        // Only for debug purpose :
1398:                        //ystem.out.println("CC> searchForMethodReturnTypeFSD: [plain] identifier = " + currentIdentifier );
1399:                    }
1400:                } // if
1401:
1402:                // CAUTION: Do NOT change the contents of the methodDescriptions
1403:                //          or inheritedMethodDescriptions.
1404:
1405:                FileStructureDescription resultFSD = null;
1406:                final Vector allMethodsVector = new Vector();
1407:                // Get the toplevel methods :
1408:                final Vector methodFSDVector = currentFSD.methodDescriptions;
1409:                // Add all toplevel methods to the allMethodsVector Vector :
1410:                for (int i = 0; i < methodFSDVector.size(); i++) {
1411:                    allMethodsVector.addElement(methodFSDVector.elementAt(i));
1412:                }
1413:                // Get all inherited methods :
1414:                final Vector inheritedMethodFSDVector = currentFSD.inheritedMethodDescriptions;
1415:                // Add all inherited methods to the allMethodsVector Vector :
1416:                for (int i = 0; i < inheritedMethodFSDVector.size(); i++) {
1417:                    allMethodsVector.addElement(inheritedMethodFSDVector
1418:                            .elementAt(i));
1419:                }
1420:                // If the caret lies in a chain of anonymous classes,
1421:                // add all toplevel-methods and inherited-methods of them :
1422:                if (anonymousClassChain.length > 0) {
1423:                    for (int i = 0; i < anonymousClassChain.length; i++) {
1424:                        for (int k = 0; k < anonymousClassChain[i].methodDescriptions
1425:                                .size(); k++) {
1426:                            allMethodsVector
1427:                                    .addElement(anonymousClassChain[i].methodDescriptions
1428:                                            .elementAt(k));
1429:                        }
1430:                        for (int k = 0; k < anonymousClassChain[i].inheritedMethodDescriptions
1431:                                .size(); k++) {
1432:                            allMethodsVector
1433:                                    .addElement(anonymousClassChain[i].inheritedMethodDescriptions
1434:                                            .elementAt(k));
1435:                        }
1436:
1437:                        /* Debug:
1438:                        if( anonymousClassChain[i].inheritedMethodDescriptions.size() == 0 )
1439:                         {
1440:                           ystem.out.println("*** No inherited methods for anonymous class " +
1441:                                               anonymousClassChain[i].className.content +
1442:                                               " with superclass= " +
1443:                                               anonymousClassChain[i].superClass_fullyQualifiedClassName.content  );
1444:                         }
1445:                        else
1446:                         {
1447:                           ystem.out.println("*** Inherited methods for anonymous class " +
1448:                                              anonymousClassChain[i].className.content +
1449:                                              " : " +
1450:                                              anonymousClassChain[i].inheritedMethodDescriptions.size() );
1451:                         }
1452:                         */
1453:
1454:                    }
1455:                }
1456:                // Copy all into one array :
1457:                final FileStructureDescriptionForMethod[] allMethodFSDs = new FileStructureDescriptionForMethod[allMethodsVector
1458:                        .size()];
1459:                allMethodsVector.copyInto(allMethodFSDs);
1460:                // and search:
1461:                boolean resultReturnTypeHasArrayType = false;
1462:                boolean isPrimitiveType = false;
1463:                String simpletype = "";
1464:                for (int i = 0; i < allMethodFSDs.length; i++) {
1465:                    final FileStructureDescriptionForMethod this MethodFSD = allMethodFSDs[i];
1466:                    final ParameterTypeDescription returnType = this MethodFSD.resultParameter;
1467:
1468:                    //ystem.out.println("CC> methodsearch:  comparing " + currentIdentifier +
1469:                    //                   " with signature= " + thisMethodFSD.signature );
1470:
1471:                    String returnedClassIdentifier = null;
1472:                    if (this MethodFSD.signature.equals(currentIdentifier)) {
1473:                        // We have found the method signature,
1474:                        // so now, we only have to get the FSD for the returned class type,
1475:                        // which should exist, unless the associated file (class or java),
1476:                        // doesnt exist, or unless its a primitive type :
1477:
1478:                        // Skip primitive return types :
1479:                        isPrimitiveType = returnType.isPrimitiveType;
1480:                        if (!returnType.isPrimitiveType) {
1481:                            String classQualifier = null;
1482:                            if (returnType.packageName.length() > 0) {
1483:                                classQualifier = returnType.packageName + "."
1484:                                        + returnType.simpleClassName;
1485:                            } else {
1486:                                classQualifier = returnType.simpleClassName;
1487:                            }
1488:                            resultReturnTypeHasArrayType = returnType.isArrayType.booleanValue;
1489:                            // Note: classQualifier only is qualified in the sense, that
1490:                            //       its the qualifier as entered in the source. That means, that we still
1491:                            //       must combine it with all import statements :
1492:                            resultFSD = this 
1493:                                    .searchFSDForClassQualifierIncludingParentChainOf(
1494:                                            currentFSD, classQualifier);
1495:                            if (resultFSD != null) // keep it for returning and break this outer loop too
1496:                            {
1497:                                break; // break the outer for loop
1498:                            }
1499:                        } else {
1500:                            simpletype = returnType.simpleClassName;
1501:                            // check array type also for primitive types :
1502:                            resultReturnTypeHasArrayType = returnType.isArrayType.booleanValue;
1503:                            break;
1504:                        }
1505:                    } // if
1506:                } // for i
1507:
1508:                boolean isJavaArrayObject = resultReturnTypeHasArrayType;
1509:                // Switch depending on simple or object type, return null if nothing has been found :
1510:                FSDSearchResult result = null; // default, if nothing found
1511:                if (isPrimitiveType) {
1512:                    result = new FSDSearchResult(simpletype, isJavaArrayObject);
1513:
1514:                    //ystem.out.println("searchForMethodReturnTypeFSD() returns simpletype " + simpletype );
1515:
1516:                } else if (resultFSD != null) {
1517:                    result = new FSDSearchResult(resultFSD, isJavaArrayObject);
1518:
1519:                    //ystem.out.println("searchForMethodReturnTypeFSD() returns fsd " + resultFSD.className.content );
1520:
1521:                } else {
1522:                    //ystem.out.println("searchForMethodReturnTypeFSD() returns NULL ");
1523:                    // this.           
1524:                }
1525:                return result;
1526:            } // searchForMethodReturnTypeFSD
1527:
1528:            private FileStructureDescription searchFSDForClassQualifierIncludingParentChainOf(
1529:                    final FileStructureDescription basisFSD,
1530:                    final String classQualifier) {
1531:                // Note: The classQualifier only is qualified in the sense, that
1532:                //       its the qualifier as entered in the source. That means, that we still
1533:                //       must combine it with all import statements :
1534:                FileStructureDescription resultFSD = null; // The return value
1535:                // Examine the current FSD, and while not found go back the parent chain :
1536:                FileStructureDescription searchFSD = basisFSD;
1537:                while ((searchFSD != null) && (resultFSD == null)) {
1538:                    final String[] inScopePossibleIdentifiers = CodeCompletionUtilities
1539:                            .CreatePossibleQualifiedClassIdentifiers(searchFSD,
1540:                                    classQualifier);
1541:                    for (int p = 0; p < inScopePossibleIdentifiers.length; p++) {
1542:                        resultFSD = this .fileStructureDescriptionManager
1543:                                .searchFSD(inScopePossibleIdentifiers[p]);
1544:                        if (resultFSD != null) // keep it for returning and break this inner loop
1545:                        {
1546:                            break; // break the for while loop
1547:                        }
1548:                    }
1549:                    // If it nothing has been found, step back the parent chain :
1550:                    if (resultFSD == null) {
1551:                        searchFSD = this .fileStructureDescriptionManager
1552:                                .getSuperClassFSDOf(searchFSD);
1553:                        // If no superclass exists, searchFSD will be null now, which
1554:                        // will leave the while loop.
1555:                    }
1556:                } // while
1557:                return resultFSD;
1558:            } // searchFSDForIdentifierIncludingParentChainOf
1559:
1560:            /**
1561:             *   Recursive method, which tries to replace the parameterList, which is the
1562:             *   text between method parameter brackets, by the signature made of the
1563:             *   parametertypes separated by commas.
1564:             *
1565:             *   The returned signature isn't enclosed by parnethesis. It just contains the
1566:             *   classnames [or simpletype names] of all parameters, separated by commas.
1567:             *
1568:             */
1569:            private String calculateParameterSignatureForParameterList(
1570:                    final String parameterListText,
1571:                    final FileStructureDescription currentFSD,
1572:                    final int caretLineNumber) {
1573:                // Round brackets go one recursion step deeper.
1574:                // example: parameterListText= "myInt,this.getComponent(a1,a2),i)"
1575:                // where the comma between a1 and a2 is a level deeper in the recursion.
1576:                // Tokenize the first level only, but be prepared, that the brackets don't
1577:                // have to be balanced (because of possible syntax errors of the programmer).
1578:                Vector parameterElementsTextVector = new Vector();
1579:                String workText = ""; // Empty String
1580:                char workCharacter;
1581:                int childLevel = 0;
1582:                for (int i = 0; i < parameterListText.length(); i++) {
1583:                    workCharacter = parameterListText.charAt(i);
1584:                    if ((workCharacter == ',') && (childLevel == 0)) {
1585:                        // Add the existing text and make a new one ready :
1586:                        if (workText.length() > 0) {
1587:                            // add, and remove spaces at the beginning and the end :
1588:                            parameterElementsTextVector.addElement(workText
1589:                                    .trim());
1590:                            workText = new String("");
1591:                        }
1592:                    } else if (workCharacter == '(') {
1593:                        childLevel++;
1594:                        workText += "" + workCharacter;
1595:                    } else if (workCharacter == ')') {
1596:                        childLevel--;
1597:                        workText += "" + workCharacter;
1598:                    } else {
1599:                        // Append. Tabs, newlines or return characters also are valid
1600:                        // delimiters, so we replace them by a space here. (easier)
1601:                        // Note: We cannot skip spaces (delimiters) anywhere, cause we would merge
1602:                        // statements of the type "new Component()". We trim the identifiers later.
1603:                        if ((workCharacter == '\t') || (workCharacter == '\r')
1604:                                || (workCharacter == '\n')) {
1605:                            workText += " ";
1606:                        } else {
1607:                            workText += "" + workCharacter;
1608:                        }
1609:                    }
1610:                } // for loop
1611:                // Ending : Add the workText, if it still contains characters :
1612:                if (workText.length() > 0) {
1613:                    // add, and remove spaces at the beginning and the end :
1614:                    parameterElementsTextVector.addElement(workText.trim());
1615:                }
1616:                // Now get the level one parameter texts into an array :
1617:                String[] parameterElements = new String[parameterElementsTextVector
1618:                        .size()];
1619:                parameterElementsTextVector.copyInto(parameterElements);
1620:
1621:                // The parameterElementClassNames has to be filled to get the signature :
1622:                String[] parameterElementClassNames = new String[parameterElementsTextVector
1623:                        .size()];
1624:                for (int i = 0; i < parameterElementClassNames.length; i++) {
1625:                    parameterElementClassNames[i] = ""; // initialize all to an empty String
1626:                }
1627:
1628:                //ystem.out.println("CC> calculateParameterSignatureForParameterList> Loop for " +
1629:                //                   parameterElements.length + " elements." );
1630:
1631:                // Now try to resolve the parameter class of each parameterElements element,
1632:                // which is a kind of [more complicated] recursion, as we create a new search,
1633:                // which again can go through this method (multiple times) :
1634:                for (int i = 0; i < parameterElements.length; i++) {
1635:
1636:                    //ystem.out.println("CC> calculateParameterSignatureForParameterList> " + parameterElements[i] );
1637:
1638:                    // Herewego recursively :
1639:                    // Note, that the scope FSD always is the same like the search has been
1640:                    // started for, and not the one of the parser chain : It is
1641:                    // this.toplevelBasisFSD and not currentFSD.
1642:                    CodeCompletionSearch ccSearch = new CodeCompletionSearch(
1643:                            parameterElements[i], 0, this .editorPanel,
1644:                            this .toplevelBasisFSD,
1645:                            this .fileStructureDescriptionManager);
1646:                    ccSearch.performSearch(caretLineNumber);
1647:                    FSDSearchResult searchResult = ccSearch
1648:                            .getFoundFSDSearchResult();
1649:
1650:                    /* Debug:
1651:                    String fsdName = "<NULL>";
1652:                    if( searchResult.getFileStructureDescription() != null )
1653:                     {
1654:                       fsdName = searchResult.getFileStructureDescription().className.content;
1655:                     }
1656:                    String simpleName = "<NULL>";
1657:                    if( searchResult.getSimpleTypeName() != null )
1658:                     {
1659:                       simpleName = searchResult.getSimpleTypeName();
1660:                     }
1661:                    ystem.out.println("CC> calculateParameterSignatureForParameterList> Loop run " + i +
1662:                                       "  SearchResult has fsd= " + fsdName +
1663:                                       " and simpletypename= "   + simpleName  );
1664:                     */
1665:
1666:                    if (searchResult != null) {
1667:                        if (searchResult.getFileStructureDescription() != null) {
1668:                            parameterElementClassNames[i] = searchResult
1669:                                    .getFileStructureDescription().className.content;
1670:                        } else if (searchResult.getSimpleTypeName() != null) {
1671:                            parameterElementClassNames[i] = searchResult
1672:                                    .getSimpleTypeName();
1673:                        }
1674:                    }
1675:                } // for
1676:                // Now build the parameter signature :
1677:                String signature = "";
1678:                for (int i = 0; i < parameterElementClassNames.length; i++) {
1679:                    if (i == 0) {
1680:                        signature += parameterElementClassNames[i];
1681:                    } else {
1682:                        signature += "," + parameterElementClassNames[i];
1683:                    }
1684:                }
1685:                parameterElementsTextVector.setSize(0); // Help the GC by lowering associations 
1686:
1687:                //System.
1688:
1689:                return signature;
1690:            } // calculateParameterSignatureForParameterList
1691:
1692:            /**
1693:             *  This method examines the resultDescription and returns methods/attributes,
1694:             *  which are visible from the current position of the currentlyEditedFSD.
1695:             *  Methods/Attributes which are not accessible from the current position are excluded,
1696:             *  and additional accessible methods/attributes from parent classes are added.
1697:             */
1698:            private CodeCompletionListEntry[] selectVisibleEntriesFrom(
1699:                    final FileStructureDescription resultDescription,
1700:                    final boolean onlySelectStaticAttributesAndMethods,
1701:                    final FileStructureDescription[] anonymousClassChain) {
1702:                /* Debug:
1703:                ystem.out.println("selectVisibleEntriesFrom [on start] for fsd " +
1704:                                   resultDescription.className.content  );
1705:                ystem.out.println("selectVisibleEntriesFrom [on start] with member methods: " +
1706:                                   resultDescription.methodDescriptions.size()  );
1707:                ystem.out.println("selectVisibleEntriesFrom [on start] with inherited methods: " +
1708:                                   resultDescription.inheritedMethodDescriptions.size()  );
1709:                ystem.out.println("selectVisibleEntriesFrom [on start] with member attributes: " +
1710:                                   resultDescription.fieldDescriptions.size()  );
1711:                ystem.out.println("selectVisibleEntriesFrom [on start] with inherited attributes: " +
1712:                                   resultDescription.inheritedFieldDescriptions.size()  );
1713:                 */
1714:
1715:                final Vector codeCompletionListEntries = new Vector(); // of CodeCompletionListEntry objects with functionality
1716:
1717:                // Filter out methods and objects, which are not accessible from
1718:                // the source FSD. Condition flags :
1719:
1720:                // Include private objects, if the edited FSD is the same
1721:                // as the resultDescription ...
1722:                boolean sameFSDs = (this .toplevelBasisFSD.fullyQualifiedClassNameBuffer
1723:                        .toString()
1724:                        .equals(resultDescription.fullyQualifiedClassNameBuffer
1725:                                .toString()));
1726:                // ... or if the resultDescription is a toplevel anonymous class fsd :
1727:                boolean isToplevelAnonymousClassFSD = false;
1728:                if (anonymousClassChain.length > 0) {
1729:                    FileStructureDescription toplevelAnonymousClassFSD = anonymousClassChain[anonymousClassChain.length - 1];
1730:                    isToplevelAnonymousClassFSD = (toplevelAnonymousClassFSD.fullyQualifiedClassNameBuffer
1731:                            .toString()
1732:                            .equals(resultDescription.fullyQualifiedClassNameBuffer
1733:                                    .toString()));
1734:                }
1735:
1736:                // ... or if the resultDescription is a nested class of the toplevel fsd :
1737:                boolean isNestedClass = this .fileStructureDescriptionManager
1738:                        .getIsInnerClassOf(resultDescription,
1739:                                this .toplevelBasisFSD);
1740:
1741:                //ystem.out.println("selectVisibleEntriesFrom isNestedClass = " + isNestedClass );
1742:
1743:                boolean includePrivateObjects = sameFSDs
1744:                        || isToplevelAnonymousClassFSD || isNestedClass;
1745:
1746:                // Include parent package-scope objects, if the package of
1747:                // the edited and the result FSD are the same.
1748:                // ***Important Exception*** : If the resultdescription is an interface,
1749:                //                             also package-scope objects ALWAYS have public scope.
1750:                boolean includePackageScopeObjects = (this .toplevelBasisFSD.packageName.content
1751:                        .equals(resultDescription.packageName.content) || (resultDescription.isInterface ));
1752:
1753:                // Include protected parent objects, if the result FSD is
1754:                // in the parentchain of the edited FSD or if the two FSD's are the same:
1755:                boolean includeProtectedObjects = ((this .isParentOf(
1756:                        resultDescription, this .toplevelBasisFSD))
1757:                        || (sameFSDs) || (isNestedClass));
1758:
1759:                /*
1760:                ystem.out.println("selectVisibleEntriesFrom [before call] with member methods: " +
1761:                                   resultDescription.methodDescriptions.size()  );
1762:                ystem.out.println("selectVisibleEntriesFrom [before call] with inherited methods: " +
1763:                                   resultDescription.inheritedMethodDescriptions.size()  );
1764:                 */
1765:
1766:                // Retrieve the short textrepresentations of all inscope methods
1767:                this .addMethodEntriesOf(resultDescription,
1768:                        resultDescription.methodDescriptions,
1769:                        codeCompletionListEntries, true, includePrivateObjects,
1770:                        includePackageScopeObjects, includeProtectedObjects,
1771:                        onlySelectStaticAttributesAndMethods);
1772:                // inherited methods :
1773:                this .addMethodEntriesOf(resultDescription,
1774:                        resultDescription.inheritedMethodDescriptions,
1775:                        codeCompletionListEntries, false,
1776:                        false, // never include private objects of parent classes
1777:                        includePackageScopeObjects, includeProtectedObjects,
1778:                        onlySelectStaticAttributesAndMethods);
1779:                // inherited attributes :
1780:                this .addFieldEntriesOf(resultDescription,
1781:                        resultDescription.inheritedFieldDescriptions,
1782:                        codeCompletionListEntries, false,
1783:                        false, // never include private objects of parent classes
1784:                        includePackageScopeObjects, includeProtectedObjects,
1785:                        onlySelectStaticAttributesAndMethods);
1786:                // Same with all inscope member attributes :    
1787:                this .addFieldEntriesOf(resultDescription,
1788:                        resultDescription.fieldDescriptions,
1789:                        codeCompletionListEntries, true, includePrivateObjects,
1790:                        includePackageScopeObjects, includeProtectedObjects,
1791:                        onlySelectStaticAttributesAndMethods);
1792:
1793:                // A special case for visible class attributes when the cursor is inside
1794:                // a nested or anonymous class: In this case, one can extend the scope
1795:                // by writing <toplevel classname> this
1796:                // Therefore "this" is added like a class attribute for these cases:
1797:                if (onlySelectStaticAttributesAndMethods && sameFSDs) {
1798:                    FileStructureDescriptionForField this VirtualFieldFSD = new FileStructureDescriptionForField(
1799:                            Modifier.PUBLIC + Modifier.STATIC, false,
1800:                            new BooleanInteger(false, 0), Language
1801:                                    .Translate("toplevel scope extension to"),
1802:                            resultDescription.className.content, "this");
1803:                    final String objectNameString = this VirtualFieldFSD.objectNameWithPosition.content;
1804:                    final CodeCompletionListEntry entry = new CodeCompletionListEntry(
1805:                            resultDescription,
1806:                            this .fileStructureDescriptionManager,
1807:                            this VirtualFieldFSD, true) {
1808:                        public void run() {
1809:                            try {
1810:                                final int offset = insertPosition;
1811:                                final String string = objectNameString;
1812:                                final Style style = StylesFactory
1813:                                        .GetEditorTextStyle();
1814:                                editorPanel.getEditor().getDocument()
1815:                                        .insertString(offset, string, style);
1816:                            } catch (Exception ouiwermnb) {
1817:                                ouiwermnb.printStackTrace();
1818:                            }
1819:                        }
1820:                    };
1821:                    codeCompletionListEntries.addElement(entry);
1822:                } // if
1823:
1824:                // Plus attributes defined in an interface, if one or multiple interfaces
1825:                // were implemented, including the optionally following extension chains,
1826:                // which are created, when each interface again extends other
1827:                // interfaces [Note that an interface neither can implement anything nor
1828:                // can it extend a class - only option is <interface extends another interface> ].
1829:                // The complete extension chains are included by getAllFieldsFromAllInterfacesFor().
1830:                this .addFieldEntriesOf(resultDescription,
1831:                        CodeCompletionUtilities
1832:                                .GetAllFieldsFromAllInterfacesFor(
1833:                                        resultDescription,
1834:                                        this .fileStructureDescriptionManager),
1835:                        codeCompletionListEntries, true, includePrivateObjects,
1836:                        includePackageScopeObjects, includeProtectedObjects,
1837:                        onlySelectStaticAttributesAndMethods);
1838:
1839:                // static inner classes:            
1840:                this .addStaticInnerClassEntriesOf(resultDescription,
1841:                        resultDescription.innerClasses,
1842:                        codeCompletionListEntries, true,
1843:                        includePackageScopeObjects, includeProtectedObjects);
1844:
1845:                // Fast copy all into the returned array :           
1846:                final CodeCompletionListEntry[] codeCompletionListEntryArray = new CodeCompletionListEntry[codeCompletionListEntries
1847:                        .size()];
1848:                codeCompletionListEntries
1849:                        .copyInto(codeCompletionListEntryArray);
1850:
1851:                //ystem.out.println("CCSearch selectVisibleEntriesFrom " + resultDescription.className.content +
1852:                //                   " has found " + codeCompletionListEntryArray.length + " entries." );
1853:
1854:                return codeCompletionListEntryArray;
1855:            } // selectVisibleEntriesFrom
1856:
1857:            private boolean isParentOf(
1858:                    final FileStructureDescription parentCandidate,
1859:                    final FileStructureDescription child) {
1860:                boolean isParent = false;
1861:                for (int i = 0; i < child.parentDescriptions.length; i++) {
1862:                    final FileStructureDescription pFSD = child.parentDescriptions[i];
1863:                    if (pFSD.fullyQualifiedClassNameBuffer.toString().equals(
1864:                            parentCandidate.fullyQualifiedClassNameBuffer
1865:                                    .toString())) {
1866:                        isParent = true;
1867:                        break;
1868:                    }
1869:                }
1870:                return isParent;
1871:            } // isParentOf
1872:
1873:            /**     
1874:             *  Called from selectVisibleEntriesFrom().
1875:             */
1876:            private void addStaticInnerClassEntriesOf(
1877:                    final FileStructureDescription parentFSD,
1878:                    final Vector innerClasses,
1879:                    final Vector codeCompletionListEntries,
1880:                    final boolean isTopLevel,
1881:                    final boolean includePackageScopeObjects,
1882:                    final boolean includeProtectedObjects) {
1883:                for (int i = 0; i < innerClasses.size(); i++) {
1884:                    final FileStructureDescription this InnerClassFSD = (FileStructureDescription) innerClasses
1885:                            .elementAt(i);
1886:                    final String innerClassName = this InnerClassFSD.className.content;
1887:                    final CodeCompletionListEntry entry = new CodeCompletionListEntry(
1888:                            parentFSD, this .fileStructureDescriptionManager,
1889:                            this InnerClassFSD, isTopLevel) {
1890:                        public void run() {
1891:                            try {
1892:                                final int offset = insertPosition;
1893:                                String stringForInsertion = innerClassName;
1894:                                final Style style = StylesFactory
1895:                                        .GetEditorTextStyle();
1896:                                editorPanel.getEditor().getDocument()
1897:                                        .insertString(offset,
1898:                                                stringForInsertion, style);
1899:                            } catch (Exception kjhsdf) {
1900:                                kjhsdf.printStackTrace();
1901:                            }
1902:                        }
1903:                    };
1904:                    // Now add this, if the visibility conditions are ok :
1905:                    if (!this InnerClassFSD.isPrivate()) // private inner classes never are visible globally
1906:                    {
1907:                        if (includePackageScopeObjects
1908:                                || !this InnerClassFSD.isPackageScope()) {
1909:                            if (includeProtectedObjects
1910:                                    || !this InnerClassFSD.isProtected()) {
1911:                                if (this InnerClassFSD.isStatic()) // static is required always here
1912:                                {
1913:                                    codeCompletionListEntries.addElement(entry);
1914:                                }
1915:                            }
1916:                        }
1917:                    }
1918:                }
1919:            } // addStaticInnerClassEntriesOf
1920:
1921:            /**
1922:             *  Called from selectVisibleEntriesFrom().
1923:             */
1924:            private void addMethodEntriesOf(
1925:                    final FileStructureDescription parentFSD,
1926:                    final Vector methodDescriptions,
1927:                    final Vector codeCompletionListEntries,
1928:                    final boolean isTopLevel,
1929:                    final boolean includePrivateObjects,
1930:                    final boolean includePackageScopeObjects,
1931:                    final boolean includeProtectedObjects,
1932:                    final boolean onlyIncludeStaticMethods) {
1933:                for (int i = 0; i < methodDescriptions.size(); i++) {
1934:                    final FileStructureDescriptionForMethod this MethodFSD = (FileStructureDescriptionForMethod) methodDescriptions
1935:                            .elementAt(i);
1936:                    final String methodName = this MethodFSD.name.content;
1937:                    final CodeCompletionListEntry entry = new CodeCompletionListEntry(
1938:                            parentFSD, this .fileStructureDescriptionManager,
1939:                            this MethodFSD, isTopLevel) {
1940:                        public void run() {
1941:                            try {
1942:                                final int offset = insertPosition;
1943:                                String stringForInsertion = null;
1944:                                // If that method has no parameters, we can add both brackets :
1945:
1946:                                //ystem.out.println("np = " + thisMethodFSD.parameters.length);
1947:
1948:                                if (this MethodFSD.parameters.length == 0) {
1949:                                    stringForInsertion = methodName + "()";
1950:                                } else {
1951:                                    stringForInsertion = methodName + "(";
1952:                                    // NOTE: The additional "(" character will automatically
1953:                                    // launch the ParameterCompletion in the editor on insertion.
1954:                                }
1955:
1956:                                //ystem.out.println("Inserting: " + stringForInsertion );
1957:
1958:                                final Style style = StylesFactory
1959:                                        .GetEditorTextStyle();
1960:                                editorPanel.getEditor().getDocument()
1961:                                        .insertString(offset,
1962:                                                stringForInsertion, style);
1963:                            } catch (Exception kjhsdf) {
1964:                                kjhsdf.printStackTrace();
1965:                            }
1966:                        }
1967:                    };
1968:                    // Now add this, if the visibility conditions are ok :
1969:                    if (includePrivateObjects || !this MethodFSD.isPrivate()) {
1970:                        if (includePackageScopeObjects
1971:                                || !this MethodFSD.isPackageScope()) {
1972:                            if (includeProtectedObjects
1973:                                    || !this MethodFSD.isProtected()) {
1974:                                if (!onlyIncludeStaticMethods
1975:                                        || this MethodFSD.isStatic()) {
1976:                                    codeCompletionListEntries.addElement(entry);
1977:                                }
1978:                            }
1979:                        }
1980:                    }
1981:                }
1982:            } // addMethodEntriesOf
1983:
1984:            /**
1985:             *  Called from selectVisibleEntriesFrom().
1986:             */
1987:            private void addFieldEntriesOf(
1988:                    final FileStructureDescription parentFSD,
1989:                    final Vector fieldDescriptions,
1990:                    final Vector codeCompletionListEntries,
1991:                    final boolean isTopLevel,
1992:                    final boolean includePrivateObjects,
1993:                    final boolean includePackageScopeObjects,
1994:                    final boolean includeProtectedObjects,
1995:                    final boolean onlyIncludeStaticFields) {
1996:                final Vector fieldMenuItems = new Vector(); // of JMenuItem objects with functionality
1997:                for (int i = 0; i < fieldDescriptions.size(); i++) {
1998:                    final FileStructureDescriptionForField fieldFSD = (FileStructureDescriptionForField) fieldDescriptions
1999:                            .elementAt(i);
2000:                    final String objectNameString = fieldFSD.objectNameWithPosition.content;
2001:                    final CodeCompletionListEntry entry = new CodeCompletionListEntry(
2002:                            parentFSD, this .fileStructureDescriptionManager,
2003:                            fieldFSD, isTopLevel) {
2004:                        public void run() {
2005:                            try {
2006:                                final int offset = insertPosition;
2007:                                final String string = objectNameString;
2008:                                final Style style = StylesFactory
2009:                                        .GetEditorTextStyle();
2010:                                editorPanel.getEditor().getDocument()
2011:                                        .insertString(offset, string, style);
2012:                            } catch (Exception ouiwermnb) {
2013:                                ouiwermnb.printStackTrace();
2014:                            }
2015:                        }
2016:                    };
2017:                    // Now add this, if the visibility conditions are ok :
2018:                    if (includePrivateObjects || !fieldFSD.isPrivate()) {
2019:                        if (includePackageScopeObjects
2020:                                || !fieldFSD.isPackageScope()) {
2021:                            if (includeProtectedObjects
2022:                                    || !fieldFSD.isProtected()) {
2023:                                if (!onlyIncludeStaticFields
2024:                                        || fieldFSD.isStatic()) {
2025:                                    codeCompletionListEntries.addElement(entry);
2026:                                }
2027:                            }
2028:                        }
2029:                    }
2030:                }
2031:            } // addFieldEntriesOf
2032:
2033:            /**
2034:             *  Decompose a.b.c into the array {a,b,c}
2035:             *             
2036:             *  Also, parameter arguments are skipped in the decomposition, because they
2037:             *  lie one or more recursion levels deeper from the parser point of view :
2038:             *  Example: a.get( this.getX() ).b.c is decomposed into
2039:             *  { a, get( this.getX() ), b, c } that is: The point after "this" lies
2040:             *  deeper.                             
2041:             */
2042:            private String[] decompose(final String identifier) {
2043:
2044:                //ystem.out.println(">decompose starts. arg= " + identifier );
2045:
2046:                // Round brackets go one recursion step deeper.    
2047:                // Tokenize the first level only, but be prepared, that the brackets don't
2048:                // have to be balanced (because of possible syntax errors of the programmer).
2049:                Vector elementsVector = new Vector();
2050:                StringBuffer workText = new StringBuffer(""); // Empty
2051:                char workCharacter;
2052:                int childLevel = 0;
2053:                for (int i = 0; i < identifier.length(); i++) {
2054:                    workCharacter = identifier.charAt(i);
2055:                    if ((workCharacter == '.') && (childLevel == 0)) {
2056:                        // Add the existing text and make a new one ready :
2057:                        if (workText.length() > 0) {
2058:                            // Make a new uncoupled instance and add it:
2059:                            elementsVector.addElement(new String(workText
2060:                                    .toString()));
2061:                            workText.setLength(0);
2062:                        }
2063:                    } else if (workCharacter == '(') {
2064:                        childLevel++;
2065:                        workText.append(workCharacter);
2066:                    } else if (workCharacter == ')') {
2067:                        childLevel--;
2068:                        workText.append(workCharacter);
2069:                    } else {
2070:                        workText.append(workCharacter);
2071:                    }
2072:                } // for loop
2073:                // Ending : Add the workText, if it still contains characters :
2074:                if (workText.length() > 0) {
2075:                    elementsVector.addElement(new String(workText.toString()));
2076:                }
2077:                // Now get the level one parameters into an array :
2078:                String[] tokens = new String[elementsVector.size()];
2079:                elementsVector.copyInto(tokens);
2080:                elementsVector.removeAllElements();
2081:                elementsVector = null;
2082:                // Trim all:                          
2083:                for (int i = 0; i < tokens.length; i++) {
2084:                    tokens[i] = tokens[i].trim();
2085:                }
2086:                workText.setLength(0);
2087:                workText = null;
2088:                return tokens;
2089:            }
2090:
2091:            /**
2092:             *  Returns the position, where the bracket at the passed position
2093:             *  it closed.
2094:             *  openingBracketPosition must point to a opening bracket.
2095:             */
2096:            private int getPositionOfClosingBracket(final String s,
2097:                    int openingBracketPosition) {
2098:                int closingPosition = -1;
2099:                // Make sure, there is an opening bracket at openingBracketPosition:
2100:                if (s.charAt(openingBracketPosition) == '(') {
2101:                    if (openingBracketPosition < s.length()) {
2102:                        int bracketLevel = 0;
2103:                        int index = openingBracketPosition;
2104:                        char ch;
2105:                        while (index < s.length()) {
2106:                            ch = s.charAt(index);
2107:                            if (ch == '(') // Note: This will be true for the first run,
2108:                            { //       increasing bracketLevel to 1
2109:                                bracketLevel++;
2110:                            } else if (ch == ')') {
2111:                                bracketLevel--;
2112:                            }
2113:                            if (bracketLevel == 0) {
2114:                                closingPosition = index;
2115:                                break;
2116:                            }
2117:                            index++;
2118:                        } // while
2119:                    } // if
2120:                } else {
2121:                    //ystem.out.println("*** CCSearch.getPositionOfClosingBracket: Invalid opening bracket position.");
2122:                }
2123:                return closingPosition;
2124:            } // getPositionOfClosingBracket
2125:
2126:            /** 
2127:             *  Removes a possible cast.
2128:             */
2129:            private String checkRemoveCastIn(final String id) {
2130:                // Assume there is an opening bracket at the start.
2131:                int closingPosition = this .getPositionOfClosingBracket(id, 0);
2132:                if (closingPosition > 0) {
2133:                    return id.substring(closingPosition + 1);
2134:                } else {
2135:                    return id;
2136:                }
2137:            } // removeCastIn
2138:
2139:            /**
2140:             *  If the passed identifier starts with a typecast, this typecast
2141:             *  is returned as NumberedString, where the number is the
2142:             *  optional array dimension of the cast, or 1 for single types.
2143:             *  Otherwise null is returned.
2144:             */
2145:            private NumberedString checkReturnCastIn(String identifier) {
2146:                //ystem.out.println("checkReturnCastIn() called for identifier= " + identifier );
2147:
2148:                // Initialize the content as null, because this is signals, that
2149:                // no cast has been detected. The number is set to zero == no array as default.
2150:                NumberedString typeCast = new NumberedString(null, 0);
2151:                identifier = identifier.trim(); // get rid of leading spaces
2152:                if (identifier.startsWith("(")) {
2153:                    // If it's a valid typecast, the opening bracket must be followed
2154:                    // ONLY by java identifiers, white-spaces and finally by a closing bracket.
2155:                    // After that closing bracket, at least one java identifier must follow.
2156:                    int closingBracketPosition = -1;
2157:                    boolean isValidTypeCast = false;
2158:                    int stringIndex = 1;
2159:                    while (stringIndex < identifier.length()) {
2160:                        final char ch = identifier.charAt(stringIndex);
2161:                        if (ch == ')') {
2162:                            // The cast is valid, if there are some more characters left as identifier.
2163:                            isValidTypeCast = (stringIndex < identifier
2164:                                    .length() - 1);
2165:                            break;
2166:                        }
2167:                        if ((!Character.isJavaIdentifierPart(ch))
2168:                                && (!Character.isWhitespace(ch))) {
2169:                            isValidTypeCast = false;
2170:                            break;
2171:                        }
2172:                        stringIndex++;
2173:                    } // while
2174:                    if (isValidTypeCast) // return it
2175:                    {
2176:                        // The raw typecast string can contain a series of "[]" array symbols.
2177:                        String rawTypeCast = identifier.substring(1,
2178:                                stringIndex).trim();
2179:                        // Check for arrays and count them :
2180:                        int arrayDimension = 0; // 0 == no array but a single value            
2181:                        // The array symbols can have spaces or tabs or... between the brackets,
2182:                        // so take an easy solution: Just count the [ and ] characters. If the
2183:                        // syntax is wrong, the search anyway won't find anything:
2184:                        int leftBracketNumber = 0;
2185:                        int rightBracketNumber = 0;
2186:                        char ch;
2187:                        for (int i = 0; i < rawTypeCast.length(); i++) {
2188:                            ch = rawTypeCast.charAt(i);
2189:                            if (ch == '[')
2190:                                leftBracketNumber++;
2191:                            if (ch == ']')
2192:                                rightBracketNumber++;
2193:                        }
2194:                        if ((leftBracketNumber == rightBracketNumber)
2195:                                && (leftBracketNumber > 0)) {
2196:                            int firstLeftBracketPosition = rawTypeCast
2197:                                    .indexOf('[');
2198:                            typeCast.content = rawTypeCast.substring(0,
2199:                                    firstLeftBracketPosition);
2200:                            typeCast.number = leftBracketNumber; // array dimension
2201:                        } else {
2202:                            typeCast.content = rawTypeCast;
2203:                            typeCast.number = 0; // array dimension == single type ==> 1
2204:                        }
2205:                    }
2206:                } // if
2207:                return typeCast;
2208:            } // checkReturnCastIn
2209:
2210:            /**
2211:             *  Updates the transient fields of the passed fsd and adds the fsd to the
2212:             *  fsdsWithUpdatedTransientFields vector, so that it will be released
2213:             *  when freeAllTransientFields() is called.
2214:             *
2215:             *  ALWAYS use this method for updating transient fields, otherwise the
2216:             *  memory explodes.
2217:             */
2218:            private void updateTransientFieldsFor(
2219:                    final FileStructureDescription fsd) {
2220:                this .fileStructureDescriptionManager
2221:                        .updateTransientFieldsFor(fsd);
2222:                this .fsdsWithUpdatedTransientFields.addElement(fsd);
2223:            }
2224:
2225:            /**
2226:             *  This method must be called before the CodeCompletionSearch object is
2227:             *  left to the GC, so that all updated transient fields are released.
2228:             *  Otherwise the memory would explode.
2229:             */
2230:            public void freeAllTransientFields() {
2231:                FileStructureDescription fsd = null;
2232:                for (int i = 0; i < this .fsdsWithUpdatedTransientFields.size(); i++) {
2233:                    fsd = (FileStructureDescription) this .fsdsWithUpdatedTransientFields
2234:                            .elementAt(i);
2235:                    this .fileStructureDescriptionManager
2236:                            .releaseTransientFieldsFor(fsd);
2237:                }
2238:                this .fsdsWithUpdatedTransientFields.setSize(0);
2239:
2240:            } // freeAllTransientFields
2241:
2242:        } // CodeCompletionSearch
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.