fixed bug: "not indexed" variables in comma separated lists
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / builder / IdentifierIndexManager.java
1 package net.sourceforge.phpeclipse.builder;
2
3 import java.io.BufferedInputStream;
4 import java.io.BufferedReader;
5 import java.io.FileNotFoundException;
6 import java.io.FileReader;
7 import java.io.FileWriter;
8 import java.io.IOException;
9 import java.io.InputStream;
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.Comparator;
13 import java.util.HashMap;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Set;
17 import java.util.SortedMap;
18 import java.util.StringTokenizer;
19 import java.util.TreeMap;
20
21 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
22 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
23 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
24 import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
25 import net.sourceforge.phpdt.internal.compiler.util.Util;
26 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
27 import net.sourceforge.phpeclipse.obfuscator.PHPIdentifier;
28
29 import org.eclipse.core.resources.IFile;
30 import org.eclipse.core.runtime.CoreException;
31 import org.eclipse.core.runtime.IStatus;
32
33 /**
34  * Manages the identifer index information for a specific project
35  *  
36  */
37 public class IdentifierIndexManager {
38   public class LineCreator implements ITerminalSymbols {
39     private Scanner fScanner;
40
41     private int fToken;
42
43     public LineCreator() {
44       fScanner = new Scanner(true, false, false, false, true, null, null);
45     }
46
47     /**
48      * Add the information of the current identifier to the line
49      * 
50      * @param typeOfIdentifier
51      *          the type of the identifier ('c'lass, 'd'efine, 'f'unction, 'm'ethod(class), 'v'ariable(class) 'g'lobal variable)
52      * @param identifier
53      *          current identifier
54      * @param line
55      *          Buffer for the current index line
56      * @param phpdocOffset
57      *          the offset of the PHPdoc comment if available
58      * @param phpdocLength
59      *          the length of the PHPdoc comment if available
60      */
61     private void addIdentifierInformation(char typeOfIdentifier, char[] identifier, StringBuffer line, int phpdocOffset,
62         int phpdocLength) {
63       line.append('\t');
64       line.append(typeOfIdentifier);
65       line.append(identifier);
66       line.append("\to"); // Offset
67       line.append(fScanner.getCurrentTokenStartPosition());
68       if (phpdocOffset >= 0) {
69         line.append("\tp"); // phpdoc offset
70         line.append(phpdocOffset);
71         line.append("\tl"); // phpdoc length
72         line.append(phpdocLength);
73       }
74     }
75
76     private void addClassVariableInformation(char typeOfIdentifier, char[] identifier, StringBuffer line, int phpdocOffset,
77         int phpdocLength) {
78       line.append('\t');
79       line.append(typeOfIdentifier);
80       line.append(identifier);
81       line.append("\to"); // Offset
82       // we don't store the '$' in the index for class variables:
83       line.append(fScanner.getCurrentTokenStartPosition() + 1);
84       if (phpdocOffset >= 0) {
85         line.append("\tp"); // phpdoc offset
86         line.append(phpdocOffset);
87         line.append("\tl"); // phpdoc length
88         line.append(phpdocLength);
89       }
90     }
91
92     /**
93      * Get the next token from input
94      */
95     private void getNextToken() {
96       try {
97         fToken = fScanner.getNextToken();
98         if (Scanner.DEBUG) {
99           int currentEndPosition = fScanner.getCurrentTokenEndPosition();
100           int currentStartPosition = fScanner.getCurrentTokenStartPosition();
101           System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
102           System.out.println(fScanner.toStringAction(fToken));
103         }
104         return;
105       } catch (InvalidInputException e) {
106         // ignore errors
107         //        e.printStackTrace();
108       }
109       fToken = TokenNameERROR;
110     }
111
112     private void parseDeclarations(char[] parent, StringBuffer buf, boolean goBack) {
113       char[] ident;
114       char[] classVariable;
115       int counter = 0;
116       boolean hasModifiers = false;
117       int phpdocOffset = -1;
118       int phpdocLength = -1;
119       try {
120         while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
121           phpdocOffset = -1;
122           hasModifiers = false;
123           if (fToken == TokenNameCOMMENT_PHPDOC) {
124             phpdocOffset = fScanner.getCurrentTokenStartPosition();
125             phpdocLength = fScanner.getCurrentTokenEndPosition() - fScanner.getCurrentTokenStartPosition() + 1;
126             getNextToken();
127             while (fToken == TokenNamestatic || fToken == TokenNamefinal || fToken == TokenNamepublic
128                 || fToken == TokenNameprotected || fToken == TokenNameprivate || fToken == TokenNameabstract) {
129               hasModifiers = true;
130               getNextToken();
131             }
132             if (fToken == TokenNameEOF || fToken == TokenNameERROR) {
133               break;
134             }
135           }
136           if (fToken == TokenNamefunction) {
137             getNextToken();
138             if (fToken == TokenNameAND) {
139               getNextToken();
140             }
141             if (fToken == TokenNameIdentifier) {
142               ident = fScanner.getCurrentIdentifierSource();
143               if (parent != null && equalCharArrays(parent, ident)) {
144                 // constructor function
145                 addIdentifierInformation('k', ident, buf, phpdocOffset, phpdocLength);
146               } else {
147                 if (parent != null) {
148                   // class method function
149                   addIdentifierInformation('m', ident, buf, phpdocOffset, phpdocLength);
150                 } else {
151                   // nested function ?!
152                   addIdentifierInformation('f', ident, buf, phpdocOffset, phpdocLength);
153                 }
154               }
155               getNextToken();
156               parseDeclarations(null, buf, true);
157             }
158           } else if (fToken == TokenNameclass || fToken == TokenNameinterface) {
159             getNextToken();
160             if (fToken == TokenNameIdentifier) {
161               ident = fScanner.getCurrentIdentifierSource();
162               addIdentifierInformation('c', ident, buf, phpdocOffset, phpdocLength);
163               getNextToken();
164               //skip tokens for classname, extends and others until we have
165               // the opening '{'
166               while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) {
167                 getNextToken();
168               }
169               parseDeclarations(ident, buf, true);
170             }
171           } else if (fToken == TokenNamevar || hasModifiers || fToken == TokenNamestatic || fToken == TokenNamefinal
172               || fToken == TokenNamepublic || fToken == TokenNameprotected || fToken == TokenNameprivate) {
173             while (fToken == TokenNamevar || fToken == TokenNamestatic || fToken == TokenNamefinal || fToken == TokenNamepublic
174                 || fToken == TokenNameprotected || fToken == TokenNameprivate) {
175               getNextToken();
176             }
177             while (fToken == TokenNameVariable) {
178               ident = fScanner.getCurrentIdentifierSource();
179               classVariable = new char[ident.length - 1];
180               System.arraycopy(ident, 1, classVariable, 0, ident.length - 1);
181               addClassVariableInformation('v', classVariable, buf, phpdocOffset, phpdocLength);
182               getNextToken();
183               if (fToken == TokenNameCOMMA) {
184                 getNextToken();
185               }
186             }
187           } else if (!hasModifiers && fToken == TokenNameIdentifier) {
188             ident = fScanner.getCurrentIdentifierSource();
189             getNextToken();
190             if (ident.length == 6 && ident[0] == 'd' && ident[1] == 'e' && ident[2] == 'f' && ident[3] == 'i' && ident[4] == 'n'
191                 && ident[5] == 'e') {
192               if (fToken == TokenNameLPAREN) {
193                 getNextToken();
194                 if (fToken == TokenNameStringDoubleQuote) {
195                   ident = fScanner.getCurrentStringLiteralSource();
196                   addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength);
197                   getNextToken();
198                 }
199               }
200             }
201           } else if (fToken == TokenNameglobal) {
202             // global variable
203             while (fToken != TokenNameEOF && fToken != TokenNameERROR && fToken != TokenNameSEMICOLON && fToken != TokenNameLBRACE
204                 && fToken != TokenNameRBRACE) {
205               getNextToken();
206               if (fToken == TokenNameVariable) {
207                 ident = fScanner.getCurrentIdentifierSource();
208                 addIdentifierInformation('g', ident, buf, phpdocOffset, phpdocLength);
209               }
210             }
211           } else if (fToken == TokenNameLBRACE) {
212             getNextToken();
213             counter++;
214           } else if (fToken == TokenNameRBRACE) {
215             getNextToken();
216             --counter;
217             if (counter == 0 && goBack) {
218               return;
219             }
220           } else {
221             getNextToken();
222           }
223         }
224       } catch (SyntaxError e) {
225         // TODO Auto-generated catch block
226         e.printStackTrace();
227       }
228     }
229
230     synchronized public void parseIdentifiers(char[] charArray, StringBuffer buf) {
231       char[] ident;
232       String identifier;
233       int counter = 0;
234       boolean hasModifiers = false;
235       int phpdocOffset = -1;
236       int phpdocLength = -1;
237       fScanner.setSource(charArray);
238       fScanner.setPHPMode(false);
239       fToken = TokenNameEOF;
240       getNextToken();
241       try {
242         while (fToken != TokenNameEOF) { // && fToken != TokenNameERROR) {
243           phpdocOffset = -1;
244           hasModifiers = false;
245           if (fToken == TokenNameCOMMENT_PHPDOC) {
246             phpdocOffset = fScanner.getCurrentTokenStartPosition();
247             phpdocLength = fScanner.getCurrentTokenEndPosition() - fScanner.getCurrentTokenStartPosition() + 1;
248             getNextToken();
249             while (fToken == TokenNamestatic || fToken == TokenNamefinal || fToken == TokenNamepublic
250                 || fToken == TokenNameprotected || fToken == TokenNameprivate || fToken == TokenNameabstract) {
251               hasModifiers = true;
252               getNextToken();
253             }
254             if (fToken == TokenNameEOF || fToken == TokenNameERROR) {
255               break;
256             }
257           }
258           if (fToken == TokenNamefunction) {
259             getNextToken();
260             if (fToken == TokenNameAND) {
261               getNextToken();
262             }
263             if (fToken == TokenNameIdentifier) {
264               ident = fScanner.getCurrentIdentifierSource();
265               addIdentifierInformation('f', ident, buf, phpdocOffset, phpdocLength);
266               getNextToken();
267               parseDeclarations(null, buf, true);
268             }
269           } else if (fToken == TokenNameclass || fToken == TokenNameinterface) {
270             getNextToken();
271             if (fToken == TokenNameIdentifier) {
272               ident = fScanner.getCurrentIdentifierSource();
273               addIdentifierInformation('c', ident, buf, phpdocOffset, phpdocLength);
274               getNextToken();
275               //skip fTokens for classname, extends and others until we have
276               // the opening '{'
277               while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) {
278                 getNextToken();
279               }
280               parseDeclarations(ident, buf, true);
281             }
282           } else if (fToken == TokenNameVariable) {
283             // global variable
284             ident = fScanner.getCurrentIdentifierSource();
285             addIdentifierInformation('g', ident, buf, phpdocOffset, phpdocLength);
286             getNextToken();
287           } else if (!hasModifiers && fToken == TokenNameIdentifier) {
288             ident = fScanner.getCurrentIdentifierSource();
289             getNextToken();
290             if (ident.length == 6 && ident[0] == 'd' && ident[1] == 'e' && ident[2] == 'f' && ident[3] == 'i' && ident[4] == 'n'
291                 && ident[5] == 'e') {
292               if (fToken == TokenNameLPAREN) {
293                 getNextToken();
294                 if (fToken == TokenNameStringDoubleQuote) {
295                   ident = fScanner.getCurrentStringLiteralSource();
296                   addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength);
297                   getNextToken();
298                 }
299               }
300             }
301           } else {
302             getNextToken();
303           }
304         }
305       } catch (SyntaxError e) {
306         // TODO Auto-generated catch block
307         e.printStackTrace();
308       }
309     }
310   }
311
312   class StringComparator implements Comparator {
313     public int compare(Object o1, Object o2) {
314       String s1 = (String) o1;
315       String s2 = (String) o2;
316       return s1.compareTo(s2);
317       //        return s1.toUpperCase().compareTo(s2.toUpperCase());
318     }
319
320     public boolean equals(Object o) {
321       String s = (String) o;
322       return compare(this, o) == 0;
323     }
324   }
325
326   private HashMap fFileMap;
327
328   private String fFilename;
329
330   private TreeMap fIndentifierMap;
331
332   public IdentifierIndexManager(String filename) {
333     fFilename = filename;
334     initialize();
335     readFile();
336   }
337
338   /**
339    * Check if 2 char arrays are equal
340    * 
341    * @param a
342    * @param b
343    * @return
344    */
345   private static boolean equalCharArrays(char[] a, char[] b) {
346     if (a.length != b.length) {
347       return false;
348     }
349     for (int i = 0; i < b.length; i++) {
350       if (a[i] != b[i]) {
351         return false;
352       }
353     }
354     return true;
355   }
356
357   public LineCreator createLineCreator() {
358     return new LineCreator();
359   }
360
361   /**
362    * Add the information for a given IFile resource
363    *  
364    */
365   public void addFile(IFile fileToParse) {
366     //    InputStream iStream;
367     LineCreator lineCreator = createLineCreator();
368     try {
369       addInputStream(new BufferedInputStream(fileToParse.getContents()), fileToParse.getProjectRelativePath().toString(),
370           lineCreator);
371     } catch (CoreException e1) {
372       // TODO Auto-generated catch block
373       e1.printStackTrace();
374     }
375   }
376
377   /**
378    * @param fileToParse
379    * @param lineCreator
380    * @throws CoreException
381    */
382   public void addInputStream(InputStream stream, String filePath, LineCreator lineCreator) throws CoreException {
383     try {
384       StringBuffer lineBuffer = new StringBuffer();
385       lineBuffer.append(filePath);
386       int lineLength = lineBuffer.length();
387       lineCreator.parseIdentifiers(Util.getInputStreamAsCharArray(stream, -1, null), lineBuffer);
388       //      if (lineLength != lineBuffer.length()) {
389       // always add the file for Open Include Action
390       addLine(lineBuffer.toString());
391       //      }
392     } catch (IOException e) {
393       e.printStackTrace();
394     } finally {
395       try {
396         if (stream != null) {
397           stream.close();
398         }
399       } catch (IOException e) {
400       }
401     }
402   }
403
404   /**
405    * Adds a line of the index file for function, class, class-method and class-variable names
406    * 
407    * @param line
408    */
409   private void addLine(String line) {
410     StringTokenizer tokenizer;
411     String phpFileName = null;
412     String token;
413     String identifier = null;
414     String classname = null;
415     String offset = null;
416     PHPIdentifierLocation phpIdentifier = null;
417     boolean tokenExists = false;
418     tokenizer = new StringTokenizer(line, "\t");
419     // first token contains the filename:
420     if (tokenizer.hasMoreTokens()) {
421       phpFileName = tokenizer.nextToken();
422       //System.out.println(token);
423     } else {
424       return;
425     }
426     // all the other tokens are identifiers:
427     while (tokenizer.hasMoreTokens()) {
428       token = tokenizer.nextToken();
429       //System.out.println(token);
430       switch (token.charAt(0)) {
431       case 'c':
432         // class name
433         identifier = token.substring(1);
434         classname = identifier;
435         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CLASS, phpFileName);
436         break;
437       case 'd':
438         // define
439         identifier = token.substring(1);
440         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.DEFINE, phpFileName);
441         break;
442       case 'f':
443         // function name
444         identifier = token.substring(1);
445         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.FUNCTION, phpFileName);
446         break;
447       case 'g':
448         // global variable
449         identifier = token.substring(1);
450         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.GLOBAL_VARIABLE, phpFileName);
451         break;
452       case 'k':
453         // constructor function name
454         identifier = token.substring(1);
455         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CONSTRUCTOR, phpFileName);
456         break;
457       case 'm':
458         //method inside a class
459         identifier = token.substring(1);
460         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.METHOD, phpFileName, classname);
461         break;
462       case 'v':
463         // variable inside a class
464         identifier = token.substring(1);
465         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.VARIABLE, phpFileName, classname);
466         break;
467       case 'o':
468         // offset information
469         identifier = null;
470         if (phpIdentifier != null) {
471           offset = token.substring(1);
472           phpIdentifier.setOffset(Integer.parseInt(offset));
473         }
474         break;
475       case 'p':
476         // PHPdoc offset information
477         identifier = null;
478         if (phpIdentifier != null) {
479           offset = token.substring(1);
480           phpIdentifier.setPHPDocOffset(Integer.parseInt(offset));
481         }
482         break;
483       case 'l':
484         // PHPdoc length information
485         identifier = null;
486         if (phpIdentifier != null) {
487           offset = token.substring(1);
488           phpIdentifier.setPHPDocLength(Integer.parseInt(offset));
489         }
490         break;
491       default:
492         PHPeclipsePlugin.log(IStatus.ERROR, "Unknown token character in IdentifierIndexManager: " + token.charAt(0));
493         identifier = null;
494         phpIdentifier = null;
495         classname = null;
496       }
497       if (identifier != null && phpIdentifier != null) {
498         tokenExists = true;
499         ArrayList list = (ArrayList) fIndentifierMap.get(identifier);
500         if (list == null) {
501           list = new ArrayList();
502           list.add(phpIdentifier);
503           fIndentifierMap.put(identifier, list);
504         } else {
505           boolean flag = false;
506           for (int i = 0; i < list.size(); i++) {
507             if (list.get(i).equals(phpIdentifier)) {
508               flag = true;
509               break;
510             }
511           }
512           if (flag == false) {
513             list.add(phpIdentifier);
514           }
515         }
516       }
517     }
518     //    if (tokenExists) {
519     fFileMap.put(phpFileName, line);
520     //    }
521   }
522
523   /**
524    * Change the information for a given IFile resource
525    *  
526    */
527   public void changeFile(IFile fileToParse) {
528     removeFile(fileToParse);
529     addFile(fileToParse);
530   }
531
532   /**
533    * Get a list of all PHPIdentifierLocation object's associated with an identifier
534    * 
535    * @param identifier
536    * @return
537    */
538   public List getLocations(String identifier) {
539     return (List) fIndentifierMap.get(identifier);
540   }
541
542   /**
543    * Initialize (i.e. clear) the current index information
544    *  
545    */
546   public void initialize() {
547     fIndentifierMap = new TreeMap(new StringComparator());
548     fFileMap = new HashMap();
549   }
550
551   private void readFile() {
552     FileReader fileReader;
553     try {
554       fileReader = new FileReader(fFilename);
555       BufferedReader bufferedReader = new BufferedReader(fileReader);
556       String line;
557       while (bufferedReader.ready()) {
558         // all entries for one file are in a line
559         // separated by tabs !
560         line = bufferedReader.readLine();
561         addLine(line);
562       }
563       fileReader.close();
564     } catch (FileNotFoundException e) {
565       // ignore this
566       // TODO DialogBox which asks the user if she/he likes to build new index?
567     } catch (IOException e) {
568       // TODO Auto-generated catch block
569       e.printStackTrace();
570     }
571   }
572
573   /**
574    * Remove the information for a given IFile resource
575    *  
576    */
577   public void removeFile(IFile fileToParse) {
578     //    String line = (String)
579     // fFileMap.get(fileToParse.getLocation().toString());
580     String line = (String) fFileMap.get(fileToParse.getProjectRelativePath().toString());
581     if (line != null) {
582       removeLine(line);
583     }
584   }
585
586   /**
587    * Removes a line of the index file for function, class, class-method and class-variable names
588    * 
589    * @param line
590    */
591   private void removeLine(String line) {
592     StringTokenizer tokenizer;
593     String phpFileName = null;
594     String token;
595     String identifier = null;
596     String classname = null;
597     PHPIdentifier phpIdentifier = null;
598     boolean tokenExists = false;
599     tokenizer = new StringTokenizer(line, "\t");
600     // first token contains the filename:
601     if (tokenizer.hasMoreTokens()) {
602       phpFileName = tokenizer.nextToken();
603       //System.out.println(token);
604     } else {
605       return;
606     }
607     int offset = -1;
608     // all the other tokens are identifiers:
609     while (tokenizer.hasMoreTokens()) {
610       token = tokenizer.nextToken();
611       //System.out.println(token);
612       switch (token.charAt(0)) {
613       case 'c':
614         // class name
615         identifier = token.substring(1);
616         classname = identifier;
617         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CLASS, phpFileName);
618         break;
619       case 'd':
620         // define
621         identifier = token.substring(1);
622         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.DEFINE, phpFileName);
623         break;
624       case 'f':
625         // function name
626         identifier = token.substring(1);
627         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.FUNCTION, phpFileName);
628         break;
629       case 'g':
630         // global variable
631         identifier = token.substring(1);
632         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.GLOBAL_VARIABLE, phpFileName);
633         break;
634       case 'k':
635         // constructor function name
636         identifier = token.substring(1);
637         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CONSTRUCTOR, phpFileName);
638         break;
639       case 'm':
640         //method inside a class
641         identifier = token.substring(1);
642         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.METHOD, phpFileName, classname);
643         break;
644       case 'o':
645         // offset information
646         identifier = null;
647         break;
648       case 'p':
649         // PHPdoc offset information
650         identifier = null;
651         break;
652       case 'l':
653         // PHPdoc length information
654         identifier = null;
655         break;
656       case 'v':
657         // variable inside a class
658         identifier = token.substring(1);
659         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.VARIABLE, phpFileName, classname);
660         break;
661       default:
662         PHPeclipsePlugin.log(IStatus.ERROR, "Unknown token character in IdentifierIndexManager: " + token.charAt(0));
663         identifier = null;
664         phpIdentifier = null;
665         classname = null;
666       }
667       if (identifier != null && phpIdentifier != null) {
668         ArrayList list = (ArrayList) fIndentifierMap.get(identifier);
669         if (list == null) {
670         } else {
671           for (int i = 0; i < list.size(); i++) {
672             if (list.get(i).equals(phpIdentifier)) {
673               list.remove(i);
674               break;
675             }
676           }
677           if (list.size() == 0) {
678             fIndentifierMap.remove(identifier);
679           }
680         }
681       }
682     }
683     fFileMap.remove(phpFileName);
684   }
685
686   /**
687    * Save the current index information in the projects index file
688    *  
689    */
690   public void writeFile() {
691     FileWriter fileWriter;
692     try {
693       fileWriter = new FileWriter(fFilename);
694       String line;
695       Collection collection = fFileMap.values();
696       Iterator iterator = collection.iterator();
697       while (iterator.hasNext()) {
698         line = (String) iterator.next();
699         fileWriter.write(line + '\n');
700       }
701       fileWriter.close();
702     } catch (FileNotFoundException e) {
703       // ignore exception; project is deleted by user
704     } catch (IOException e) {
705       // TODO Auto-generated catch block
706       e.printStackTrace();
707     }
708   }
709
710   /**
711    * @param fromKey
712    * @param toKey
713    * @return
714    */
715   public SortedMap getIdentifierMap() {
716     return fIndentifierMap;
717   }
718
719   synchronized public List getFileList(String filePattern) {
720     Set set = fFileMap.keySet();
721     if (set.isEmpty()) {
722       return null;
723     }
724     Iterator iter = set.iterator();
725     ArrayList list = new ArrayList();
726     String fileName;
727     int index;
728     while (iter.hasNext()) {
729       fileName = (String) iter.next();
730       if ((index = fileName.indexOf(filePattern)) != -1 && fileName.length() == (index + filePattern.length())) {
731         list.add(fileName);
732       }
733     }
734     return list;
735   }
736 }