/*******************************************************************************
* 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.EntryResult;
import org.eclipse.jdt.internal.core.index.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);
}
}