TypeExtractor Class — spring-boot Architecture
Architecture documentation for the TypeExtractor class in TypeUtils.java from the spring-boot codebase.
Entity Profile
Source Code
configuration-metadata/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeUtils.java lines 289–389
private static class TypeExtractor extends SimpleTypeVisitor8<String, TypeDescriptor> {
private final Types types;
TypeExtractor(Types types) {
this.types = types;
}
@Override
public String visitDeclared(DeclaredType type, TypeDescriptor descriptor) {
TypeElement enclosingElement = getEnclosingTypeElement(type);
String qualifiedName = determineQualifiedName(type, enclosingElement);
if (type.getTypeArguments().isEmpty()) {
return qualifiedName;
}
StringBuilder name = new StringBuilder();
name.append(qualifiedName);
name.append("<")
.append(type.getTypeArguments()
.stream()
.map((t) -> visit(t, descriptor))
.collect(Collectors.joining(",")))
.append(">");
return name.toString();
}
private String determineQualifiedName(DeclaredType type, TypeElement enclosingElement) {
if (enclosingElement != null) {
return getQualifiedName(enclosingElement) + "$" + type.asElement().getSimpleName();
}
return getQualifiedName(type.asElement());
}
@Override
public String visitTypeVariable(TypeVariable typeVariable, TypeDescriptor descriptor) {
TypeMirror resolvedGeneric = descriptor.resolveGeneric(typeVariable);
if (resolvedGeneric != null) {
if (resolvedGeneric instanceof TypeVariable resolveTypeVariable) {
// Still unresolved, let's use the upper bound, checking first if
// a cycle may exist
if (!hasCycle(resolveTypeVariable)) {
return visit(resolveTypeVariable.getUpperBound(), descriptor);
}
}
else {
return visit(resolvedGeneric, descriptor);
}
}
// Fallback to simple representation of the upper bound
return defaultAction(typeVariable.getUpperBound(), descriptor);
}
private boolean hasCycle(TypeVariable variable) {
TypeMirror upperBound = variable.getUpperBound();
if (upperBound instanceof DeclaredType declaredType) {
return declaredType.getTypeArguments().stream().anyMatch((candidate) -> candidate.equals(variable));
}
return false;
}
@Override
public String visitArray(ArrayType t, TypeDescriptor descriptor) {
return t.getComponentType().accept(this, descriptor) + "[]";
}
@Override
public String visitPrimitive(PrimitiveType t, TypeDescriptor descriptor) {
return this.types.boxedClass(t).getQualifiedName().toString();
}
@Override
protected String defaultAction(TypeMirror t, TypeDescriptor descriptor) {
return t.toString();
}
String getQualifiedName(Element element) {
if (element == null) {
return null;
}
TypeElement enclosingElement = getEnclosingTypeElement(element.asType());
if (enclosingElement != null) {
return getQualifiedName(enclosingElement) + "$"
+ ((DeclaredType) element.asType()).asElement().getSimpleName();
}
if (element instanceof TypeElement typeElement) {
return typeElement.getQualifiedName().toString();
}
throw new IllegalStateException("Could not extract qualified name from " + element);
}
private TypeElement getEnclosingTypeElement(TypeMirror type) {
if (type instanceof DeclaredType declaredType) {
Element enclosingElement = declaredType.asElement().getEnclosingElement();
if (enclosingElement instanceof TypeElement typeElement) {
return typeElement;
}
}
return null;
}
}
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free