| /******************************************************************************* |
| * Copyright (c) 2000, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.core.search.matching; |
| |
| import java.io.IOException; |
| |
| import org.eclipse.jdt.core.compiler.CharOperation; |
| import org.eclipse.jdt.core.search.SearchPattern; |
| import org.eclipse.jdt.internal.core.index.*; |
| |
| public class MultiTypeDeclarationPattern extends JavaSearchPattern { |
| |
| public char[][] simpleNames; |
| public char[][] qualifications; |
| |
| // set to CLASS_SUFFIX for only matching classes |
| // set to INTERFACE_SUFFIX for only matching interfaces |
| // set to ENUM_SUFFIX for only matching enums |
| // set to ANNOTATION_TYPE_SUFFIX for only matching annotation types |
| // set to TYPE_SUFFIX for matching both classes and interfaces |
| public char typeSuffix; |
| |
| protected static char[][] CATEGORIES = { TYPE_DECL }; |
| |
| public MultiTypeDeclarationPattern( |
| char[][] qualifications, |
| char[][] simpleNames, |
| char typeSuffix, |
| int matchRule) { |
| |
| this(matchRule); |
| |
| if (this.isCaseSensitive || qualifications == null) { |
| this.qualifications = qualifications; |
| } else { |
| int length = qualifications.length; |
| this.qualifications = new char[length][]; |
| for (int i = 0; i < length; i++) |
| this.qualifications[i] = CharOperation.toLowerCase(qualifications[i]); |
| } |
| // null simple names are allowed (should return all names) |
| if (simpleNames != null) { |
| if (this.isCaseSensitive || this.isCamelCase) { |
| this.simpleNames = simpleNames; |
| } else { |
| int length = simpleNames.length; |
| this.simpleNames = new char[length][]; |
| for (int i = 0; i < length; i++) |
| this.simpleNames[i] = CharOperation.toLowerCase(simpleNames[i]); |
| } |
| } |
| this.typeSuffix = typeSuffix; |
| |
| this.mustResolve = typeSuffix != TYPE_SUFFIX; // only used to report type declarations, not their positions |
| } |
| MultiTypeDeclarationPattern(int matchRule) { |
| super(TYPE_DECL_PATTERN, matchRule); |
| } |
| public SearchPattern getBlankPattern() { |
| return new QualifiedTypeDeclarationPattern(R_EXACT_MATCH | R_CASE_SENSITIVE); |
| } |
| public char[][] getIndexCategories() { |
| return CATEGORIES; |
| } |
| public boolean matchesDecodedKey(SearchPattern decodedPattern) { |
| QualifiedTypeDeclarationPattern pattern = (QualifiedTypeDeclarationPattern) decodedPattern; |
| |
| // check type suffix |
| if (this.typeSuffix != pattern.typeSuffix && this.typeSuffix != TYPE_SUFFIX) { |
| if (!matchDifferentTypeSuffixes(this.typeSuffix, pattern.typeSuffix)) { |
| return false; |
| } |
| } |
| |
| // check qualified name |
| if (this.qualifications != null) { |
| int count = 0; |
| int max = this.qualifications.length; |
| if (max == 0 && pattern.qualification.length > 0) { |
| return false; |
| } |
| if (max > 0) { |
| for (; count < max; count++) |
| if (matchesName(this.qualifications[count], pattern.qualification)) |
| break; |
| if (count == max) return false; |
| } |
| } |
| |
| // check simple name (null are allowed) |
| if (this.simpleNames == null) return true; |
| int count = 0; |
| int max = this.simpleNames.length; |
| for (; count < max; count++) |
| if (matchesName(this.simpleNames[count], pattern.simpleName)) |
| break; |
| return count < max; |
| } |
| public EntryResult[] queryIn(Index index) throws IOException { |
| if (this.simpleNames == null) { |
| // if no simple names then return all possible ones from index |
| return index.query(getIndexCategories(), null, -1); // match rule is irrelevant when the key is null |
| } |
| |
| int count = -1; |
| int numOfNames = this.simpleNames.length; |
| EntryResult[][] allResults = numOfNames > 1 ? new EntryResult[numOfNames][] : null; |
| for (int i = 0; i < numOfNames; i++) { |
| char[] key = this.simpleNames[i]; |
| int matchRule = getMatchRule(); |
| |
| switch(getMatchMode()) { |
| case R_PREFIX_MATCH : |
| // do a prefix query with the simpleName |
| break; |
| case R_EXACT_MATCH : |
| // do a prefix query with the simpleName |
| matchRule &= ~R_EXACT_MATCH; |
| matchRule |= R_PREFIX_MATCH; |
| key = CharOperation.append(key, SEPARATOR); |
| break; |
| case R_PATTERN_MATCH : |
| if (key[key.length - 1] != '*') |
| key = CharOperation.concat(key, ONE_STAR, SEPARATOR); |
| break; |
| case R_REGEXP_MATCH : |
| // TODO (frederic) implement regular expression match |
| break; |
| case R_CAMELCASE_MATCH: |
| case R_CAMELCASE_SAME_PART_COUNT_MATCH: |
| // do a prefix query with the simpleName |
| break; |
| } |
| |
| EntryResult[] entries = index.query(getIndexCategories(), key, matchRule); // match rule is irrelevant when the key is null |
| if (entries != null) { |
| if (allResults == null) return entries; |
| allResults[++count] = entries; |
| } |
| } |
| |
| if (count == -1) return null; |
| int total = 0; |
| for (int i = 0; i <= count; i++) |
| total += allResults[i].length; |
| EntryResult[] allEntries = new EntryResult[total]; |
| int next = 0; |
| for (int i = 0; i <= count; i++) { |
| EntryResult[] entries = allResults[i]; |
| System.arraycopy(entries, 0, allEntries, next, entries.length); |
| next += entries.length; |
| } |
| return allEntries; |
| } |
| protected StringBuffer print(StringBuffer output) { |
| switch (this.typeSuffix){ |
| case CLASS_SUFFIX : |
| output.append("MultiClassDeclarationPattern: "); //$NON-NLS-1$ |
| break; |
| case CLASS_AND_INTERFACE_SUFFIX : |
| output.append("MultiClassAndInterfaceDeclarationPattern: "); //$NON-NLS-1$ |
| break; |
| case CLASS_AND_ENUM_SUFFIX : |
| output.append("MultiClassAndEnumDeclarationPattern: "); //$NON-NLS-1$ |
| break; |
| case INTERFACE_SUFFIX : |
| output.append("MultiInterfaceDeclarationPattern: "); //$NON-NLS-1$ |
| break; |
| case INTERFACE_AND_ANNOTATION_SUFFIX : |
| output.append("MultiInterfaceAndAnnotationDeclarationPattern: "); //$NON-NLS-1$ |
| break; |
| case ENUM_SUFFIX : |
| output.append("MultiEnumDeclarationPattern: "); //$NON-NLS-1$ |
| break; |
| case ANNOTATION_TYPE_SUFFIX : |
| output.append("MultiAnnotationTypeDeclarationPattern: "); //$NON-NLS-1$ |
| break; |
| default : |
| output.append("MultiTypeDeclarationPattern: "); //$NON-NLS-1$ |
| break; |
| } |
| if (this.qualifications != null) { |
| output.append("qualifications: <"); //$NON-NLS-1$ |
| for (int i = 0; i < this.qualifications.length; i++){ |
| output.append(this.qualifications[i]); |
| if (i < this.qualifications.length - 1) |
| output.append(", "); //$NON-NLS-1$ |
| } |
| output.append("> "); //$NON-NLS-1$ |
| } |
| if (this.simpleNames != null) { |
| output.append("simpleNames: <"); //$NON-NLS-1$ |
| for (int i = 0; i < this.simpleNames.length; i++){ |
| output.append(this.simpleNames[i]); |
| if (i < this.simpleNames.length - 1) |
| output.append(", "); //$NON-NLS-1$ |
| } |
| output.append(">"); //$NON-NLS-1$ |
| } |
| return super.print(output); |
| } |
| } |