KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > index > Index


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.core.index;
12
13 import java.io.*;
14
15 import org.eclipse.jdt.core.compiler.CharOperation;
16 import org.eclipse.jdt.core.search.*;
17 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
18 import org.eclipse.jdt.internal.compiler.util.SimpleSet;
19 import org.eclipse.jdt.internal.core.search.indexing.ReadWriteMonitor;
20
21 /**
22  * An <code>Index</code> maps document names to their referenced words in various categories.
23  *
24  * Queries can search a single category or several at the same time.
25  *
26  * Indexes are not synchronized structures and should only be queried/updated one at a time.
27  */

28
29 public class Index {
30
31 public String JavaDoc containerPath;
32 public ReadWriteMonitor monitor;
33
34 protected DiskIndex diskIndex;
35 protected MemoryIndex memoryIndex;
36
37 /**
38  * Mask used on match rule for indexing.
39  */

40 static final int MATCH_RULE_INDEX_MASK =
41     SearchPattern.R_EXACT_MATCH |
42     SearchPattern.R_PREFIX_MATCH |
43     SearchPattern.R_PATTERN_MATCH |
44     SearchPattern.R_REGEXP_MATCH |
45     SearchPattern.R_CASE_SENSITIVE |
46     SearchPattern.R_CAMELCASE_MATCH;
47
48 public static boolean isMatch(char[] pattern, char[] word, int matchRule) {
49     if (pattern == null) return true;
50     int patternLength = pattern.length;
51     int wordLength = word.length;
52     if (patternLength == 0) return matchRule != SearchPattern.R_EXACT_MATCH;
53     if (wordLength == 0) return (matchRule & SearchPattern.R_PATTERN_MATCH) != 0 && patternLength == 1 && pattern[0] == '*';
54
55     // First test camel case if necessary
56
boolean isCamelCase = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0;
57     if (isCamelCase && pattern[0] == word[0] && CharOperation.camelCaseMatch(pattern, word)) {
58         return true;
59     }
60
61     // need to mask some bits of pattern rule (bug 79790)
62
matchRule &= ~SearchPattern.R_CAMELCASE_MATCH;
63     switch(matchRule & MATCH_RULE_INDEX_MASK) {
64         case SearchPattern.R_EXACT_MATCH :
65             if (!isCamelCase) {
66                 return patternLength == wordLength && CharOperation.equals(pattern, word, false);
67             }
68             // fall through prefix match if camel case failed
69
case SearchPattern.R_PREFIX_MATCH :
70             return patternLength <= wordLength && CharOperation.prefixEquals(pattern, word, false);
71         case SearchPattern.R_PATTERN_MATCH :
72             return CharOperation.match(pattern, word, false);
73         case SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE :
74             if (!isCamelCase) {
75                 return pattern[0] == word[0] && patternLength == wordLength && CharOperation.equals(pattern, word);
76             }
77             // fall through prefix match if camel case failed
78
case SearchPattern.R_PREFIX_MATCH | SearchPattern.R_CASE_SENSITIVE :
79             return pattern[0] == word[0] && patternLength <= wordLength && CharOperation.prefixEquals(pattern, word);
80         case SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE :
81             return CharOperation.match(pattern, word, true);
82     }
83     return false;
84 }
85
86
87 public Index(String JavaDoc fileName, String JavaDoc containerPath, boolean reuseExistingFile) throws IOException {
88     this.containerPath = containerPath;
89     this.monitor = new ReadWriteMonitor();
90
91     this.memoryIndex = new MemoryIndex();
92     this.diskIndex = new DiskIndex(fileName);
93     this.diskIndex.initialize(reuseExistingFile);
94 }
95 public void addIndexEntry(char[] category, char[] key, String JavaDoc containerRelativePath) {
96     this.memoryIndex.addIndexEntry(category, key, containerRelativePath);
97 }
98 public String JavaDoc containerRelativePath(String JavaDoc documentPath) {
99     int index = documentPath.indexOf(IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR);
100     if (index == -1) {
101         index = this.containerPath.length();
102         if (documentPath.length() <= index)
103             throw new IllegalArgumentException JavaDoc("Document path " + documentPath + " must be relative to " + this.containerPath); //$NON-NLS-1$ //$NON-NLS-2$
104
}
105     return documentPath.substring(index + 1);
106 }
107 public File getIndexFile() {
108     return this.diskIndex == null ? null : this.diskIndex.indexFile;
109 }
110 public boolean hasChanged() {
111     return this.memoryIndex.hasChanged();
112 }
113 /**
114  * Returns the entries containing the given key in a group of categories, or null if no matches are found.
115  * The matchRule dictates whether its an exact, prefix or pattern match, as well as case sensitive or insensitive.
116  * If the key is null then all entries in specified categories are returned.
117  */

118 public EntryResult[] query(char[][] categories, char[] key, int matchRule) throws IOException {
119     if (this.memoryIndex.shouldMerge() && monitor.exitReadEnterWrite()) {
120         try {
121             save();
122         } finally {
123             monitor.exitWriteEnterRead();
124         }
125     }
126
127     HashtableOfObject results;
128     int rule = matchRule & MATCH_RULE_INDEX_MASK;
129     if (this.memoryIndex.hasChanged()) {
130         results = this.diskIndex.addQueryResults(categories, key, rule, this.memoryIndex);
131         results = this.memoryIndex.addQueryResults(categories, key, rule, results);
132     } else {
133         results = this.diskIndex.addQueryResults(categories, key, rule, null);
134     }
135     if (results == null) return null;
136
137     EntryResult[] entryResults = new EntryResult[results.elementSize];
138     int count = 0;
139     Object JavaDoc[] values = results.valueTable;
140     for (int i = 0, l = values.length; i < l; i++) {
141         EntryResult result = (EntryResult) values[i];
142         if (result != null)
143             entryResults[count++] = result;
144     }
145     return entryResults;
146 }
147 /**
148  * Returns the document names that contain the given substring, if null then returns all of them.
149  */

150 public String JavaDoc[] queryDocumentNames(String JavaDoc substring) throws IOException {
151     SimpleSet results;
152     if (this.memoryIndex.hasChanged()) {
153         results = this.diskIndex.addDocumentNames(substring, this.memoryIndex);
154         this.memoryIndex.addDocumentNames(substring, results);
155     } else {
156         results = this.diskIndex.addDocumentNames(substring, null);
157     }
158     if (results.elementSize == 0) return null;
159
160     String JavaDoc[] documentNames = new String JavaDoc[results.elementSize];
161     int count = 0;
162     Object JavaDoc[] paths = results.values;
163     for (int i = 0, l = paths.length; i < l; i++)
164         if (paths[i] != null)
165             documentNames[count++] = (String JavaDoc) paths[i];
166     return documentNames;
167 }
168 public void remove(String JavaDoc containerRelativePath) {
169     this.memoryIndex.remove(containerRelativePath);
170 }
171 public void save() throws IOException {
172     // must own the write lock of the monitor
173
if (!hasChanged()) return;
174
175     int numberOfChanges = this.memoryIndex.docsToReferences.elementSize;
176     this.diskIndex = this.diskIndex.mergeWith(this.memoryIndex);
177     this.memoryIndex = new MemoryIndex();
178     if (numberOfChanges > 1000)
179         System.gc(); // reclaim space if the MemoryIndex was very BIG
180
}
181 public void startQuery() {
182     if (this.diskIndex != null)
183         this.diskIndex.startQuery();
184 }
185 public void stopQuery() {
186     if (this.diskIndex != null)
187         this.diskIndex.stopQuery();
188 }
189 public String JavaDoc toString() {
190     return "Index for " + this.containerPath; //$NON-NLS-1$
191
}
192 }
193
Popular Tags