diff options
Diffstat (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java')
-rw-r--r-- | javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java new file mode 100644 index 000000000..5be7bece9 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionClassAdapter.java @@ -0,0 +1,190 @@ +package com.github.javaparser.symbolsolver.reflectionmodel; + +import com.github.javaparser.resolution.UnsolvedSymbolException; +import com.github.javaparser.resolution.declarations.*; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder; +import com.github.javaparser.symbolsolver.logic.FunctionalInterfaceLogic; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.NullType; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.TypeVariable; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author Federico Tomassetti + */ +class ReflectionClassAdapter { + + private Class<?> clazz; + private TypeSolver typeSolver; + private ResolvedReferenceTypeDeclaration typeDeclaration; + + public ReflectionClassAdapter(Class<?> clazz, TypeSolver typeSolver, ResolvedReferenceTypeDeclaration typeDeclaration) { + this.clazz = clazz; + this.typeSolver = typeSolver; + this.typeDeclaration = typeDeclaration; + } + + public ReferenceTypeImpl getSuperClass() { + if (clazz.getGenericSuperclass() == null) { + return null; + } + java.lang.reflect.Type superType = clazz.getGenericSuperclass(); + if (superType instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) superType; + List<ResolvedType> typeParameters = Arrays.stream(parameterizedType.getActualTypeArguments()) + .map((t) -> ReflectionFactory.typeUsageFor(t, typeSolver)) + .collect(Collectors.toList()); + return new ReferenceTypeImpl(new ReflectionClassDeclaration(clazz.getSuperclass(), typeSolver), typeParameters, typeSolver); + } + return new ReferenceTypeImpl(new ReflectionClassDeclaration(clazz.getSuperclass(), typeSolver), typeSolver); + } + + public List<ResolvedReferenceType> getInterfaces() { + List<ResolvedReferenceType> interfaces = new ArrayList<>(); + for (java.lang.reflect.Type superInterface : clazz.getGenericInterfaces()) { + if (superInterface instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) superInterface; + List<ResolvedType> typeParameters = Arrays.stream(parameterizedType.getActualTypeArguments()) + .map((t) -> ReflectionFactory.typeUsageFor(t, typeSolver)) + .collect(Collectors.toList()); + interfaces.add(new ReferenceTypeImpl(new ReflectionInterfaceDeclaration((Class<?>) ((ParameterizedType) superInterface).getRawType(), typeSolver), typeParameters, typeSolver)); + } else { + interfaces.add(new ReferenceTypeImpl(new ReflectionInterfaceDeclaration((Class<?>) superInterface, typeSolver), typeSolver)); + } + } + return interfaces; + } + + public List<ResolvedReferenceType> getAncestors() { + List<ResolvedReferenceType> ancestors = new LinkedList<>(); + if (getSuperClass() != null) { + ReferenceTypeImpl superClass = getSuperClass(); + ancestors.add(superClass); + } else { + ReferenceTypeImpl object = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver); + ancestors.add(object); + } + ancestors.addAll(getInterfaces()); + for (int i = 0; i < ancestors.size(); i++) { + ResolvedReferenceType ancestor = ancestors.get(i); + if (ancestor.hasName() && ancestor.getQualifiedName().equals(Object.class.getCanonicalName())) { + ancestors.remove(i); + i--; + } + } + return ancestors; + } + + public ResolvedFieldDeclaration getField(String name) { + for (Field field : clazz.getDeclaredFields()) { + if (field.getName().equals(name)) { + return new ReflectionFieldDeclaration(field, typeSolver); + } + } + for (ResolvedReferenceType ancestor : typeDeclaration.getAllAncestors()) { + if (ancestor.getTypeDeclaration().hasField(name)) { + ReflectionFieldDeclaration reflectionFieldDeclaration = (ReflectionFieldDeclaration) ancestor.getTypeDeclaration().getField(name); + return reflectionFieldDeclaration.replaceType(ancestor.getFieldType(name).get()); + } + } + throw new UnsolvedSymbolException(name, "Field in " + this); + } + + public boolean hasField(String name) { + for (Field field : clazz.getDeclaredFields()) { + if (field.getName().equals(name)) { + return true; + } + } + ReferenceTypeImpl superclass = getSuperClass(); + if (superclass == null) { + return false; + } else { + return superclass.getTypeDeclaration().hasField(name); + } + } + + public List<ResolvedFieldDeclaration> getAllFields() { + ArrayList<ResolvedFieldDeclaration> fields = new ArrayList<>(); + for (Field field : clazz.getDeclaredFields()) { + fields.add(new ReflectionFieldDeclaration(field, typeSolver)); + } + for (ResolvedReferenceType ancestor : typeDeclaration.getAllAncestors()) { + fields.addAll(ancestor.getTypeDeclaration().getAllFields()); + } + return fields; + } + + public Set<ResolvedMethodDeclaration> getDeclaredMethods() { + return Arrays.stream(clazz.getDeclaredMethods()) + .filter(m -> !m.isSynthetic() && !m.isBridge()) + .map(m -> new ReflectionMethodDeclaration(m, typeSolver)) + .collect(Collectors.toSet()); + } + + public List<ResolvedTypeParameterDeclaration> getTypeParameters() { + List<ResolvedTypeParameterDeclaration> params = new ArrayList<>(); + for (TypeVariable<?> tv : this.clazz.getTypeParameters()) { + params.add(new ReflectionTypeParameter(tv, true, typeSolver)); + } + return params; + } + + public boolean isAssignableBy(ResolvedType type) { + if (type instanceof NullType) { + return true; + } + if (type instanceof LambdaArgumentTypePlaceholder) { + return isFunctionalInterface(); + } + if (type.isArray()) { + return false; + } + if (type.isPrimitive()) { + return false; + } + if (type.describe().equals(typeDeclaration.getQualifiedName())) { + return true; + } + if (type instanceof ReferenceTypeImpl) { + ReferenceTypeImpl otherTypeDeclaration = (ReferenceTypeImpl) type; + return otherTypeDeclaration.getTypeDeclaration().canBeAssignedTo(typeDeclaration); + } + + return false; + } + + public boolean hasDirectlyAnnotation(String canonicalName) { + for (Annotation a : clazz.getDeclaredAnnotations()) { + if (a.annotationType().getCanonicalName().equals(canonicalName)) { + return true; + } + } + return false; + } + + private final boolean isFunctionalInterface() { + return FunctionalInterfaceLogic.getFunctionalMethod(typeDeclaration).isPresent(); + } + + public List<ResolvedConstructorDeclaration> getConstructors() { + return Arrays.stream(clazz.getConstructors()) + .map(m -> new ReflectionConstructorDeclaration(m, typeSolver)) + .collect(Collectors.toList()); + } + + public Optional<ResolvedReferenceTypeDeclaration> containerType() { + Class<?> declaringClass = clazz.getDeclaringClass(); + return declaringClass == null ? + Optional.empty() : + Optional.of(ReflectionFactory.typeDeclarationFor(declaringClass, typeSolver)); + } +} |