/* * Copyright 2012 Red Hat, Inc. and/or its affiliates. * * Licensed under the Eclipse Public License version 1.0, available at * http://www.eclipse.org/legal/epl-v10.html */ package org.jboss.forge.roaster.model.impl; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ArrayType; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.ParameterizedType; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.jboss.forge.roaster.Roaster; import org.jboss.forge.roaster.model.JavaType; import org.jboss.forge.roaster.model.Type; import org.jboss.forge.roaster.model.source.FieldSource; import org.jboss.forge.roaster.model.source.Importer; import org.jboss.forge.roaster.model.source.JavaClassSource; import org.jboss.forge.roaster.model.source.MethodSource; import org.jboss.forge.roaster.model.util.Strings; import org.jboss.forge.roaster.model.util.Types; /** * @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a> */ public class TypeImpl<O extends JavaType<O>> implements Type<O> { private O origin; private CompilationUnit cu; private final Type<O> parent; private final org.eclipse.jdt.core.dom.Type type; private void init(final O origin) { this.origin = origin; cu = (CompilationUnit) origin.getInternal(); } public TypeImpl(final O origin, final Object internal) { init(origin); type = (org.eclipse.jdt.core.dom.Type) internal; parent = null; } public TypeImpl(final O origin, final Type<O> parent, final String type) { init(origin); this.parent = parent; String stub = "public class Stub { private " + type + " getType(){return null;} }"; JavaClassSource temp = (JavaClassSource) Roaster.parse(stub); List<MethodSource<JavaClassSource>> methods = temp.getMethods(); MethodDeclaration newMethod = (MethodDeclaration) methods.get(0).getInternal(); org.eclipse.jdt.core.dom.Type subtree = (org.eclipse.jdt.core.dom.Type) ASTNode.copySubtree(cu.getAST(), newMethod.getReturnType2()); this.type = subtree; } public TypeImpl(final O origin, final Type<O> parent, final Object internal) { init(origin); this.parent = parent; type = (org.eclipse.jdt.core.dom.Type) internal; } @Override public O getOrigin() { return origin; } @Override @SuppressWarnings("unchecked") public List<Type<O>> getTypeArguments() { org.eclipse.jdt.core.dom.Type typeLocal = this.type; if (typeLocal.isArrayType()) { typeLocal = ((ArrayType) typeLocal).getElementType(); } if (typeLocal instanceof ParameterizedType) { List<Type<O>> result = new ArrayList<Type<O>>(); List<org.eclipse.jdt.core.dom.Type> arguments = ((ParameterizedType) typeLocal).typeArguments(); for (org.eclipse.jdt.core.dom.Type t : arguments) { result.add(new TypeImpl<O>(origin, this, t)); } return Collections.unmodifiableList(result); } return Collections.emptyList(); } @Override public boolean isArray() { return getArrayDimensions() > 0; } @Override public boolean isParameterized() { if (type.isArrayType()) { return ((ArrayType) type).getElementType().isParameterizedType(); } return type.isParameterizedType(); } @Override public boolean isPrimitive() { if (type.isArrayType()) { return ((ArrayType) type).getElementType().isPrimitiveType(); } return type.isPrimitiveType(); } @Override public boolean isQualified() { return type.toString().contains("."); } @Override public boolean isWildcard() { if (type.isArrayType()) { return ((ArrayType) type).getElementType().isWildcardType(); } return type.isWildcardType(); } @Override public String getName() { String result = type.toString(); if (isParameterized()) { // strip type parameters after stripping array dimensions if (isArray()) { result = Types.stripArray(result); } result = Types.stripGenerics(result); // restore array dimensions for (int i = 0, dim = getArrayDimensions(); i < dim; i++) { result += "[]"; } return result; } for (int i = 0, dim = getExtraDimensions(); i < dim; i++) { result += "[]"; } return result; } @Override public String getQualifiedName() { String result = type.toString(); if (origin instanceof Importer<?>) { return ((Importer<?>) origin).resolveType(result); } return result; } @Override public String getSimpleName() { return Types.toSimpleName(getQualifiedName()); } @Override public String getQualifiedNameWithGenerics() { String result = type.toString(); if (origin instanceof Importer<?>) { return Types.rebuildGenericNameWithArrays(((Importer<?>) origin).resolveType(result), this); } return result; } @Override public Type<O> getParentType() { return parent; } @Override public int getArrayDimensions() { int result = 0; if (type.isArrayType()) { result += ((ArrayType) type).getDimensions(); } result += getExtraDimensions(); return result; } @Override public boolean isType(final Class<?> type) { final String qualifiedName = getQualifiedName(); if (Strings.areEqual(type.getName(), qualifiedName)) { return true; } final String simpleName = type.getSimpleName(); if (isPrimitive() && type.isPrimitive() && simpleName.equals(getName())) { return true; } if (getOrigin() instanceof Importer<?> && Strings.areEqual(simpleName, qualifiedName)) { return !((Importer<?>) getOrigin()).requiresImport(type); } return false; } @Override public boolean isType(final String name) { if (Strings.areEqual(name, getQualifiedName())) { return true; } if (Types.areEquivalent(name, getQualifiedName())) { if (!Types.isQualified(name)) { return true; } return getOrigin() instanceof Importer<?> && !((Importer<?>) getOrigin()).requiresImport(name); } return false; } @Override public String toString() { return type.toString(); } private int getExtraDimensions() { ASTNode parentLocal = type.getParent(); if (parentLocal instanceof FieldDeclaration) { for (Object f : ((FieldDeclaration) parentLocal).fragments()) { if (f instanceof VariableDeclarationFragment) { return ((VariableDeclarationFragment) f).getExtraDimensions(); } } } if (parentLocal instanceof SingleVariableDeclaration) { return ((SingleVariableDeclaration) parentLocal).getExtraDimensions(); } return 0; } public static org.eclipse.jdt.core.dom.Type fromString(String resolvedType, AST ast) { String stub = "public class Stub { " + resolvedType + " field; }"; JavaClassSource temp = (JavaClassSource) Roaster.parse(stub); List<FieldSource<JavaClassSource>> fields = temp.getFields(); org.eclipse.jdt.core.dom.Type fieldType = ((FieldDeclaration) ((VariableDeclarationFragment) fields.get(0) .getInternal()).getParent()).getType(); return (org.eclipse.jdt.core.dom.Type) ASTNode.copySubtree(ast, fieldType); } }