1package com.github.javaparser.symbolsolver.reflectionmodel; 2 3import com.github.javaparser.resolution.UnsolvedSymbolException; 4import com.github.javaparser.resolution.declarations.*; 5import com.github.javaparser.resolution.types.ResolvedReferenceType; 6import com.github.javaparser.resolution.types.ResolvedType; 7import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder; 8import com.github.javaparser.symbolsolver.logic.FunctionalInterfaceLogic; 9import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; 10import com.github.javaparser.symbolsolver.model.typesystem.NullType; 11import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; 12 13import java.lang.annotation.Annotation; 14import java.lang.reflect.Field; 15import java.lang.reflect.ParameterizedType; 16import java.lang.reflect.TypeVariable; 17import java.util.*; 18import java.util.stream.Collectors; 19 20/** 21 * @author Federico Tomassetti 22 */ 23class ReflectionClassAdapter { 24 25 private Class<?> clazz; 26 private TypeSolver typeSolver; 27 private ResolvedReferenceTypeDeclaration typeDeclaration; 28 29 public ReflectionClassAdapter(Class<?> clazz, TypeSolver typeSolver, ResolvedReferenceTypeDeclaration typeDeclaration) { 30 this.clazz = clazz; 31 this.typeSolver = typeSolver; 32 this.typeDeclaration = typeDeclaration; 33 } 34 35 public ReferenceTypeImpl getSuperClass() { 36 if (clazz.getGenericSuperclass() == null) { 37 return null; 38 } 39 java.lang.reflect.Type superType = clazz.getGenericSuperclass(); 40 if (superType instanceof ParameterizedType) { 41 ParameterizedType parameterizedType = (ParameterizedType) superType; 42 List<ResolvedType> typeParameters = Arrays.stream(parameterizedType.getActualTypeArguments()) 43 .map((t) -> ReflectionFactory.typeUsageFor(t, typeSolver)) 44 .collect(Collectors.toList()); 45 return new ReferenceTypeImpl(new ReflectionClassDeclaration(clazz.getSuperclass(), typeSolver), typeParameters, typeSolver); 46 } 47 return new ReferenceTypeImpl(new ReflectionClassDeclaration(clazz.getSuperclass(), typeSolver), typeSolver); 48 } 49 50 public List<ResolvedReferenceType> getInterfaces() { 51 List<ResolvedReferenceType> interfaces = new ArrayList<>(); 52 for (java.lang.reflect.Type superInterface : clazz.getGenericInterfaces()) { 53 if (superInterface instanceof ParameterizedType) { 54 ParameterizedType parameterizedType = (ParameterizedType) superInterface; 55 List<ResolvedType> typeParameters = Arrays.stream(parameterizedType.getActualTypeArguments()) 56 .map((t) -> ReflectionFactory.typeUsageFor(t, typeSolver)) 57 .collect(Collectors.toList()); 58 interfaces.add(new ReferenceTypeImpl(new ReflectionInterfaceDeclaration((Class<?>) ((ParameterizedType) superInterface).getRawType(), typeSolver), typeParameters, typeSolver)); 59 } else { 60 interfaces.add(new ReferenceTypeImpl(new ReflectionInterfaceDeclaration((Class<?>) superInterface, typeSolver), typeSolver)); 61 } 62 } 63 return interfaces; 64 } 65 66 public List<ResolvedReferenceType> getAncestors() { 67 List<ResolvedReferenceType> ancestors = new LinkedList<>(); 68 if (getSuperClass() != null) { 69 ReferenceTypeImpl superClass = getSuperClass(); 70 ancestors.add(superClass); 71 } else { 72 ReferenceTypeImpl object = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver); 73 ancestors.add(object); 74 } 75 ancestors.addAll(getInterfaces()); 76 for (int i = 0; i < ancestors.size(); i++) { 77 ResolvedReferenceType ancestor = ancestors.get(i); 78 if (ancestor.hasName() && ancestor.getQualifiedName().equals(Object.class.getCanonicalName())) { 79 ancestors.remove(i); 80 i--; 81 } 82 } 83 return ancestors; 84 } 85 86 public ResolvedFieldDeclaration getField(String name) { 87 for (Field field : clazz.getDeclaredFields()) { 88 if (field.getName().equals(name)) { 89 return new ReflectionFieldDeclaration(field, typeSolver); 90 } 91 } 92 for (ResolvedReferenceType ancestor : typeDeclaration.getAllAncestors()) { 93 if (ancestor.getTypeDeclaration().hasField(name)) { 94 ReflectionFieldDeclaration reflectionFieldDeclaration = (ReflectionFieldDeclaration) ancestor.getTypeDeclaration().getField(name); 95 return reflectionFieldDeclaration.replaceType(ancestor.getFieldType(name).get()); 96 } 97 } 98 throw new UnsolvedSymbolException(name, "Field in " + this); 99 } 100 101 public boolean hasField(String name) { 102 for (Field field : clazz.getDeclaredFields()) { 103 if (field.getName().equals(name)) { 104 return true; 105 } 106 } 107 ReferenceTypeImpl superclass = getSuperClass(); 108 if (superclass == null) { 109 return false; 110 } else { 111 return superclass.getTypeDeclaration().hasField(name); 112 } 113 } 114 115 public List<ResolvedFieldDeclaration> getAllFields() { 116 ArrayList<ResolvedFieldDeclaration> fields = new ArrayList<>(); 117 for (Field field : clazz.getDeclaredFields()) { 118 fields.add(new ReflectionFieldDeclaration(field, typeSolver)); 119 } 120 for (ResolvedReferenceType ancestor : typeDeclaration.getAllAncestors()) { 121 fields.addAll(ancestor.getTypeDeclaration().getAllFields()); 122 } 123 return fields; 124 } 125 126 public Set<ResolvedMethodDeclaration> getDeclaredMethods() { 127 return Arrays.stream(clazz.getDeclaredMethods()) 128 .filter(m -> !m.isSynthetic() && !m.isBridge()) 129 .map(m -> new ReflectionMethodDeclaration(m, typeSolver)) 130 .collect(Collectors.toSet()); 131 } 132 133 public List<ResolvedTypeParameterDeclaration> getTypeParameters() { 134 List<ResolvedTypeParameterDeclaration> params = new ArrayList<>(); 135 for (TypeVariable<?> tv : this.clazz.getTypeParameters()) { 136 params.add(new ReflectionTypeParameter(tv, true, typeSolver)); 137 } 138 return params; 139 } 140 141 public boolean isAssignableBy(ResolvedType type) { 142 if (type instanceof NullType) { 143 return true; 144 } 145 if (type instanceof LambdaArgumentTypePlaceholder) { 146 return isFunctionalInterface(); 147 } 148 if (type.isArray()) { 149 return false; 150 } 151 if (type.isPrimitive()) { 152 return false; 153 } 154 if (type.describe().equals(typeDeclaration.getQualifiedName())) { 155 return true; 156 } 157 if (type instanceof ReferenceTypeImpl) { 158 ReferenceTypeImpl otherTypeDeclaration = (ReferenceTypeImpl) type; 159 return otherTypeDeclaration.getTypeDeclaration().canBeAssignedTo(typeDeclaration); 160 } 161 162 return false; 163 } 164 165 public boolean hasDirectlyAnnotation(String canonicalName) { 166 for (Annotation a : clazz.getDeclaredAnnotations()) { 167 if (a.annotationType().getCanonicalName().equals(canonicalName)) { 168 return true; 169 } 170 } 171 return false; 172 } 173 174 private final boolean isFunctionalInterface() { 175 return FunctionalInterfaceLogic.getFunctionalMethod(typeDeclaration).isPresent(); 176 } 177 178 public List<ResolvedConstructorDeclaration> getConstructors() { 179 return Arrays.stream(clazz.getConstructors()) 180 .map(m -> new ReflectionConstructorDeclaration(m, typeSolver)) 181 .collect(Collectors.toList()); 182 } 183 184 public Optional<ResolvedReferenceTypeDeclaration> containerType() { 185 Class<?> declaringClass = clazz.getDeclaringClass(); 186 return declaringClass == null ? 187 Optional.empty() : 188 Optional.of(ReflectionFactory.typeDeclarationFor(declaringClass, typeSolver)); 189 } 190} 191