io.sundr.codegen.functions.ClassTo Maven / Gradle / Ivy
/*
* Copyright 2016 The original authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.sundr.codegen.functions;
import io.sundr.FunctionFactory;
import io.sundr.Function;
import io.sundr.codegen.DefinitionRepository;
import io.sundr.codegen.model.AnnotationRef;
import io.sundr.codegen.model.AnnotationRefBuilder;
import io.sundr.codegen.model.AttributeKey;
import io.sundr.codegen.model.Attributeable;
import io.sundr.codegen.model.ClassRef;
import io.sundr.codegen.model.ClassRefBuilder;
import io.sundr.codegen.model.Kind;
import io.sundr.codegen.model.Method;
import io.sundr.codegen.model.MethodBuilder;
import io.sundr.codegen.model.PrimitiveRefBuilder;
import io.sundr.codegen.model.Property;
import io.sundr.codegen.model.PropertyBuilder;
import io.sundr.codegen.model.TypeDef;
import io.sundr.codegen.model.TypeDefBuilder;
import io.sundr.codegen.model.TypeParamDef;
import io.sundr.codegen.model.TypeParamDefBuilder;
import io.sundr.codegen.model.TypeParamRefBuilder;
import io.sundr.codegen.model.TypeRef;
import io.sundr.codegen.model.VoidRefBuilder;
import io.sundr.codegen.model.WildcardRefBuilder;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class ClassTo {
private static final String ARGUMENT_PREFIX = "arg";
public static final Function KIND = FunctionFactory.cache(new Function() {
public Kind apply(Class item) {
if (item.isAnnotation()) {
return Kind.ANNOTATION;
} else if (item.isEnum()) {
return Kind.ENUM;
} else if (item.isInterface()) {
return Kind.INTERFACE;
} else {
return Kind.CLASS;
}
}
});
public static final Function TYPEREF = FunctionFactory.cache(new Function() {
public TypeRef apply(Type item) {
if (item == null) {
return new VoidRefBuilder().build();
} else if (item instanceof WildcardType) {
return new WildcardRefBuilder().withBounds(Arrays.asList(((WildcardType) item).getLowerBounds()).stream().map(t->TYPEREF.apply(t)).collect(Collectors.toList())).build();
} else if (item instanceof TypeVariable) {
return new TypeParamRefBuilder().withName(((TypeVariable) item).getName()).build();
} else if (item instanceof GenericArrayType) {
Type target = item;
int dimensions = 0;
while (target instanceof GenericArrayType) {
target = ((GenericArrayType) target).getGenericComponentType();
dimensions++;
}
TypeRef targetRef = TYPEREF.apply(target);
return targetRef.withDimensions(dimensions + targetRef.getDimensions());
} else if (item instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) item;
Type rawType = parameterizedType.getRawType();
List arguments = new ArrayList();
for (Type arg : parameterizedType.getActualTypeArguments()) {
arguments.add(TYPEREF.apply(arg));
}
return new ClassRefBuilder((ClassRef) TYPEREF.apply(rawType))
.withArguments(arguments)
.build();
} else if (Object.class.equals(item)) {
return ClassRef.OBJECT;
} else if (item instanceof Class) {
Class c = (Class) item;
if (c.isPrimitive()) {
return new PrimitiveRefBuilder().withName(c.getName()).build();
} else {
List arguments = new ArrayList();
for (TypeVariable v : c.getTypeParameters()) {
arguments.add(TYPEREF.apply(v));
}
return new ClassRefBuilder()
.withDefinition(TYPEDEF.apply(c))
.withArguments(arguments)
.build();
}
}
throw new IllegalArgumentException("Can't convert type:"+item+" to a TypeRef");
}
});
public static final Function, AnnotationRef> ANNOTATIONTYPEREF = FunctionFactory.cache(new Function, AnnotationRef>() {
@Override
public AnnotationRef apply(Class extends Annotation> item) {
//An annotation can't be a primitive or a void type, so its safe to cast.
ClassRef classRef = (ClassRef) TYPEREF.apply(item);
Map parameters;
return new AnnotationRefBuilder().withClassRef(classRef).build();
}
});
private static final Function INTERNAL_TYPEDEF = new Function() {
public TypeDef apply(Class item) {
if (Object.class.equals(item)) {
return TypeDef.OBJECT;
}
Kind kind = KIND.apply(item);
List extendsList = new ArrayList();
List implementsList = new ArrayList();
List properties = new ArrayList();
List methods = new ArrayList();
List constructors = new ArrayList();
List parameters = new ArrayList();
if (item.getSuperclass() != null && kind == Kind.INTERFACE) {
extendsList.add((ClassRef) TYPEREF.apply(item.getSuperclass()));
}
constructors.addAll(getConstructors(item));
methods.addAll(getMethods(item));
properties.addAll(getProperties(item));
for (Class interfaceClass : item.getInterfaces()) {
TypeRef ref = TYPEREF.apply(interfaceClass);
if (ref instanceof ClassRef) {
implementsList.add((ClassRef) ref);
}
}
for (TypeVariable typeVariable : item.getTypeParameters()) {
List bounds = new ArrayList();
for (Type boundType : typeVariable.getBounds()) {
TypeRef typeRef = TYPEREF.apply(boundType);
if (typeRef instanceof ClassRef) {
bounds.add((ClassRef)typeRef);
}
}
parameters.add(new TypeParamDefBuilder()
.withName(typeVariable.getName())
.withBounds(bounds)
.build());
}
return DefinitionRepository.getRepository().register(new TypeDefBuilder()
.withKind(kind)
.withName(item.getSimpleName())
.withPackageName(item.getPackage() != null ? item.getPackage().getName() : null)
.withModifiers(item.getModifiers())
.withParameters(parameters)
.withConstructors(constructors)
.withMethods(methods)
.withProperties(properties)
.withExtendsList(extendsList)
.withImplementsList(implementsList)
.build());
}
};
private static final Function INTERNAL_SHALLOW_TYPEDEF = new Function() {
public TypeDef apply(Class item) {
if (Object.class.equals(item)) {
return TypeDef.OBJECT;
}
Kind kind = KIND.apply(item);
return new TypeDefBuilder()
.withKind(kind)
.withName(item.getSimpleName())
.withPackageName(item.getPackage() != null ? item.getPackage().getName() : null)
.withModifiers(item.getModifiers())
.withParameters()
.build();
}
};
public static final Function TYPEDEF = FunctionFactory.cache(INTERNAL_TYPEDEF).withFallback(INTERNAL_SHALLOW_TYPEDEF).withMaximumRecursionLevel(5).withMaximumNestingDepth(5);
private static Function TYPEPARAMDEF = FunctionFactory.cache(new Function() {
public TypeParamDef apply(Type item) {
if (item instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) item;
String name = typeVariable.getName();
List bounds = new ArrayList();
for (Type b : typeVariable.getBounds()) {
if (b instanceof Class) {
Class c = (Class) b;
bounds.add((ClassRef) TYPEREF.apply(c));
}
}
return new TypeParamDefBuilder().withName(name).withBounds(bounds).build();
}
return null;
}
});
private static Set getProperties(Class item) {
Set properties = new HashSet();
for (Field field : item.getDeclaredFields()) {
List annotationRefs = new ArrayList();
for (Annotation annotation : field.getDeclaredAnnotations()) {
annotationRefs.add(ANNOTATIONTYPEREF.apply(annotation.annotationType()));
}
field.getDeclaringClass();
properties.add(new PropertyBuilder()
.withName(field.getName())
.withModifiers(field.getModifiers())
.withAnnotations(annotationRefs)
.withTypeRef(TYPEREF.apply(field.getGenericType()))
.build());
}
return properties;
}
private static Set getConstructors(Class item) {
Set constructors = new HashSet();
for (java.lang.reflect.Constructor constructor : item.getDeclaredConstructors()) {
List annotationRefs = new ArrayList();
for (Annotation annotation : constructor.getDeclaredAnnotations()) {
annotationRefs.add(ANNOTATIONTYPEREF.apply(annotation.annotationType()));
}
List arguments = new ArrayList();
for (int i = 1; i <= constructor.getGenericParameterTypes().length; i++) {
Type argumentType = constructor.getGenericParameterTypes()[i - 1];
arguments.add(new PropertyBuilder()
.withName(ARGUMENT_PREFIX + i)
.withTypeRef(TYPEREF.apply(argumentType))
.build());
}
List parameters = new ArrayList();
for (Type type : constructor.getGenericParameterTypes()) {
TypeParamDef typeParamDef = TYPEPARAMDEF.apply(type);
if (typeParamDef != null) {
parameters.add(typeParamDef);
}
}
constructors.add(new MethodBuilder()
.withName(constructor.getName())
.withModifiers(constructor.getModifiers())
.withArguments(arguments)
.withParameters(parameters)
.withAnnotations(annotationRefs)
.build());
}
return constructors;
}
private static Set getMethods(Class item) {
Set methods = new HashSet();
for (java.lang.reflect.Method method : item.getDeclaredMethods()) {
List annotationRefs = new ArrayList();
for (Annotation annotation : method.getDeclaredAnnotations()) {
annotationRefs.add(ANNOTATIONTYPEREF.apply(annotation.annotationType()));
}
List arguments = new ArrayList();
for (int i = 1; i <= method.getGenericParameterTypes().length; i++) {
Type argumentType = method.getGenericParameterTypes()[i - 1];
arguments.add(new PropertyBuilder()
.withName(ARGUMENT_PREFIX + i)
.withTypeRef(TYPEREF.apply(argumentType))
.build());
}
List parameters = new ArrayList();
for (Type type : method.getGenericParameterTypes()) {
TypeParamDef typeParamDef = TYPEPARAMDEF.apply(type);
if (typeParamDef != null) {
parameters.add(typeParamDef);
}
}
Map attributes = new HashMap<>();
if (method.getDefaultValue() != null) {
attributes.put(Attributeable.DEFAULT_VALUE, method.getDefaultValue());
}
methods.add(new MethodBuilder()
.withName(method.getName())
.withModifiers(method.getModifiers())
.withReturnType(TYPEREF.apply(method.getReturnType()))
.withArguments(arguments)
.withParameters(parameters)
.withAnnotations(annotationRefs)
.withAttributes(attributes)
.build());
}
return methods;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy