/**
* Optimus, framework for Model Transformation
*
* Copyright (C) 2013 Worldline or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.atos.optimus.common.tools.jdt;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import net.atos.optimus.common.tools.jdt.jstcomp.ASTArrayTypeHelper;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IExtendedModifier;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.WildcardType;
import org.eclipse.jface.text.Document;
/**
* Contains helper methods about Java code manipulation
*
* @author Maxence Vanbésien (mvaawl@gmail.com)
* @since 1.0
*/
public class JavaCodeHelper {
/**
* Compiler options used inside this Java code Merger
*/
@SuppressWarnings("unchecked")
public static Map<String, String> compilerOptions = JavaCore.getOptions();
static {
// Set compiler options to 1.5 level
compilerOptions.put("org.eclipse.jdt.core.compiler.source", "1.5");
}
/**
* Generated annotation class name.
*/
public static final String GENERATED_CLASSNAME = javax.annotation.Generated.class.getName();
/**
* Generated annotation simple class name.
*/
public static final String GENERATED_SIMPLECLASSNAME = javax.annotation.Generated.class.getSimpleName();
/**
* Return a AbstractTypeDeclaration instance defined in a CompilationUnit
* with typeName as name
*
* @param cu
* A compilation unit object
* @param typeName
* The name of the type searched
* @return a AbstractTypeDeclaration object associated with typeName, null
* if not found or typeName null
*/
public static AbstractTypeDeclaration getTypeDeclaration(CompilationUnit cu, String typeName) {
AbstractTypeDeclaration result = null;
List<?> types = cu.types();
if ((typeName != null) && (types != null)) {
Iterator<?> typesIterator = types.iterator();
while ((result == null) && (typesIterator.hasNext())) {
AbstractTypeDeclaration td = (AbstractTypeDeclaration) typesIterator.next();
result = (td.getName().getFullyQualifiedName().equals(typeName)) ? td : null;
}
}
return result;
}
/**
* Return a AbstractTypeDeclaration instance defined in an other Abstract
* Type Declaration with innerTypeName as name
*
* @param td
* A AbstractTypeDeclaration object
* @param innerTypeName
* The name of the inner type searched
* @return a AbstractTypeDeclaration object associated with innerTypeName,
* null if not found or innerTypeName null
*/
public static AbstractTypeDeclaration getInnerTypeDeclaration(AbstractTypeDeclaration td,
String innerTypeName) {
AbstractTypeDeclaration result = null;
List<AbstractTypeDeclaration> types = JavaCodeHelper.getTypedChildren(td,
AbstractTypeDeclaration.class);
int inc = -1;
if ((innerTypeName != null) && (types != null)) {
while ((result == null) && (++inc < types.size())) {
AbstractTypeDeclaration t = types.get(inc);
result = (t.getName().getFullyQualifiedName().equals(innerTypeName)) ? t : null;
}
}
return result;
}
/**
* Return a BodyDeclaration instance according to the wanted BodyDeclaration
* type.
*
* @param atd
* An AbstractTypeDeclaration object
* @param bd
* A "same Body Declaration" used to find in {@code atd}
* @return A BodyDeclaration instance according to the wanted
* BodyDeclaration type.
*/
@SuppressWarnings("unchecked")
public static BodyDeclaration getBodyDeclaration(AbstractTypeDeclaration atd, BodyDeclaration bd) {
String bdName = JavaCodeHelper.getName(bd);
Class<? extends BodyDeclaration> bdc = bd.getClass();
if (FieldDeclaration.class.isAssignableFrom(bdc)) {
return getField(atd, bdName);
}
else if (MethodDeclaration.class.isAssignableFrom(bdc)) {
return getMethod(atd, bdName, ((MethodDeclaration) bd).parameters());
}
else if (AbstractTypeDeclaration.class.isAssignableFrom(bdc)) {
return getInnerType(atd, bdName);
}
else if (EnumConstantDeclaration.class.isAssignableFrom(bdc)) {
return getEnumConstant((EnumDeclaration) atd, bdName);
}
return null;
}
/**
*
* @return
*/
public static BodyDeclaration getBodyDeclarationFromUniqueId(AbstractTypeDeclaration parentNodeToSearchATD,
BodyDeclaration bodyDeclarationToFind) {
Class<? extends BodyDeclaration> bodyDeclarationToFindClass = bodyDeclarationToFind.getClass();
List<? extends BodyDeclaration> childrenToSearch = Collections.<BodyDeclaration>emptyList();
if (FieldDeclaration.class.isAssignableFrom(bodyDeclarationToFindClass)) {
childrenToSearch = getTypedChildren(parentNodeToSearchATD, FieldDeclaration.class);
}
else if (MethodDeclaration.class.isAssignableFrom(bodyDeclarationToFindClass)) {
childrenToSearch = getTypedChildren(parentNodeToSearchATD, MethodDeclaration.class);
}
else if (AbstractTypeDeclaration.class.isAssignableFrom(bodyDeclarationToFindClass)) {
childrenToSearch = getTypedChildren(parentNodeToSearchATD, AbstractTypeDeclaration.class);
}
else if (EnumConstantDeclaration.class.isAssignableFrom(bodyDeclarationToFindClass)) {
childrenToSearch = getTypedChildren(parentNodeToSearchATD, EnumConstantDeclaration.class);
}
if(childrenToSearch != null && childrenToSearch.size()>0) {
String uniqueIdToFind = ASTHelper.getUniqueIdFromGeneratedAnnotation(bodyDeclarationToFind);
for(BodyDeclaration method : childrenToSearch) {
if(uniqueIdToFind != null && uniqueIdToFind.equals(ASTHelper.getUniqueIdFromGeneratedAnnotation(method))) {
return method;
}
}
}
return null;
}
/**
* Return an AST FieldDeclaration object from a TypeDeclaration and a field
* name.
*
* @param atd
* An AbstractTypeDeclaration object
* @param field
* A field name
* @return A FieldDeclaration object instance
*/
public static FieldDeclaration getField(AbstractTypeDeclaration atd, String fieldName) {
List<FieldDeclaration> fds = getTypedChildren(atd, FieldDeclaration.class);
if (fds == null) {
return null;
}
boolean fieldFound = false;
int inc = -1;
while (!fieldFound && ++inc < fds.size()) {
fieldFound = fieldName.equals(
((VariableDeclarationFragment) fds.get(inc).fragments().get(0))
.getName().getFullyQualifiedName()
);
}
return (fieldFound ? fds.get(inc) : null);
}
/**
* Return all fields from a TypeDeclaration
*
* @param td
* A TypeDeclaration object
* @return a FieldDeclaration[]
*/
public static FieldDeclaration[] getFields(AbstractTypeDeclaration atd) {
List<?> typedChildren = getTypedChildren(atd, FieldDeclaration.class);
FieldDeclaration[] declarations = new FieldDeclaration[typedChildren.size()];
for (int i = 0;i<typedChildren.size();i++)
declarations[i] = (FieldDeclaration) typedChildren.get(i);
return declarations;
}
/**
* Return all fields names from a TypeDeclaration
*
* @param td
* A TypeDeclaration object
* @return a String[]
*/
public static String[] getFieldsNames(AbstractTypeDeclaration td) {
FieldDeclaration[] fds = getFields(td);
String[] fieldsNames = new String[fds.length];
for (int inc = 0; inc < fds.length; inc++) {
fieldsNames[inc] = getFieldName(fds[inc]);
}
return fieldsNames;
}
/**
* Return a name of a Body Declaration instance.
*
* @param bd
* A BodyDeclaration object
* @return a String containing the body declaration name
*/
public static String getName(BodyDeclaration bd) {
if (FieldDeclaration.class.isAssignableFrom(bd.getClass())) {
return getFieldName((FieldDeclaration) bd);
} else if (MethodDeclaration.class.isAssignableFrom(bd.getClass())) {
return getMethodName((MethodDeclaration) bd);
} else if (AbstractTypeDeclaration.class.isAssignableFrom(bd.getClass())) {
return getTypeName((AbstractTypeDeclaration) bd);
} else if (EnumConstantDeclaration.class.isAssignableFrom(bd.getClass())) {
return getEnumConstantName((EnumConstantDeclaration) bd);
}
return null;
}
/**
* Return a name of an ASTNode.
*
* @param astn
* A ASTNode object
* @return a String containing the node name
*/
public static String getName(ASTNode astn) {
if (astn.getClass().isAssignableFrom(CompilationUnit.class)) {
return getName(getMainType((CompilationUnit) astn));
} else {
return getName((BodyDeclaration) astn);
}
}
/**
* Return a field name from a FieldDeclaration
*
* @param fd
* A FieldDeclaration object
* @return a String containing the field name
*/
public static String getFieldName(FieldDeclaration fd) {
return (fd != null) ? ((VariableDeclarationFragment) fd.fragments().get(0)).getName()
.getFullyQualifiedName() : null;
}
/**
* Return an AST MethodDeclaration object from a TypeDeclaration, a method
* name and a SingleVariableDeclaration list (method parameters).
*
* @param atd
* A AbstractTypeDeclaration object
* @param methodName
* A method name
* @param svds
* A SingleVariableDeclaration list (method parameters)
* @return A MethodDeclaration object instance
*/
public static MethodDeclaration getMethod(AbstractTypeDeclaration atd, String methodName,
List<SingleVariableDeclaration> svds) {
String[] parameters = null;
if (svds != null) {
parameters = new String[svds.size()];
for (int inc = 0; inc < svds.size(); inc++) {
SingleVariableDeclaration svd = svds.get(inc);
parameters[inc] = svd.getType().toString();
}
} else {
parameters = new String[0];
}
return getMethod(atd, methodName, parameters);
}
/**
* Return an AST MethodDeclaration object from a TypeDeclaration and a
* method name. This method is useful when one and only one method with the
* same name appears in the type declaration.
*
* @param atd
* A AbstractTypeDeclaration object
* @param methodName
* A method name
* @return A MethodDeclaration object instance
*/
public static MethodDeclaration getMethod(AbstractTypeDeclaration atd, String methodName) {
return getMethod(atd, methodName, (String[]) null);
}
/**
* Return an AST MethodDeclaration object from a TypeDeclaration, a method
* name and an arguments types names list.
*
* @param atd
* A AbstractTypeDeclaration object
* @param methodName
* A method name
* @param argumentsTypesNames
* Arguments types names as list
* @return A MethodDeclaration object instance
*/
@SuppressWarnings("unchecked")
public static MethodDeclaration getMethod(AbstractTypeDeclaration atd, String methodName,
String... argumentsTypesNames) {
List<MethodDeclaration> mds = getTypedChildren(atd, MethodDeclaration.class);
boolean methodFound = false;
int inc = -1;
if (mds == null) {
return null;
}
while (!methodFound && ++inc < mds.size()) {
methodFound = methodName.equals(mds.get(inc).getName().getFullyQualifiedName());
if (methodFound && argumentsTypesNames != null) {
MethodDeclaration md = mds.get(inc);
List<SingleVariableDeclaration> svds = md.parameters();
if (svds != null && svds.size() == argumentsTypesNames.length) {
// Check each parameter
for (int inc2 = 0; inc2 < svds.size() && methodFound; inc2++) {
methodFound = methodFound && areTypesEquals(svds.get(inc2).getType(), argumentsTypesNames[inc2]);
}
} else {
methodFound = false;
}
}
}
return (methodFound ? mds.get(inc) : null);
}
/**
* Return a List of AST MethodDeclaration object from a TypeDeclaration and
* a method name.
*
* @param atd
* A AbstractTypeDeclaration object
* @param methodName
* A method name
* @return A List<MethodDeclaration> object instance
*/
public static List<MethodDeclaration> getMethods(AbstractTypeDeclaration atd, String methodName) {
return getMethods(atd, methodName, (String[]) null);
}
/**
* Return an List of AST MethodDeclaration object from a TypeDeclaration, a
* method name and an arguments types names list.
*
* @param atd
* A AbstractTypeDeclaration object
* @param methodName
* A method name
* @param argumentsTypesNames
* Arguments types names as list
* @return A List<MethodDeclaration> object instance
*/
@SuppressWarnings("unchecked")
public static List<MethodDeclaration> getMethods(AbstractTypeDeclaration atd,
String methodName, String... argumentsTypesNames) {
List<MethodDeclaration> mds = getTypedChildren(atd,
MethodDeclaration.class);
int inc = -1;
List<MethodDeclaration> lstMethods = new ArrayList<MethodDeclaration>();
while (++inc < mds.size()) {
boolean methodFound = false;
methodFound = methodName.equals(mds.get(inc).getName().getFullyQualifiedName());
MethodDeclaration md = mds.get(inc);
if (methodFound && argumentsTypesNames != null) {
List<SingleVariableDeclaration> svds = md.parameters();
if (svds != null && svds.size() == argumentsTypesNames.length) {
// Check each parameter
for (int inc2 = 0; inc2 < svds.size() && methodFound; inc2++) {
methodFound = methodFound
&& areTypesEquals(svds.get(inc2).getType(),
argumentsTypesNames[inc2]);
}
}
}
if (methodFound)
lstMethods.add(md);
}
return lstMethods;
}
/**
* Return an AST TypeDeclaration object from a TypeDeclaration and a inner
* type name.
*
* @param atd
* A AbstractTypeDeclaration object
* @param innerTypeName
* An inner type name
* @return A AbstractTypeDeclaration object instance
*/
public static AbstractTypeDeclaration getInnerType(AbstractTypeDeclaration atd,
String innerTypeName) {
List<AbstractTypeDeclaration> atds = getTypedChildren(atd, AbstractTypeDeclaration.class);
boolean innerTypeFound = false;
int inc = -1;
while (!innerTypeFound && ++inc < atds.size()) {
innerTypeFound = innerTypeName.equals(atds.get(inc).getName().getFullyQualifiedName());
}
return (innerTypeFound ? atds.get(inc) : null);
}
/**
* Return an AST AbstractTypeDeclaration object from a CompilationUnit and a
* type name.
*
* @param cu
* A CompilationUnit object
* @param typeName
* An type name
* @return A AbstractTypeDeclaration object instance
*/
public static AbstractTypeDeclaration getType(CompilationUnit cu, String typeName) {
if (cu == null || typeName == null) {
return null;
}
List<?> tds = cu.types();
boolean typeFound = false;
int inc = -1;
while (!typeFound && ++inc < tds.size()) {
typeFound = typeName.equals(getTypeName((AbstractTypeDeclaration) tds.get(inc)));
}
return (typeFound ? (AbstractTypeDeclaration) tds.get(inc) : null);
}
/**
* Return the name of the type describes in a TypeDeclaration instance.
*
* @param atd
* A AbstractTypeDeclaration instance
* @param The
* name of the type describes by TypeDeclaration
*/
public static String getTypeName(AbstractTypeDeclaration atd) {
return atd.getName().getFullyQualifiedName();
}
/**
* Return an AST AbstractTypeDeclaration object from a CompilationUnit.
*
* @param cu
* A CompilationUnit object
* @return A AbstractTypeDeclaration object instance
*/
@SuppressWarnings("unchecked")
public static AbstractTypeDeclaration getMainType(CompilationUnit cu) {
if (cu == null) {
return null;
}
List<AbstractTypeDeclaration> tds = cu.types();
boolean typeFound = false;
int inc = -1;
while (!typeFound && ++inc < tds.size()) {
typeFound = Modifier.isPublic(tds.get(inc).getModifiers()) || isPackage(tds.get(inc));
}
return (typeFound ? (AbstractTypeDeclaration) tds.get(inc) : null);
}
/**
* Return true if a AbstractTypeDeclaration have a package visibility
*/
private static boolean isPackage(AbstractTypeDeclaration atd) {
int modifiers = atd.getModifiers();
return !(Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers) || Modifier
.isPrivate(modifiers));
}
/**
* Return all methods from a TypeDeclaration
*
* @param td
* A TypeDeclaration object
* @return a MethodDeclaration[]
*/
public static MethodDeclaration[] getMethods(AbstractTypeDeclaration atd) {
List<?> typedChildren = getTypedChildren(atd, MethodDeclaration.class);
MethodDeclaration[] declarations = new MethodDeclaration[typedChildren.size()];
for (int i = 0;i<typedChildren.size();i++)
declarations[i] = (MethodDeclaration) typedChildren.get(i);
return declarations;
}
/**
* Return all methods names from a TypeDeclaration
*
* @param td
* A TypeDeclaration object
* @return a String[]
*/
public static String[] getMethodsNames(AbstractTypeDeclaration td) {
MethodDeclaration[] mds = getMethods(td);
String[] methodsNames = new String[mds.length];
for (int inc = 0; inc < mds.length; inc++) {
methodsNames[inc] = getMethodName(mds[inc]);
}
return methodsNames;
}
/**
* Return a method name from a MethodDeclaration
*
* @param md
* A MethodDeclaration object
* @return a String containing the method name
*/
public static String getMethodName(MethodDeclaration md) {
return (md != null) ? md.getName().getFullyQualifiedName() : null;
}
/**
* Return the initialization expression of a field.
*/
@SuppressWarnings("unchecked")
public static Expression getFieldInitializer(FieldDeclaration fd) {
List<VariableDeclarationFragment> vdfs = fd.fragments();
return vdfs.get(0).getInitializer();
}
/**
* Return an ImportDeclaration of a CompilationUnit
*/
public static ImportDeclaration getImport(CompilationUnit cu, String importName) {
List<?> imports = cu.imports();
List<String> importsNames = new ArrayList<String>();
for (Object o : imports) {
importsNames.add(((ImportDeclaration) o).getName().getFullyQualifiedName());
}
return (importsNames.indexOf(importName) == -1) ? null : (ImportDeclaration) imports
.get(importsNames.indexOf(importName));
}
/**
* Return an Annotation object of a BodyDeclaration object
*/
public static Annotation getAnnotation(BodyDeclaration bd, String annotationFullyQualifiedName) {
List<?> modifiers = bd.modifiers();
Annotation result = null;
// Test if this BodyDeclaration contains modifiers
if (modifiers != null) {
Iterator<?> modifiersIterator = bd.modifiers().iterator();
// For each modifier, search for @annotationType marker
// annotation
while ((result == null) && modifiersIterator.hasNext()) {
IExtendedModifier modifier = (IExtendedModifier) modifiersIterator.next();
if (modifier.isAnnotation()) {
Annotation a = (Annotation) modifier;
// Test if the name of the annotation is a simple name or a
// fully qualified name
String annotationName = (a.getTypeName().isSimpleName()) ? annotationFullyQualifiedName
.substring(annotationFullyQualifiedName.lastIndexOf('.') + 1)
: annotationFullyQualifiedName;
if (a.getTypeName().getFullyQualifiedName().equals(annotationName)) {
result = a;
}
}
}
}
return result;
}
/**
* Return an Annotation object of a SingleVariableDeclaration object
*/
public static Annotation getAnnotation(SingleVariableDeclaration svd,
String annotationFullyQualifiedName) {
List<?> modifiers = svd.modifiers();
Annotation result = null;
// Test if this BodyDeclaration contains modifiers
if (modifiers != null) {
Iterator<?> modifiersIterator = svd.modifiers().iterator();
// For each modifier, search for @annotationType marker
// annotation
while ((result == null) && modifiersIterator.hasNext()) {
IExtendedModifier modifier = (IExtendedModifier) modifiersIterator.next();
if (modifier.isAnnotation()) {
Annotation a = (Annotation) modifier;
// Test if the name of the annotation is a simple name or a
// fully qualified name
String annotationName = (a.getTypeName().isSimpleName()) ? annotationFullyQualifiedName
.substring(annotationFullyQualifiedName.lastIndexOf('.') + 1)
: annotationFullyQualifiedName;
if (a.getTypeName().getFullyQualifiedName().equals(annotationName)) {
result = a;
}
}
}
}
return result;
}
/**
* Return true if the annotation content matches the input map (@Foo(f1 = v1
* , f2 = v2)
*
* @param annotation
* input annotation to check
* @param content
* a Map object containing as key the expected member name and as
* value the expected member value
* @return true if the annotation is a normal annotation and if the content
* matches the content parameter, false otherwise
*/
@SuppressWarnings("unchecked")
public static boolean checkAnnotationContent(Annotation annotation, Map<String, Object> content) {
boolean correct = false;
// Test if this annotation is a Normal Member Annotation
if (annotation != null && annotation.isNormalAnnotation()) {
List<MemberValuePair> values = ((NormalAnnotation) annotation).values();
correct = true;
for (int inc = 0; inc < values.size() && correct; inc++) {
MemberValuePair mvp = values.get(inc);
String memberName = mvp.getName().getFullyQualifiedName();
Object contentValue = content.get(memberName);
correct = contentValue != null;
Expression memberValue = mvp.getValue();
correct = checkSingleAnnotationValue(memberValue, contentValue);
}
}
return correct;
}
/**
* Compare two annotations contents
*
* @param memberValue
* @param contentValue
* @return true if content matches, false else
*/
public static boolean checkSingleAnnotationValue(Expression memberValue, Object contentValue) {
boolean correct = false;
if (memberValue != null) {
if (contentValue instanceof String) {
correct = ((memberValue instanceof StringLiteral) && (contentValue
.equals(((StringLiteral) memberValue).getLiteralValue())));
} else {
if (contentValue instanceof InternalQualifiedName) {
if (!(memberValue instanceof QualifiedName)) {
correct = false;
} else {
InternalQualifiedName internalQualifiedName = (InternalQualifiedName) contentValue;
correct = ((QualifiedName) memberValue).getQualifier()
.getFullyQualifiedName().equals(
internalQualifiedName.getQualifier())
&& ((QualifiedName) memberValue).getName().getFullyQualifiedName()
.equals(internalQualifiedName.getName());
}
}
}
}
return correct;
}
/**
* Return true if {@code firstType} as Type object is equals to {@code
* secondType} as Type
*
* @param type1
* first type as Type object
* @param type2
* second type as Type object
* @return true if {@code firstType} is equals to {@code secondType}
*/
public static boolean areTypesEquals(Type type1, Type type2) {
return areTypesEquals(type1, type2.toString());
}
/**
* Return true if {@code firstType} as Type object is equals to {@code
* secondType} as fully qualified String
*
* @param type1
* first type as Type object
* @param type2
* second type as fully qualified String
* @return true if {@code firstType} is equals to {@code secondType}
*/
public static boolean areTypesEquals(Type type1, String type2) {
// Check if type1 and type2 are not null before method
// execution
if (type1 == null || type2 == null) {
return false;
}
type2 = type2.trim();
/* Remove the generic information from type 2 is this one exists */
type2 = (type2.indexOf('<') != -1) ? type2.substring(0, type2.indexOf('<')) : type2;
if (type1 instanceof SimpleType) {
// Case when type1 is a simple type (MyObject)
String type1Name = ((SimpleType) type1).getName().getFullyQualifiedName();
String simpleType1Name = (type1Name.lastIndexOf('.') != -1) ? type1Name
.substring(type1Name.lastIndexOf('.') + 1) : type1Name;
String simpleType2Name = (type2.lastIndexOf('.') != -1) ? type2.substring(type2
.lastIndexOf('.') + 1) : type2;
return simpleType1Name.equals(simpleType2Name);
} else if (type1 instanceof QualifiedType) {
// Case when type1 is a qualified type (net.atos.xa.MyObject)
return (((QualifiedType) type1).getName().getFullyQualifiedName().equals(type2));
} else if (type1 instanceof PrimitiveType) {
// Case when type1 is a primitive type (int, boolean, void, ...)
return ((PrimitiveType) type1).getPrimitiveTypeCode().toString().equals(type2);
} else if (type1 instanceof ArrayType) {
ArrayType arrayType = (ArrayType) type1;
// Case when type1 is an array (int[], MyObject[],...)
return type2.endsWith("[]")
&& areTypesEquals(ASTArrayTypeHelper.getComponentType(arrayType), type2.substring(0,
type2.lastIndexOf('[')));
} else if (type1 instanceof ParameterizedType) {
// Case when type1 is a parametrized type (MyObject<Integer>,
// Map<List,String>,...)
// Check the main type
return areTypesEquals(((ParameterizedType) type1).getType(), type2);
} else if (type1 instanceof WildcardType) {
// Case when type1 is a wildcard type (? , ? extends MyObject,
// ...)
if (((WildcardType) type1).getBound() == null) {
return type2.equals("?");
} else {
StringTokenizer st = new StringTokenizer(type2, " ");
if (!st.nextToken().trim().equals("?")) {
return false;
}
if (((WildcardType) type1).isUpperBound()) {
return st.nextToken().trim().equalsIgnoreCase("extends")
&& areTypesEquals(((WildcardType) type1).getBound(), st.nextToken());
} else {
return st.nextToken().trim().equalsIgnoreCase("super")
&& areTypesEquals(((WildcardType) type1).getBound(), st.nextToken());
}
}
}
return false;
}
/**
* Return a simple name from a fully qualified name. If this name is already
* a simple name (without dot), this method returns the original name. If
* this name is a fully qualified name, this method return the class name
* without dot.
*
* @param fullyQualifiedName
* The fully qualified name to transform
* @return a simple name from a fully qualified name. If this name is
* already a simple name (without dot), this method returns the
* original name. If this name is a fully qualified name, this
* method return the class name without dot.
*/
public static String getSimpleName(String fullyQualifiedName) {
if (fullyQualifiedName == null) {
return null;
}
// Check if fullyQualifiedName contains a dot
if (fullyQualifiedName.lastIndexOf('.') == -1) {
return fullyQualifiedName;
} else {
return fullyQualifiedName.substring(fullyQualifiedName.lastIndexOf('.') + 1);
}
}
/**
* Return a list of {@code typeWanted} typed elements as children of {@code
* atd} AbstractTypeDeclaration.
*
* @param atd
* The parent instance
* @param typeWanted
* Type of children wanted
* @return a list of {@code typeWanted} typed elements as children of
* {@code atd} AbstractTypeDeclaration
*/
@SuppressWarnings("unchecked")
public static <T extends BodyDeclaration> List<T> getTypedChildren(AbstractTypeDeclaration atd, Class<T> typeWanted) {
if (atd == null) {
return null;
}
List<T> result = new ArrayList<T>(5);
if (typeWanted.equals(EnumConstantDeclaration.class)) {
result = ((EnumDeclaration) atd).enumConstants();
} else {
for (BodyDeclaration bd : (List<BodyDeclaration>) atd.bodyDeclarations()) {
if (typeWanted.isAssignableFrom(bd.getClass())) {
result.add((T) bd);
}
}
}
return result;
}
/**
* Return the name of the enum constant describes in a
* EnumConstantDeclaration instance.
*
* @param ecd
* A EnumConstantDeclaration instance
* @param The
* name of the enum constant describes by EnumConstantDeclaration
*/
public static String getEnumConstantName(EnumConstantDeclaration ecd) {
return ecd.getName().getFullyQualifiedName();
}
/**
* Return an AST EnumConstantDeclaration object from a EnumDeclaration and a
* enumeration constant name.
*
* @param ed
* An EnumDeclaration object
* @param enumerationConstantName
* An enumeration constant name
* @return A EnumConstantDeclaration object instance
*/
@SuppressWarnings("unchecked")
public static EnumConstantDeclaration getEnumConstant(EnumDeclaration ed,
String enumerationConstantName) {
List<EnumConstantDeclaration> atds = ed.enumConstants();
boolean enumerationConstantNameFound = false;
int inc = -1;
while (!enumerationConstantNameFound && ++inc < atds.size()) {
enumerationConstantNameFound = enumerationConstantName.equals(atds.get(inc).getName()
.getFullyQualifiedName());
}
return (enumerationConstantNameFound ? atds.get(inc) : null);
}
/**
* Return a Body Declaration Property according to the {@code type} type.
*
* @param type
* A Body Declaration type
* @return a Body Declaration Property according to the {@code type} type.
*/
public static ChildListPropertyDescriptor getBodyDeclarationProperty(Class<?> type) {
if (type.equals(TypeDeclaration.class)) {
return TypeDeclaration.BODY_DECLARATIONS_PROPERTY;
} else if (type.equals(EnumDeclaration.class)) {
return EnumDeclaration.BODY_DECLARATIONS_PROPERTY;
} else if (type.equals(AnnotationTypeDeclaration.class)) {
return AnnotationTypeDeclaration.BODY_DECLARATIONS_PROPERTY;
}
return null;
}
/**
* Return the simple name as String from a Name instance
*/
public static String getSimpleName(Name n) {
String simpleName = null;
/*
* If it's a fully qualified name, remove package name.
*/
if (n.isQualifiedName()) {
simpleName = n.getFullyQualifiedName().substring(
n.getFullyQualifiedName().lastIndexOf('.') + 1);
} else {
simpleName = n.getFullyQualifiedName();
}
return simpleName;
}
/**
* Return a name instance from a Type instance
*/
public static Name getName(Type t) {
if (t.isArrayType()) {
ArrayType arrayType = (ArrayType) t;
return getName(ASTArrayTypeHelper.getComponentType(arrayType));
} else if (t.isParameterizedType()) {
return getName(((ParameterizedType) t).getType());
} else if (t.isPrimitiveType()) {
return null;
} else if (t.isQualifiedType()) {
return ((QualifiedType) t).getName();
} else if (t.isSimpleType()) {
return ((SimpleType) t).getName();
}
return null;
}
/**
* Return a compilation unit object from a java source as String.
*
* @param source
* Java source as String
* @return A Compilation Unit object
*/
public static CompilationUnit getACompilationUnit(String source) {
// Create a Document object for the source
Document sourceAsDocument = new Document(source);
// Create an AST parser for the source
ASTParser existingContentParser = ASTParserFactory.INSTANCE.newParser();
existingContentParser.setSource(sourceAsDocument.get().toCharArray());
existingContentParser.setCompilerOptions(JavaCodeHelper.compilerOptions);
return (CompilationUnit) existingContentParser.createAST(null);
}
/**
* Return the description of a BodyDeclaration
*/
public static String getDescription(ASTNode astn) {
if (astn == null) {
return "empty";
}
if (astn instanceof FieldDeclaration) {
// It's a field, return "field"
return "field";
} else if (astn instanceof MethodDeclaration) {
// It's a method, return "method"
return "method";
} else if (astn instanceof TypeDeclaration) {
// It's a type, return "type"
return "type";
} else if (astn instanceof EnumDeclaration) {
// It's an enumeration, return "enumeration"
return "enumeration";
} else if (astn instanceof EnumConstantDeclaration) {
// It's an enumeration, return "enumeration constant"
return "enumeration constant";
} else if (astn instanceof CompilationUnit) {
// It's an enumeration, return "compilation unit"
return "compilation unit";
}
return "empty";
}
}