| /******************************************************************************* |
| * Copyright (c) 2000, 2007 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 |
| * |
| |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.corext.util; |
| |
| import org.eclipse.dltk.core.ISearchPatternProcessor; |
| import org.eclipse.dltk.core.ISearchPatternProcessor.ITypePattern; |
| import org.eclipse.dltk.core.search.IDLTKSearchConstants; |
| import org.eclipse.dltk.core.search.IDLTKSearchScope; |
| import org.eclipse.dltk.core.search.SearchEngine; |
| import org.eclipse.dltk.core.search.SearchPattern; |
| import org.eclipse.dltk.core.search.TypeNameMatch; |
| import org.eclipse.dltk.internal.ui.util.StringMatcher; |
| import org.eclipse.dltk.ui.IDLTKUILanguageToolkit; |
| import org.eclipse.dltk.ui.dialogs.ITypeInfoFilterExtension; |
| |
| public class TypeInfoFilter { |
| |
| private static class PatternMatcher { |
| |
| private String fPattern; |
| private int fMatchKind; |
| private StringMatcher fStringMatcher; |
| |
| private static final char END_SYMBOL = '<'; |
| private static final char ANY_STRING = '*'; |
| private static final char BLANK = ' '; |
| |
| public PatternMatcher(String pattern, boolean ignoreCase) { |
| this(pattern, SearchPattern.R_EXACT_MATCH |
| | SearchPattern.R_PREFIX_MATCH |
| | SearchPattern.R_PATTERN_MATCH |
| | SearchPattern.R_CAMELCASE_MATCH); |
| } |
| |
| public PatternMatcher(String pattern, int allowedModes) { |
| initializePatternAndMatchKind(pattern); |
| fMatchKind = fMatchKind & allowedModes; |
| if (fMatchKind == SearchPattern.R_PATTERN_MATCH) { |
| fStringMatcher = new StringMatcher(fPattern, true, false); |
| } |
| } |
| |
| public String getPattern() { |
| return fPattern; |
| } |
| |
| public int getMatchKind() { |
| return fMatchKind; |
| } |
| |
| public boolean matches(String text) { |
| switch (fMatchKind) { |
| case SearchPattern.R_PATTERN_MATCH: |
| return fStringMatcher.match(text); |
| case SearchPattern.R_EXACT_MATCH: |
| return fPattern.equalsIgnoreCase(text); |
| case SearchPattern.R_CAMELCASE_MATCH: |
| if (SearchPattern.camelCaseMatch(fPattern, text)) { |
| return true; |
| } |
| // fall through to prefix match if camel case failed (bug |
| // 137244) |
| default: |
| return Strings.startsWithIgnoreCase(text, fPattern); |
| } |
| } |
| |
| private void initializePatternAndMatchKind(String pattern) { |
| int length = pattern.length(); |
| if (length == 0) { |
| fMatchKind = SearchPattern.R_EXACT_MATCH; |
| fPattern = pattern; |
| return; |
| } |
| char last = pattern.charAt(length - 1); |
| |
| if (pattern.indexOf('*') != -1 || pattern.indexOf('?') != -1) { |
| fMatchKind = SearchPattern.R_PATTERN_MATCH; |
| switch (last) { |
| case END_SYMBOL: |
| fPattern = pattern.substring(0, length - 1); |
| break; |
| case BLANK: |
| fPattern = pattern.trim(); |
| break; |
| case ANY_STRING: |
| fPattern = pattern; |
| break; |
| default: |
| fPattern = pattern + ANY_STRING; |
| } |
| return; |
| } |
| |
| if (last == END_SYMBOL) { |
| fMatchKind = SearchPattern.R_EXACT_MATCH; |
| fPattern = pattern.substring(0, length - 1); |
| return; |
| } |
| |
| if (last == BLANK) { |
| fMatchKind = SearchPattern.R_EXACT_MATCH; |
| fPattern = pattern.trim(); |
| return; |
| } |
| |
| if (SearchUtils.isCamelCasePattern(pattern)) { |
| fMatchKind = SearchPattern.R_CAMELCASE_MATCH; |
| fPattern = pattern; |
| return; |
| } |
| |
| fMatchKind = SearchPattern.R_PREFIX_MATCH; |
| fPattern = pattern; |
| } |
| } |
| |
| private String fText; |
| private final IDLTKSearchScope fSearchScope; |
| private final boolean fIsWorkspaceScope; |
| private int fElementKind; |
| private ITypeInfoFilterExtension fFilterExtension; |
| private TypeInfoRequestorAdapter fAdapter = new TypeInfoRequestorAdapter(); |
| |
| private PatternMatcher fPackageMatcher; |
| private PatternMatcher fNameMatcher; |
| |
| private static final int TYPE_MODIFIERS = 0; |
| |
| public TypeInfoFilter(IDLTKUILanguageToolkit uiToolkit, String text, |
| IDLTKSearchScope scope, int elementKind, |
| ITypeInfoFilterExtension extension, |
| ISearchPatternProcessor processor) { |
| fText = text; |
| fSearchScope = scope; |
| fIsWorkspaceScope = fSearchScope.equals(SearchEngine |
| .createWorkspaceScope(uiToolkit.getCoreToolkit())); |
| fElementKind = elementKind; |
| fFilterExtension = extension; |
| ITypePattern pattern = processor.parseType(text); |
| String simpleName = pattern.getSimpleName(); |
| if (simpleName.length() == 0) { |
| simpleName = "*"; |
| } |
| fNameMatcher = new PatternMatcher(simpleName, true); |
| if (pattern.getQualification() != null) { |
| fPackageMatcher = new PatternMatcher( |
| evaluatePackagePattern(pattern.getQualification()), true); |
| } |
| } |
| |
| /* |
| * Transforms o.e.j to o*.e*.j* |
| */ |
| private String evaluatePackagePattern(String s) { |
| StringBuilder buf = new StringBuilder(); |
| boolean hasWildCard = false; |
| int len = s.length(); |
| for (int i = 0; i < len; i++) { |
| char ch = s.charAt(i); |
| if (ch == ISearchPatternProcessor.TYPE_SEPARATOR) { |
| if (!hasWildCard) { |
| buf.append('*'); |
| } |
| hasWildCard = false; |
| } else if (ch == '*' || ch == '?') { |
| hasWildCard = true; |
| } |
| buf.append(ch); |
| } |
| if (!hasWildCard) { |
| if (len == 0) { |
| buf.append('?'); |
| } |
| buf.append('*'); |
| } |
| return buf.toString(); |
| } |
| |
| public String getText() { |
| return fText; |
| } |
| |
| public boolean isSubFilter(String text) { |
| if (!fText.startsWith(text)) |
| return false; |
| |
| return fPackageMatcher == null; |
| } |
| |
| public boolean isCamelCasePattern() { |
| return fNameMatcher.getMatchKind() == SearchPattern.R_CAMELCASE_MATCH; |
| } |
| |
| public String getPackagePattern() { |
| if (fPackageMatcher == null) |
| return null; |
| return fPackageMatcher.getPattern(); |
| } |
| |
| public String getNamePattern() { |
| return fNameMatcher.getPattern(); |
| } |
| |
| public int getSearchFlags() { |
| return fNameMatcher.getMatchKind(); |
| } |
| |
| public int getPackageFlags() { |
| if (fPackageMatcher == null) |
| return SearchPattern.R_EXACT_MATCH; |
| |
| return fPackageMatcher.getMatchKind(); |
| } |
| |
| public boolean matchesRawNamePattern(TypeNameMatch type) { |
| return Strings.startsWithIgnoreCase(type.getSimpleTypeName(), |
| fNameMatcher.getPattern()); |
| } |
| |
| public boolean matchesCachedResult(TypeNameMatch type) { |
| if (!(matchesPackage(type) && matchesFilterExtension(type))) |
| return false; |
| return matchesName(type); |
| } |
| |
| public boolean matchesHistoryElement(TypeNameMatch type) { |
| if (!(matchesPackage(type) && matchesModifiers(type) |
| && matchesScope(type) && matchesFilterExtension(type))) |
| return false; |
| return matchesName(type); |
| } |
| |
| public boolean matchesFilterExtension(TypeNameMatch type) { |
| if (fFilterExtension == null) |
| return true; |
| fAdapter.setMatch(type); |
| return fFilterExtension.select(fAdapter); |
| } |
| |
| private boolean matchesName(TypeNameMatch type) { |
| return fNameMatcher.matches(type.getSimpleTypeName()); |
| } |
| |
| private boolean matchesPackage(TypeNameMatch type) { |
| if (fPackageMatcher == null) |
| return true; |
| return fPackageMatcher.matches(type.getTypeContainerName()); |
| } |
| |
| private boolean matchesScope(TypeNameMatch type) { |
| if (fIsWorkspaceScope) |
| return true; |
| return fSearchScope.encloses(type.getType()); |
| } |
| |
| private boolean matchesModifiers(TypeNameMatch type) { |
| if (fElementKind == IDLTKSearchConstants.TYPE) |
| return true; |
| int modifiers = type.getModifiers() & TYPE_MODIFIERS; |
| switch (fElementKind) { |
| case IDLTKSearchConstants.TYPE: |
| return modifiers == 0; |
| } |
| return false; |
| } |
| |
| } |