Update ClassNameGenerator to work with a ClassName target

This commit updates ClassNameGenerator so that it uses a ClassName for
its default target. This makes sure that a target that has been
generated can be used.

See gh-29027
This commit is contained in:
Stephane Nicoll
2022-09-22 14:22:17 +02:00
parent 1707a22c18
commit 8ef850ff91
9 changed files with 99 additions and 81 deletions

View File

@@ -27,8 +27,8 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Generate unique class names based on a target {@link Class} and a feature
* name.
* Generate unique class names based on a target {@link ClassName} and a
* feature name.
*
* <p>This class is stateful, so the same instance should be used for all name
* generation.
@@ -43,7 +43,7 @@ public final class ClassNameGenerator {
private static final String AOT_FEATURE = "Aot";
private final Class<?> defaultTarget;
private final ClassName defaultTarget;
private final String featureNamePrefix;
@@ -55,7 +55,7 @@ public final class ClassNameGenerator {
* feature name prefix.
* @param defaultTarget the default target class to use
*/
public ClassNameGenerator(Class<?> defaultTarget) {
public ClassNameGenerator(ClassName defaultTarget) {
this(defaultTarget, "");
}
@@ -65,11 +65,11 @@ public final class ClassNameGenerator {
* @param defaultTarget the default target class to use
* @param featureNamePrefix the prefix to use to qualify feature names
*/
public ClassNameGenerator(Class<?> defaultTarget, String featureNamePrefix) {
public ClassNameGenerator(ClassName defaultTarget, String featureNamePrefix) {
this(defaultTarget, featureNamePrefix, new ConcurrentHashMap<>());
}
private ClassNameGenerator(Class<?> defaultTarget, String featureNamePrefix,
private ClassNameGenerator(ClassName defaultTarget, String featureNamePrefix,
Map<String, AtomicInteger> sequenceGenerator) {
Assert.notNull(defaultTarget, "'defaultTarget' must not be null");
this.defaultTarget = defaultTarget;
@@ -98,16 +98,16 @@ public final class ClassNameGenerator {
* {@code null} to use the main target
* @return a unique generated class name
*/
public ClassName generateClassName(String featureName, @Nullable Class<?> target) {
public ClassName generateClassName(String featureName, @Nullable ClassName target) {
return generateSequencedClassName(getRootName(featureName, target));
}
private String getRootName(String featureName, @Nullable Class<?> target) {
private String getRootName(String featureName, @Nullable ClassName target) {
Assert.hasLength(featureName, "'featureName' must not be empty");
featureName = clean(featureName);
Class<?> targetToUse = (target != null ? target : this.defaultTarget);
ClassName targetToUse = (target != null ? target : this.defaultTarget);
String featureNameToUse = this.featureNamePrefix + featureName;
return targetToUse.getName().replace("$", "_") + SEPARATOR + StringUtils.capitalize(featureNameToUse);
return toName(targetToUse).replace("$", "_") + SEPARATOR + StringUtils.capitalize(featureNameToUse);
}
private String clean(String name) {
@@ -147,4 +147,8 @@ public final class ClassNameGenerator {
this.sequenceGenerator);
}
private static String toName(ClassName className) {
return GeneratedTypeReference.of(className).getName();
}
}

View File

@@ -99,7 +99,7 @@ public class GeneratedClasses {
* @return an existing or newly generated class
*/
public GeneratedClass getOrAddForFeatureComponent(String featureName,
Class<?> targetComponent, Consumer<TypeSpec.Builder> type) {
ClassName targetComponent, Consumer<TypeSpec.Builder> type) {
Assert.hasLength(featureName, "'featureName' must not be empty");
Assert.notNull(targetComponent, "'targetComponent' must not be null");
@@ -111,6 +111,24 @@ public class GeneratedClasses {
return generatedClass;
}
/**
* Get or add a generated class for the specified {@code featureName}
* targeting the specified {@code component}. If this method has previously
* been called with the given {@code featureName}/{@code target} the
* existing class will be returned, otherwise a new class will be generated,
* otherwise a new class will be generated.
* @param featureName the name of the feature to associate with the
* generated class
* @param targetComponent the target component
* @param type a {@link Consumer} used to build the type
* @return an existing or newly generated class
*/
public GeneratedClass getOrAddForFeatureComponent(String featureName,
Class<?> targetComponent, Consumer<TypeSpec.Builder> type) {
return getOrAddForFeatureComponent(featureName, ClassName.get(targetComponent), type);
}
/**
* Add a new generated class for the specified {@code featureName} and no
* particular component.
@@ -135,7 +153,7 @@ public class GeneratedClasses {
* @return the newly generated class
*/
public GeneratedClass addForFeatureComponent(String featureName,
Class<?> targetComponent, Consumer<TypeSpec.Builder> type) {
ClassName targetComponent, Consumer<TypeSpec.Builder> type) {
Assert.hasLength(featureName, "'featureName' must not be empty");
Assert.notNull(targetComponent, "'targetComponent' must not be null");
@@ -143,8 +161,23 @@ public class GeneratedClasses {
return createAndAddGeneratedClass(featureName, targetComponent, type);
}
/**
* Add a new generated class for the specified {@code featureName} targeting
* the specified {@code component}.
* @param featureName the name of the feature to associate with the
* generated class
* @param targetComponent the target component
* @param type a {@link Consumer} used to build the type
* @return the newly generated class
*/
public GeneratedClass addForFeatureComponent(String featureName,
Class<?> targetComponent, Consumer<TypeSpec.Builder> type) {
return addForFeatureComponent(featureName, ClassName.get(targetComponent), type);
}
private GeneratedClass createAndAddGeneratedClass(String featureName,
@Nullable Class<?> targetComponent, Consumer<TypeSpec.Builder> type) {
@Nullable ClassName targetComponent, Consumer<TypeSpec.Builder> type) {
ClassName className = this.classNameGenerator.generateClassName(featureName, targetComponent);
GeneratedClass generatedClass = new GeneratedClass(className, type);
@@ -171,7 +204,7 @@ public class GeneratedClasses {
this.classes, this.classesByOwner);
}
private record Owner(String featureNamePrefix, String featureName, @Nullable Class<?> target) {
private record Owner(String featureNamePrefix, String featureName, @Nullable ClassName target) {
}
}