blob: c142084b003e46409a36db9c1a7876c11e7bbc86 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* 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:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.sdk.util.type;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.scout.commons.CompareUtility;
import org.eclipse.scout.sdk.util.internal.SdkUtilActivator;
import org.eclipse.scout.sdk.util.typecache.ITypeHierarchy;
/**
*
*/
public class TypeFilters {
private final static ITypeFilter INTERFACE_FILTER = new ITypeFilter() {
@Override
public boolean accept(IType candidate) {
try {
int flags = candidate.getFlags();
return Flags.isInterface(flags) && !Flags.isDeprecated(flags);
}
catch (JavaModelException e) {
SdkUtilActivator.logWarning("could not evalutate flags of type '" + candidate.getFullyQualifiedName() + "'.", e);
return false;
}
}
};
private final static ITypeFilter EXISTS_FILTER = new ITypeFilter() {
@Override
public boolean accept(IType type) {
return TypeUtility.exists(type);
}
};
private final static ITypeFilter CLASS_FILTER = new ITypeFilter() {
@Override
public boolean accept(IType candidate) {
return isClass(candidate);
}
};
private final static ITypeFilter TOP_LEVEL_FILTER = new ITypeFilter() {
@Override
public boolean accept(IType type) {
return TypeUtility.exists(type) && !TypeUtility.exists(type.getDeclaringType());
}
};
private final static ITypeFilter IN_WORKSPACE_FILTER = new ITypeFilter() {
@Override
public boolean accept(IType type) {
return !type.isBinary() && !type.isReadOnly();
}
};
protected TypeFilters() {
}
public static ITypeFilter invertFilter(final ITypeFilter filter) {
return new ITypeFilter() {
@Override
public boolean accept(IType type) {
return !filter.accept(type);
}
};
}
/**
* @param type
* @return
* @note this filter is expensive - for every candidate a super type hierarchy will be created. Use
* {@link TypeFilters#getSubtypeFilter(IType, ITypeHierarchy)} when ever possible.
*/
public static ITypeFilter getSubtypeFilter(final IType type) {
return new ITypeFilter() {
@Override
public boolean accept(IType candidate) {
try {
org.eclipse.jdt.core.ITypeHierarchy hierarchy = candidate.newSupertypeHierarchy(null);
return hierarchy.contains(type);
}
catch (JavaModelException e) {
SdkUtilActivator.logWarning("could not create super hierarchy of '" + candidate.getElementName() + "'.", e);
return false;
}
}
};
}
public static ITypeFilter getSubtypeFilter(final IType type, final ITypeHierarchy hierarchy) {
return new ITypeFilter() {
@Override
public boolean accept(IType candidate) {
return hierarchy.isSubtype(type, candidate);
}
};
}
public static ITypeFilter getElementNameFilter(final String typeName) {
return new ITypeFilter() {
@Override
public boolean accept(IType type) {
return type.getElementName().equals(typeName);
}
};
}
/**
* Creates and gets a new type filter that accepts all types where the simple name matches the given regex with the
* given regex flags.
*
* @param regex
* The expression to use
* @param flags
* The regex flags to use. A bit mask that may include {@link Pattern#CASE_INSENSITIVE},
* {@link Pattern#MULTILINE}, {@link Pattern#DOTALL}, {@link Pattern#UNICODE_CASE}, {@link Pattern#CANON_EQ},
* {@link Pattern#UNIX_LINES}, {@link Pattern#LITERAL} and {@link Pattern#COMMENTS}
* @return the created filter
*/
public static ITypeFilter getRegexSimpleNameFilter(final String regex, int flags) {
final Pattern pat = Pattern.compile(regex, flags);
return new ITypeFilter() {
@Override
public boolean accept(IType type) {
return pat.matcher(type.getElementName()).matches();
}
};
}
/**
* Creates and gets a new type filter that accepts all types where the simple name matches the given regex pattern.<br>
* <b>Note: The given regex uses case-insensitive matching!</b>
*
* @param regex
* The regex to use for the matching.
* @return the created filter
*/
public static ITypeFilter getRegexSimpleNameFilter(final String regex) {
return getRegexSimpleNameFilter(regex, Pattern.CASE_INSENSITIVE);
}
public static ITypeFilter getInnerTypeFilter(final IType type) {
return new ITypeFilter() {
@Override
public boolean accept(IType t) {
if (t != null) {
if (t.equals(type)) {
return true;
}
else {
return accept(t.getDeclaringType());
}
}
return false;
}
};
}
public static ITypeFilter getTypesInProject(final IJavaProject project) {
return new ITypeFilter() {
@Override
public boolean accept(IType type) {
if (!TypeUtility.exists(type)) {
return false;
}
return CompareUtility.equals(type.getJavaProject(), project);
}
};
}
public static ITypeFilter getTypesOnClasspath(final IJavaProject project) {
return new ITypeFilter() {
@Override
public boolean accept(IType candidate) {
if (!TypeUtility.exists(candidate)) {
return false;
}
return TypeUtility.isOnClasspath(candidate, project);
}
};
}
public static ITypeFilter getInWorkspaceFilter() {
return IN_WORKSPACE_FILTER;
}
public static ITypeFilter getTopLevelTypeFilter() {
return TOP_LEVEL_FILTER;
}
public static ITypeFilter getInnerClasses(final IType declaringType) {
return new ITypeFilter() {
@Override
public boolean accept(IType candidate) {
if (!TypeUtility.exists(candidate)) {
return false;
}
IType candidateDeclaringType = candidate.getDeclaringType();
return candidateDeclaringType != null && candidateDeclaringType.equals(declaringType) && isClass(candidate);
}
};
}
public static ITypeFilter getInHierarchyFilter(final ITypeHierarchy hierarchy) {
return new ITypeFilter() {
@Override
public boolean accept(IType type) {
return hierarchy.contains(type);
}
};
}
public static ITypeFilter getAbstractOnClasspath(final IJavaProject project) {
return new ITypeFilter() {
@Override
public boolean accept(IType type) {
try {
int flags = type.getFlags();
return !Flags.isInterface(flags) && Flags.isAbstract(flags) && !Flags.isDeprecated(flags) && TypeUtility.isOnClasspath(type, project);
}
catch (JavaModelException e) {
SdkUtilActivator.logError("could not filter type '" + type.getFullyQualifiedName() + "'.", e);
return false;
}
}
};
}
public static ITypeFilter getFlagsFilter(final int flags) {
return new ITypeFilter() {
@Override
public boolean accept(IType type) {
try {
int typeFlags = type.getFlags();
return ((typeFlags & flags) == flags);
}
catch (JavaModelException e) {
SdkUtilActivator.logError("could not filter type '" + type.getFullyQualifiedName() + "'.", e);
return false;
}
}
};
}
/**
* Gets a filter that accepts only types that are classes.<br>
* A class is defined as a type that is neither abstract, an interface or deprecated.
*
* @return The filter that only accepts classes.
* @see #isClass(IType)
*/
public static ITypeFilter getClassFilter() {
return CLASS_FILTER;
}
public static ITypeFilter getExistingFilter() {
return EXISTS_FILTER;
}
public static ITypeFilter getNotInTypes(IType[]... excludedTypes) {
HashSet<IType> excludedSet = new HashSet<IType>();
if (excludedTypes != null) {
for (IType[] list : excludedTypes) {
for (IType t : list) {
excludedSet.add(t);
}
}
}
return getNotInTypes(excludedSet);
}
public static ITypeFilter getNotInTypes(IType... excludedTypes) {
HashSet<IType> excludedSet = null;
if (excludedTypes != null) {
excludedSet = new HashSet<IType>(excludedTypes.length);
for (IType t : excludedTypes) {
excludedSet.add(t);
}
}
else {
excludedSet = new HashSet<IType>(0);
}
return getNotInTypes(excludedSet);
}
public static ITypeFilter getNotInTypes(final Set<IType> excludedTypes) {
return new ITypeFilter() {
@Override
public boolean accept(IType type) {
if (excludedTypes == null) {
return true;
}
return !excludedTypes.contains(type);
}
};
}
public static ITypeFilter getInterfaceFilter() {
return INTERFACE_FILTER;
}
/**
* Gets if the given type is a class.<br>
* A class is defined as a type that is neither abstract, an interface or deprecated.
*
* @param type
* The type to check
* @return true if the given type has none of the following flags: abstract, interface, deprecated
* @see Flags#isAbstract(int)
* @see Flags#isInterface(int)
* @see Flags#isDeprecated(int)
*/
protected static boolean isClass(IType type) {
try {
int flags = type.getFlags();
return !Flags.isAbstract(flags) && !Flags.isInterface(flags) && !Flags.isDeprecated(flags);
}
catch (JavaModelException e) {
SdkUtilActivator.logWarning("could not evalutate flags of type '" + type.getFullyQualifiedName() + "'.", e);
return false;
}
}
public static ITypeFilter getMultiTypeFilterOr(final ITypeFilter... filters) {
return new ITypeFilter() {
@Override
public boolean accept(IType candidate) {
if (filters == null) {
return true;
}
else {
for (ITypeFilter f : filters) {
if (f.accept(candidate)) {
return true;
}
}
return false;
}
}
};
}
public static ITypeFilter getMultiTypeFilter(final ITypeFilter... filters) {
if (filters == null) {
return null;
}
return new ITypeFilter() {
@Override
public boolean accept(IType candidate) {
for (ITypeFilter f : filters) {
if (!f.accept(candidate)) {
return false;
}
}
return true;
}
};
}
}