KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > search > matching > TypeDeclarationPattern


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.search.matching;
12
13 import java.io.IOException JavaDoc;
14
15 import org.eclipse.jdt.core.compiler.CharOperation;
16 import org.eclipse.jdt.core.search.SearchPattern;
17 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
18 import org.eclipse.jdt.internal.core.index.*;
19
20 public class TypeDeclarationPattern extends JavaSearchPattern {
21
22 public char[] simpleName;
23 public char[] pkg;
24 public char[][] enclosingTypeNames;
25
26 // set to CLASS_SUFFIX for only matching classes
27
// set to INTERFACE_SUFFIX for only matching interfaces
28
// set to ENUM_SUFFIX for only matching enums
29
// set to ANNOTATION_TYPE_SUFFIX for only matching annotation types
30
// set to TYPE_SUFFIX for matching both classes and interfaces
31
public char typeSuffix;
32 public int modifiers;
33 public boolean secondary = false;
34
35 protected static char[][] CATEGORIES = { TYPE_DECL };
36
37 // want to save space by interning the package names for each match
38
static PackageNameSet internedPackageNames = new PackageNameSet(1001);
39 static class PackageNameSet {
40
41 public char[][] names;
42 public int elementSize; // number of elements in the table
43
public int threshold;
44
45 PackageNameSet(int size) {
46     this.elementSize = 0;
47     this.threshold = size; // size represents the expected number of elements
48
int extraRoom = (int) (size * 1.5f);
49     if (this.threshold == extraRoom)
50         extraRoom++;
51     this.names = new char[extraRoom][];
52 }
53
54 char[] add(char[] name) {
55     int length = names.length;
56     int index = CharOperation.hashCode(name) % length;
57     char[] current;
58     while ((current = names[index]) != null) {
59         if (CharOperation.equals(current, name)) return current;
60         if (++index == length) index = 0;
61     }
62     names[index] = name;
63
64     // assumes the threshold is never equal to the size of the table
65
if (++elementSize > threshold) rehash();
66     return name;
67 }
68
69 void rehash() {
70     PackageNameSet newSet = new PackageNameSet(elementSize * 2); // double the number of expected elements
71
char[] current;
72     for (int i = names.length; --i >= 0;)
73         if ((current = names[i]) != null)
74             newSet.add(current);
75
76     this.names = newSet.names;
77     this.elementSize = newSet.elementSize;
78     this.threshold = newSet.threshold;
79 }
80 }
81
82 /*
83  * Create index key for type declaration pattern:
84  * key = typeName / packageName / enclosingTypeName / modifiers
85  * or for secondary types
86  * key = typeName / packageName / enclosingTypeName / modifiers / 'S'
87  */

88 public static char[] createIndexKey(int modifiers, char[] typeName, char[] packageName, char[][] enclosingTypeNames, boolean secondary) { //, char typeSuffix) {
89
int typeNameLength = typeName == null ? 0 : typeName.length;
90     int packageLength = packageName == null ? 0 : packageName.length;
91     int enclosingNamesLength = 0;
92     if (enclosingTypeNames != null) {
93         for (int i = 0, length = enclosingTypeNames.length; i < length;) {
94             enclosingNamesLength += enclosingTypeNames[i].length;
95             if (++i < length)
96                 enclosingNamesLength++; // for the '.' separator
97
}
98     }
99
100     int resultLength = typeNameLength + packageLength + enclosingNamesLength + 5;
101     if (secondary) resultLength += 2;
102     char[] result = new char[resultLength];
103     int pos = 0;
104     if (typeNameLength > 0) {
105         System.arraycopy(typeName, 0, result, pos, typeNameLength);
106         pos += typeNameLength;
107     }
108     result[pos++] = SEPARATOR;
109     if (packageLength > 0) {
110         System.arraycopy(packageName, 0, result, pos, packageLength);
111         pos += packageLength;
112     }
113     result[pos++] = SEPARATOR;
114     if (enclosingTypeNames != null && enclosingNamesLength > 0) {
115         for (int i = 0, length = enclosingTypeNames.length; i < length;) {
116             char[] enclosingName = enclosingTypeNames[i];
117             int itsLength = enclosingName.length;
118             System.arraycopy(enclosingName, 0, result, pos, itsLength);
119             pos += itsLength;
120             if (++i < length)
121                 result[pos++] = '.';
122         }
123     }
124     result[pos++] = SEPARATOR;
125     result[pos++] = (char) modifiers;
126     result[pos] = (char) (modifiers>>16);
127     if (secondary) {
128         result[++pos] = SEPARATOR;
129         result[++pos] = 'S';
130     }
131     return result;
132 }
133
134 public TypeDeclarationPattern(
135     char[] pkg,
136     char[][] enclosingTypeNames,
137     char[] simpleName,
138     char typeSuffix,
139     int matchRule) {
140
141     this(matchRule);
142
143     this.pkg = isCaseSensitive() ? pkg : CharOperation.toLowerCase(pkg);
144     if (isCaseSensitive() || enclosingTypeNames == null) {
145         this.enclosingTypeNames = enclosingTypeNames;
146     } else {
147         int length = enclosingTypeNames.length;
148         this.enclosingTypeNames = new char[length][];
149         for (int i = 0; i < length; i++)
150             this.enclosingTypeNames[i] = CharOperation.toLowerCase(enclosingTypeNames[i]);
151     }
152     this.simpleName = (isCaseSensitive() || isCamelCase()) ? simpleName : CharOperation.toLowerCase(simpleName);
153     this.typeSuffix = typeSuffix;
154
155     ((InternalSearchPattern)this).mustResolve = (this.pkg != null && this.enclosingTypeNames != null) || typeSuffix != TYPE_SUFFIX;
156 }
157 TypeDeclarationPattern(int matchRule) {
158     super(TYPE_DECL_PATTERN, matchRule);
159 }
160 /*
161  * Type entries are encoded as:
162  * simpleTypeName / packageName / enclosingTypeName / modifiers
163  * e.g. Object/java.lang//0
164  * e.g. Cloneable/java.lang//512
165  * e.g. LazyValue/javax.swing/UIDefaults/0
166  * or for secondary types as:
167  * simpleTypeName / packageName / enclosingTypeName / modifiers / S
168  */

169 public void decodeIndexKey(char[] key) {
170     int slash = CharOperation.indexOf(SEPARATOR, key, 0);
171     this.simpleName = CharOperation.subarray(key, 0, slash);
172
173     int start = ++slash;
174     if (key[start] == SEPARATOR) {
175         this.pkg = CharOperation.NO_CHAR;
176     } else {
177         slash = CharOperation.indexOf(SEPARATOR, key, start);
178         this.pkg = internedPackageNames.add(CharOperation.subarray(key, start, slash));
179     }
180
181     // Continue key read by the end to decode modifiers
182
int last = key.length-1;
183     this.secondary = key[last] == 'S';
184     if (this.secondary) {
185         last -= 2;
186     }
187     this.modifiers = key[last-1] + (key[last]<<16);
188     decodeModifiers();
189
190     // Retrieve enclosing type names
191
start = slash + 1;
192     last -= 2; // position of ending slash
193
if (start == last) {
194         this.enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
195     } else {
196         if (last == (start+1) && key[start] == ZERO_CHAR) {
197             this.enclosingTypeNames = ONE_ZERO_CHAR;
198         } else {
199             this.enclosingTypeNames = CharOperation.splitOn('.', key, start, last);
200         }
201     }
202 }
203 protected void decodeModifiers() {
204
205     // Extract suffix from modifiers instead of index key
206
switch (this.modifiers & (ClassFileConstants.AccInterface|ClassFileConstants.AccEnum|ClassFileConstants.AccAnnotation)) {
207         case ClassFileConstants.AccAnnotation:
208         case ClassFileConstants.AccAnnotation+ClassFileConstants.AccInterface:
209             this.typeSuffix = ANNOTATION_TYPE_SUFFIX;
210             break;
211         case ClassFileConstants.AccEnum:
212             this.typeSuffix = ENUM_SUFFIX;
213             break;
214         case ClassFileConstants.AccInterface:
215             this.typeSuffix = INTERFACE_SUFFIX;
216             break;
217         default:
218             this.typeSuffix = CLASS_SUFFIX;
219             break;
220     }
221 }
222 public SearchPattern getBlankPattern() {
223     return new TypeDeclarationPattern(R_EXACT_MATCH | R_CASE_SENSITIVE);
224 }
225 public char[][] getIndexCategories() {
226     return CATEGORIES;
227 }
228 public boolean matchesDecodedKey(SearchPattern decodedPattern) {
229     TypeDeclarationPattern pattern = (TypeDeclarationPattern) decodedPattern;
230     
231     // check type suffix
232
if (this.typeSuffix != pattern.typeSuffix && typeSuffix != TYPE_SUFFIX) {
233         if (!matchDifferentTypeSuffixes(this.typeSuffix, pattern.typeSuffix)) {
234             return false;
235         }
236     }
237
238     // check name
239
if (!matchesName(this.simpleName, pattern.simpleName))
240         return false;
241
242     // check package - exact match only
243
if (this.pkg != null && !CharOperation.equals(this.pkg, pattern.pkg, isCaseSensitive()))
244         return false;
245
246     // check enclosingTypeNames - exact match only
247
if (this.enclosingTypeNames != null) {
248         if (this.enclosingTypeNames.length == 0)
249             return pattern.enclosingTypeNames.length == 0;
250         if (this.enclosingTypeNames.length == 1 && pattern.enclosingTypeNames.length == 1)
251             return CharOperation.equals(this.enclosingTypeNames[0], pattern.enclosingTypeNames[0], isCaseSensitive());
252         if (pattern.enclosingTypeNames == ONE_ZERO_CHAR)
253             return true; // is a local or anonymous type
254
return CharOperation.equals(this.enclosingTypeNames, pattern.enclosingTypeNames, isCaseSensitive());
255     }
256     return true;
257 }
258 EntryResult[] queryIn(Index index) throws IOException JavaDoc {
259     char[] key = this.simpleName; // can be null
260
int matchRule = getMatchRule();
261
262     switch(getMatchMode()) {
263         case R_PREFIX_MATCH :
264             // do a prefix query with the simpleName
265
break;
266         case R_EXACT_MATCH :
267             if (this.isCamelCase) break;
268             matchRule &= ~R_EXACT_MATCH;
269             if (this.simpleName != null) {
270                 matchRule |= R_PREFIX_MATCH;
271                 key = this.pkg == null
272                     ? CharOperation.append(this.simpleName, SEPARATOR)
273                     : CharOperation.concat(this.simpleName, SEPARATOR, this.pkg, SEPARATOR, CharOperation.NO_CHAR);
274                 break; // do a prefix query with the simpleName and possibly the pkg
275
}
276             matchRule |= R_PATTERN_MATCH;
277             // fall thru to encode the key and do a pattern query
278
case R_PATTERN_MATCH :
279             if (this.pkg == null) {
280                 if (this.simpleName == null) {
281                     switch(this.typeSuffix) {
282                         case CLASS_SUFFIX :
283                         case INTERFACE_SUFFIX :
284                         case ENUM_SUFFIX :
285                         case ANNOTATION_TYPE_SUFFIX :
286                         case CLASS_AND_INTERFACE_SUFFIX :
287                         case CLASS_AND_ENUM_SUFFIX :
288                         case INTERFACE_AND_ANNOTATION_SUFFIX :
289                             // null key already returns all types
290
// key = new char[] {ONE_STAR[0], SEPARATOR, ONE_STAR[0]};
291
break;
292                     }
293                 } else if (this.simpleName[this.simpleName.length - 1] != '*') {
294                     key = CharOperation.concat(this.simpleName, ONE_STAR, SEPARATOR);
295                 }
296                 break; // do a pattern query with the current encoded key
297
}
298             // must decode to check enclosingTypeNames due to the encoding of local types
299
key = CharOperation.concat(
300                 this.simpleName == null ? ONE_STAR : this.simpleName, SEPARATOR, this.pkg, SEPARATOR, ONE_STAR);
301             break;
302         case R_REGEXP_MATCH :
303             // TODO (frederic) implement regular expression match
304
break;
305     }
306
307     return index.query(getIndexCategories(), key, matchRule); // match rule is irrelevant when the key is null
308
}
309 protected StringBuffer JavaDoc print(StringBuffer JavaDoc output) {
310     switch (this.typeSuffix){
311         case CLASS_SUFFIX :
312             output.append("ClassDeclarationPattern: pkg<"); //$NON-NLS-1$
313
break;
314         case CLASS_AND_INTERFACE_SUFFIX:
315             output.append("ClassAndInterfaceDeclarationPattern: pkg<"); //$NON-NLS-1$
316
break;
317         case CLASS_AND_ENUM_SUFFIX :
318             output.append("ClassAndEnumDeclarationPattern: pkg<"); //$NON-NLS-1$
319
break;
320         case INTERFACE_SUFFIX :
321             output.append("InterfaceDeclarationPattern: pkg<"); //$NON-NLS-1$
322
break;
323         case INTERFACE_AND_ANNOTATION_SUFFIX:
324             output.append("InterfaceAndAnnotationDeclarationPattern: pkg<"); //$NON-NLS-1$
325
break;
326         case ENUM_SUFFIX :
327             output.append("EnumDeclarationPattern: pkg<"); //$NON-NLS-1$
328
break;
329         case ANNOTATION_TYPE_SUFFIX :
330             output.append("AnnotationTypeDeclarationPattern: pkg<"); //$NON-NLS-1$
331
break;
332         default :
333             output.append("TypeDeclarationPattern: pkg<"); //$NON-NLS-1$
334
break;
335     }
336     if (pkg != null)
337         output.append(pkg);
338     else
339         output.append("*"); //$NON-NLS-1$
340
output.append(">, enclosing<"); //$NON-NLS-1$
341
if (enclosingTypeNames != null) {
342         for (int i = 0; i < enclosingTypeNames.length; i++){
343             output.append(enclosingTypeNames[i]);
344             if (i < enclosingTypeNames.length - 1)
345                 output.append('.');
346         }
347     } else {
348         output.append("*"); //$NON-NLS-1$
349
}
350     output.append(">, type<"); //$NON-NLS-1$
351
if (simpleName != null)
352         output.append(simpleName);
353     else
354         output.append("*"); //$NON-NLS-1$
355
output.append(">"); //$NON-NLS-1$
356
return super.print(output);
357 }
358 }
359
Popular Tags