Refactoring of constructors for generated entities
This commit is contained in:
parent
6d0b551b5e
commit
96b2669a00
11 changed files with 89 additions and 91 deletions
|
@ -50,6 +50,7 @@ import javax.lang.model.SourceVersion;
|
|||
import static org.keycloak.models.map.processor.FieldAccessorType.GETTER;
|
||||
import static org.keycloak.models.map.processor.Util.getGenericsDeclaration;
|
||||
import static org.keycloak.models.map.processor.Util.isMapType;
|
||||
import static org.keycloak.models.map.processor.Util.singularToPlural;
|
||||
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||
public abstract class AbstractGenerateEntityImplementationsProcessor extends AbstractProcessor {
|
||||
|
@ -123,11 +124,11 @@ public abstract class AbstractGenerateEntityImplementationsProcessor extends Abs
|
|||
|
||||
// Merge plurals with singulars
|
||||
methodsPerAttribute.keySet().stream()
|
||||
.filter(key -> methodsPerAttribute.containsKey(key + "s"))
|
||||
.filter(key -> methodsPerAttribute.containsKey(singularToPlural(key)))
|
||||
.collect(Collectors.toSet())
|
||||
.forEach(key -> {
|
||||
HashSet<ExecutableElement> removed = methodsPerAttribute.remove(key);
|
||||
methodsPerAttribute.get(key + "s").addAll(removed);
|
||||
methodsPerAttribute.get(singularToPlural(key)).addAll(removed);
|
||||
});
|
||||
|
||||
return methodsPerAttribute;
|
||||
|
|
|
@ -26,6 +26,7 @@ import javax.lang.model.element.Name;
|
|||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
import static org.keycloak.models.map.processor.Util.getGenericsDeclaration;
|
||||
import static org.keycloak.models.map.processor.Util.pluralToSingular;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -52,7 +53,7 @@ enum FieldAccessorType {
|
|||
COLLECTION_ADD {
|
||||
@Override
|
||||
public boolean is(ExecutableElement method, String fieldName, Types types, TypeMirror fieldType) {
|
||||
String fieldNameSingular = fieldName.endsWith("s") ? fieldName.substring(0, fieldName.length() - 1) : fieldName;
|
||||
String fieldNameSingular = pluralToSingular(fieldName);
|
||||
String methodName = "add" + fieldNameSingular;
|
||||
List<TypeMirror> res = getGenericsDeclaration(fieldType);
|
||||
return Objects.equals(methodName, method.getSimpleName().toString())
|
||||
|
@ -63,7 +64,7 @@ enum FieldAccessorType {
|
|||
COLLECTION_DELETE {
|
||||
@Override
|
||||
public boolean is(ExecutableElement method, String fieldName, Types types, TypeMirror fieldType) {
|
||||
String fieldNameSingular = fieldName.endsWith("s") ? fieldName.substring(0, fieldName.length() - 1) : fieldName;
|
||||
String fieldNameSingular = pluralToSingular(fieldName);
|
||||
String removeFromCollection = "remove" + fieldNameSingular;
|
||||
List<TypeMirror> res = getGenericsDeclaration(fieldType);
|
||||
return Objects.equals(removeFromCollection, method.getSimpleName().toString())
|
||||
|
@ -74,7 +75,7 @@ enum FieldAccessorType {
|
|||
MAP_ADD {
|
||||
@Override
|
||||
public boolean is(ExecutableElement method, String fieldName, Types types, TypeMirror fieldType) {
|
||||
String fieldNameSingular = fieldName.endsWith("s") ? fieldName.substring(0, fieldName.length() - 1) : fieldName;
|
||||
String fieldNameSingular = pluralToSingular(fieldName);
|
||||
String methodName = "set" + fieldNameSingular;
|
||||
List<TypeMirror> res = getGenericsDeclaration(fieldType);
|
||||
return Objects.equals(methodName, method.getSimpleName().toString())
|
||||
|
@ -86,7 +87,7 @@ enum FieldAccessorType {
|
|||
MAP_GET {
|
||||
@Override
|
||||
public boolean is(ExecutableElement method, String fieldName, Types types, TypeMirror fieldType) {
|
||||
String fieldNameSingular = fieldName.endsWith("s") ? fieldName.substring(0, fieldName.length() - 1) : fieldName;
|
||||
String fieldNameSingular = pluralToSingular(fieldName);
|
||||
String methodName = "get" + fieldNameSingular;
|
||||
List<TypeMirror> res = getGenericsDeclaration(fieldType);
|
||||
return Objects.equals(methodName, method.getSimpleName().toString())
|
||||
|
|
|
@ -171,7 +171,7 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti
|
|||
pw.println(" return " + types.erasure(firstParameterType) + ".class;");
|
||||
pw.println(" }");
|
||||
});
|
||||
|
||||
|
||||
FieldAccessorType.getMethod(FieldAccessorType.MAP_ADD, methods, fieldName, types, fieldType).ifPresent(method -> {
|
||||
TypeMirror firstParameterType = method.getParameters().get(0).asType();
|
||||
TypeMirror secondParameterType = method.getParameters().get(1).asType();
|
||||
|
@ -182,7 +182,7 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti
|
|||
pw.println(" return " + types.erasure(secondParameterType) + ".class;");
|
||||
pw.println(" }");
|
||||
});
|
||||
|
||||
|
||||
for (ExecutableElement ee : methods) {
|
||||
FieldAccessorType fat = FieldAccessorType.determineType(ee, fieldName, types, fieldType);
|
||||
printMethodBody(pw, fat, ee, className, fieldType);
|
||||
|
@ -265,6 +265,7 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti
|
|||
boolean needsDeepClone = fieldGetters(methodsPerAttribute)
|
||||
.map(ExecutableElement::getReturnType)
|
||||
.anyMatch(fieldType -> ! isKnownCollectionOfImmutableFinalTypes(fieldType) && ! isImmutableFinalType(fieldType));
|
||||
boolean usingGeneratedCloner = ! hasDeepClone && needsDeepClone;
|
||||
|
||||
JavaFileObject file = processingEnv.getFiler().createSourceFile(mapImplClassName);
|
||||
try (PrintWriter pw = new PrintWriterNoJavaLang(file.openWriter())) {
|
||||
|
@ -283,28 +284,26 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti
|
|||
.map(ExecutableElement.class::cast)
|
||||
.filter((ExecutableElement ee) -> ee.getKind() == ElementKind.CONSTRUCTOR)
|
||||
.forEach((ExecutableElement ee) -> {
|
||||
if (hasDeepClone || ! needsDeepClone) {
|
||||
pw.println(" "
|
||||
+ ee.getModifiers().stream().map(Object::toString).collect(Collectors.joining(" "))
|
||||
+ " " + mapSimpleClassName + "(" + methodParameters(ee.getParameters()) + ") { super(" + ee.getParameters() + "); }"
|
||||
);
|
||||
} else if (needsDeepClone) {
|
||||
// Create constructor and initialize cloner to DUMB_CLONER if necessary
|
||||
if (usingGeneratedCloner) {
|
||||
pw.println(" /**");
|
||||
pw.println(" * @deprecated This constructor uses a {@link DeepCloner#DUMB_CLONER} that does not clone anything. Use {@link #" + mapSimpleClassName + "(DeepCloner)} variant instead");
|
||||
pw.println(" */");
|
||||
pw.println(" "
|
||||
+ ee.getModifiers().stream().map(Object::toString).collect(Collectors.joining(" "))
|
||||
+ " "
|
||||
+ mapSimpleClassName + "(" + methodParameters(ee.getParameters()) + ") { this(DeepCloner.DUMB_CLONER" + (ee.getParameters().isEmpty() ? "" : ", ") + ee.getParameters() + "); }"
|
||||
);
|
||||
pw.println(" "
|
||||
+ ee.getModifiers().stream().map(Object::toString).collect(Collectors.joining(" "))
|
||||
+ " "
|
||||
+ mapSimpleClassName + "(DeepCloner cloner" + (ee.getParameters().isEmpty() ? "" : ", ") + methodParameters(ee.getParameters()) + ") { super(" + ee.getParameters() + "); this.cloner = cloner; }"
|
||||
);
|
||||
}
|
||||
pw.println(" "
|
||||
+ ee.getModifiers().stream().map(Object::toString).collect(Collectors.joining(" "))
|
||||
+ " " + mapSimpleClassName + "(" + methodParameters(ee.getParameters()) + ") {"
|
||||
);
|
||||
pw.println(" super(" + ee.getParameters() + ");");
|
||||
if (usingGeneratedCloner) pw.println(" this.cloner = DeepCloner.DUMB_CLONER;");
|
||||
pw.println(" }");
|
||||
});
|
||||
|
||||
pw.println(" "
|
||||
+ "public "
|
||||
+ mapSimpleClassName + "(DeepCloner cloner) { super(); " + (!usingGeneratedCloner ? "" : "this.cloner = cloner;") + "}"
|
||||
);
|
||||
|
||||
// equals, hashCode, toString
|
||||
pw.println(" @Override public boolean equals(Object o) {");
|
||||
pw.println(" if (o == this) return true; ");
|
||||
|
@ -339,7 +338,7 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti
|
|||
pw.println(" }");
|
||||
|
||||
// deepClone
|
||||
if (! hasDeepClone && needsDeepClone) {
|
||||
if (usingGeneratedCloner) {
|
||||
pw.println(" private final DeepCloner cloner;");
|
||||
pw.println(" public <V> V deepClone(V obj) {");
|
||||
pw.println(" return cloner.from(obj);");
|
||||
|
@ -363,7 +362,7 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti
|
|||
|
||||
if (parentMethod.isPresent()) {
|
||||
processingEnv.getMessager().printMessage(Kind.OTHER, "Method " + method + " is declared in a parent class.", method);
|
||||
} else if (fat != FieldAccessorType.UNKNOWN && ! printMethodBody(pw, fat, method, "f" + me.getKey(), fieldType)) {
|
||||
} else if (fat == FieldAccessorType.UNKNOWN || ! printMethodBody(pw, fat, method, "f" + me.getKey(), fieldType)) {
|
||||
processingEnv.getMessager().printMessage(Kind.WARNING, "Could not determine desired semantics of method from its signature", method);
|
||||
}
|
||||
}
|
||||
|
@ -446,10 +445,12 @@ public class GenerateEntityImplementationsProcessor extends AbstractGenerateEnti
|
|||
pw.println(" }");
|
||||
return true;
|
||||
case COLLECTION_DELETE:
|
||||
boolean needsReturn = method.getReturnType().getKind() != TypeKind.VOID;
|
||||
pw.println(" @SuppressWarnings(\"unchecked\") @Override public " + method.getReturnType() + " " + method.getSimpleName() + "(" + firstParameterType + " p0) {");
|
||||
pw.println(" if (" + fieldName + " == null) { return; }");
|
||||
pw.println(" if (" + fieldName + " == null) { return" + (needsReturn ? " false" : "") + "; }");
|
||||
pw.println(" boolean removed = " + fieldName + ".remove(p0)" + ("java.util.Map".equals(typeElement.getQualifiedName().toString()) ? " != null" : "") + ";");
|
||||
pw.println(" updated |= removed;");
|
||||
if (needsReturn) pw.println(" return removed;");
|
||||
pw.println(" }");
|
||||
return true;
|
||||
case MAP_ADD:
|
||||
|
|
|
@ -104,6 +104,7 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera
|
|||
boolean needsDeepClone = fieldGetters(methodsPerAttribute)
|
||||
.map(ExecutableElement::getReturnType)
|
||||
.anyMatch(fieldType -> ! isKnownCollectionOfImmutableFinalTypes(fieldType) && ! isImmutableFinalType(fieldType));
|
||||
boolean usingGeneratedCloner = ! hasDeepClone && needsDeepClone;
|
||||
boolean hasId = methodsPerAttribute.containsKey("Id") || allMembers.stream().anyMatch(el -> "getId".equals(el.getSimpleName().toString()));
|
||||
|
||||
JavaFileObject file = processingEnv.getFiler().createSourceFile(hotRodImplClassName);
|
||||
|
@ -132,45 +133,43 @@ public class GenerateHotRodEntityImplementationsProcessor extends AbstractGenera
|
|||
.map(ExecutableElement.class::cast)
|
||||
.filter((ExecutableElement ee) -> ee.getKind() == ElementKind.CONSTRUCTOR)
|
||||
.forEach((ExecutableElement ee) -> {
|
||||
if (hasDeepClone || ! needsDeepClone) {
|
||||
pw.println(" "
|
||||
+ ee.getModifiers().stream().map(Object::toString).collect(Collectors.joining(" "))
|
||||
+ " " + hotRodSimpleClassName + "(" + methodParameters(ee.getParameters()) + ") {"
|
||||
);
|
||||
pw.println(" super(" + ee.getParameters() + ");");
|
||||
pw.println(" this." + ENTITY_VARIABLE + " = new " + className + "();");
|
||||
pw.println(" }");
|
||||
} else if (needsDeepClone) {
|
||||
// Create constructor and initialize cloner to DUMB_CLONER if necessary
|
||||
if (usingGeneratedCloner) {
|
||||
pw.println(" /**");
|
||||
pw.println(" * @deprecated This constructor uses a {@link DeepCloner#DUMB_CLONER} that does not clone anything. Use {@link #" + hotRodSimpleClassName + "(DeepCloner)} variant instead");
|
||||
pw.println(" */");
|
||||
pw.println(" "
|
||||
+ ee.getModifiers().stream().map(Object::toString).collect(Collectors.joining(" "))
|
||||
+ " "
|
||||
+ hotRodSimpleClassName + "(" + methodParameters(ee.getParameters()) + ") { this(DeepCloner.DUMB_CLONER" + (ee.getParameters().isEmpty() ? "" : ", ") + ee.getParameters() + "); }"
|
||||
);
|
||||
pw.println(" "
|
||||
+ ee.getModifiers().stream().map(Object::toString).collect(Collectors.joining(" "))
|
||||
+ " "
|
||||
+ hotRodSimpleClassName + "(DeepCloner cloner" + (ee.getParameters().isEmpty() ? "" : ", ") + methodParameters(ee.getParameters()) + ") {"
|
||||
);
|
||||
pw.println(" super(" + ee.getParameters() + ");");
|
||||
pw.println(" this.cloner = cloner;");
|
||||
pw.println(" this." + ENTITY_VARIABLE + " = new " + className + "();");
|
||||
pw.println(" }");
|
||||
}
|
||||
pw.println(" "
|
||||
+ ee.getModifiers().stream().map(Object::toString).collect(Collectors.joining(" "))
|
||||
+ " " + hotRodSimpleClassName + "(" + methodParameters(ee.getParameters()) + ") {"
|
||||
);
|
||||
pw.println(" super(" + ee.getParameters() + ");");
|
||||
if (usingGeneratedCloner) pw.println(" this.cloner = DeepCloner.DUMB_CLONER;");
|
||||
pw.println(" this." + ENTITY_VARIABLE + " = new " + className + "();");
|
||||
pw.println(" }");
|
||||
});
|
||||
|
||||
// Add constructor for setting HotRodEntity
|
||||
if (usingGeneratedCloner) {
|
||||
pw.println(" /**");
|
||||
pw.println(" * @deprecated This constructor uses a {@link DeepCloner#DUMB_CLONER} that does not clone anything. Use {@link #" + hotRodSimpleClassName + "(DeepCloner)} variant instead");
|
||||
pw.println(" */");
|
||||
}
|
||||
pw.println(" " +
|
||||
"public " + hotRodSimpleClassName + "(" + className + " " + ENTITY_VARIABLE + ") {"
|
||||
);
|
||||
pw.println(" this." + ENTITY_VARIABLE + " = " + ENTITY_VARIABLE + ";");
|
||||
if (! hasDeepClone && needsDeepClone) {
|
||||
if (usingGeneratedCloner) {
|
||||
pw.println(" this.cloner = DeepCloner.DUMB_CLONER;");
|
||||
}
|
||||
pw.println(" }");
|
||||
|
||||
pw.println(" public " + hotRodSimpleClassName + "(DeepCloner cloner) {");
|
||||
pw.println(" super();");
|
||||
pw.println(" this." + ENTITY_VARIABLE + " = new " + className + "();");
|
||||
if (usingGeneratedCloner) pw.println(" this.cloner = cloner;");
|
||||
pw.println(" }");
|
||||
|
||||
// equals, hashCode, toString
|
||||
pw.println(" @Override public boolean equals(Object o) {");
|
||||
pw.println(" if (o == this) return true; ");
|
||||
|
|
|
@ -99,4 +99,11 @@ public class Util {
|
|||
.findAny();
|
||||
}
|
||||
|
||||
public static String singularToPlural(String word) {
|
||||
return word.endsWith("y") ? word.substring(0, word.length() -1) + "ies" : word + "s";
|
||||
}
|
||||
|
||||
public static String pluralToSingular(String word) {
|
||||
return word.endsWith("ies") ? word.substring(0, word.length() - 3) + "y" : word.endsWith("s") ? word.substring(0, word.length() - 1) : word;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,9 +49,9 @@ public class HotRodMapStorageProviderFactory implements AmphibianProviderFactory
|
|||
private static final Logger LOG = Logger.getLogger(HotRodMapStorageProviderFactory.class);
|
||||
|
||||
private final static DeepCloner CLONER = new DeepCloner.Builder()
|
||||
.constructorDC(MapClientEntity.class, HotRodClientEntityDelegate::new)
|
||||
.constructor(MapClientEntity.class, HotRodClientEntityDelegate::new)
|
||||
.constructor(MapProtocolMapperEntity.class, HotRodProtocolMapperEntityDelegate::new)
|
||||
.constructorDC(MapGroupEntity.class, HotRodGroupEntityDelegate::new)
|
||||
.constructor(MapGroupEntity.class, HotRodGroupEntityDelegate::new)
|
||||
.build();
|
||||
|
||||
public static final Map<Class<?>, HotRodEntityDescriptor<?, ?>> ENTITY_DESCRIPTOR_MAP = new HashMap<>();
|
||||
|
|
|
@ -42,6 +42,8 @@ import org.hibernate.annotations.TypeDefs;
|
|||
import org.keycloak.models.map.client.MapClientEntity.AbstractClientEntity;
|
||||
import org.keycloak.models.map.client.MapProtocolMapperEntity;
|
||||
import static org.keycloak.models.map.storage.jpa.client.JpaClientMapStorage.SUPPORTED_VERSION;
|
||||
|
||||
import org.keycloak.models.map.common.DeepCloner;
|
||||
import org.keycloak.models.map.storage.jpa.hibernate.jsonb.JsonbType;
|
||||
|
||||
@Entity
|
||||
|
@ -87,6 +89,10 @@ public class JpaClientEntity extends AbstractClientEntity implements Serializabl
|
|||
this.metadata = new JpaClientMetadata();
|
||||
}
|
||||
|
||||
public JpaClientEntity(DeepCloner cloner) {
|
||||
this.metadata = new JpaClientMetadata(cloner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by hibernate when calling cb.construct from read(QueryParameters) method.
|
||||
* It is used to select client without metadata(json) field.
|
||||
|
|
|
@ -18,9 +18,18 @@ package org.keycloak.models.map.storage.jpa.client.entity;
|
|||
|
||||
import java.io.Serializable;
|
||||
import org.keycloak.models.map.client.MapClientEntityImpl;
|
||||
import org.keycloak.models.map.common.DeepCloner;
|
||||
|
||||
public class JpaClientMetadata extends MapClientEntityImpl implements Serializable {
|
||||
|
||||
public JpaClientMetadata(DeepCloner cloner) {
|
||||
super(cloner);
|
||||
}
|
||||
|
||||
public JpaClientMetadata() {
|
||||
super();
|
||||
}
|
||||
|
||||
private Integer entityVersion;
|
||||
|
||||
public Integer getEntityVersion() {
|
||||
|
|
|
@ -111,7 +111,6 @@ public class DeepCloner {
|
|||
* Builder for the {@code DeepCloner} helper class.
|
||||
*/
|
||||
public static class Builder {
|
||||
private final Map<Class<?>, Supplier<?>> parameterlessConstructors = new HashMap<>();
|
||||
private final Map<Class<?>, Function<DeepCloner, ?>> constructors = new HashMap<>();
|
||||
private final Map<Class<?>, Cloner<?>> clonersWithId = new HashMap<>(org.keycloak.models.map.common.AutogeneratedCloners.CLONERS_WITH_ID);
|
||||
private final Map<Class<?>, Cloner<?>> clonersWithoutId = new HashMap<>(org.keycloak.models.map.common.AutogeneratedCloners.CLONERS_WITHOUT_ID);
|
||||
|
@ -124,7 +123,7 @@ public class DeepCloner {
|
|||
* @return
|
||||
*/
|
||||
public DeepCloner build() {
|
||||
return new DeepCloner(parameterlessConstructors, constructors, delegateCreators, entityFieldDelegateCreators, clonersWithId, clonersWithoutId, genericCloner);
|
||||
return new DeepCloner(constructors, delegateCreators, entityFieldDelegateCreators, clonersWithId, clonersWithoutId, genericCloner);
|
||||
}
|
||||
|
||||
private <V> void forThisClassAndAllMarkedParentsAndInterfaces(Class<V> rootClazz, Consumer<Class<?>> action) {
|
||||
|
@ -149,22 +148,6 @@ public class DeepCloner {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a method, often a constructor, that instantiates a record of type {@code V}.
|
||||
*
|
||||
* @param <V> Class or interface that would be instantiated by the given methods
|
||||
* @param clazz Class or interface that would be instantiated by the given methods
|
||||
* @param constructorNoParameters Parameterless function that creates a new instance of class {@code V}.
|
||||
* If {@code null}, parameterless constructor is not available.
|
||||
* @return This builder.
|
||||
*/
|
||||
public <V> Builder constructor(Class<V> clazz, Supplier<? extends V> constructorNoParameters) {
|
||||
if (constructorNoParameters != null) {
|
||||
forThisClassAndAllMarkedParentsAndInterfaces(clazz, cl -> this.parameterlessConstructors.put(cl, constructorNoParameters));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a method, often a constructor, that instantiates a record of type {@code V}.
|
||||
*
|
||||
|
@ -174,7 +157,7 @@ public class DeepCloner {
|
|||
* If {@code null}, such a single-parameter constructor is not available.
|
||||
* @return This builder.
|
||||
*/
|
||||
public <V> Builder constructorDC(Class<V> clazz, Function<DeepCloner, ? extends V> constructor) {
|
||||
public <V> Builder constructor(Class<V> clazz, Function<DeepCloner, ? extends V> constructor) {
|
||||
if (constructor != null) {
|
||||
forThisClassAndAllMarkedParentsAndInterfaces(clazz, cl -> this.constructors.put(cl, constructor));
|
||||
}
|
||||
|
@ -267,7 +250,6 @@ public class DeepCloner {
|
|||
|
||||
private static final Logger LOG = Logger.getLogger(DeepCloner.class);
|
||||
|
||||
private final Map<Class<?>, Supplier<?>> parameterlessConstructors;
|
||||
private final Map<Class<?>, Function<DeepCloner, ?>> constructors;
|
||||
private final Map<Class<?>, Cloner<?>> clonersWithId;
|
||||
private final Map<Class<?>, Cloner<?>> clonersWithoutId;
|
||||
|
@ -276,14 +258,12 @@ public class DeepCloner {
|
|||
private final Cloner<?> genericCloner;
|
||||
private final Map<Class<?>, Object> emptyInstances = new HashMap<>(AutogeneratedCloners.EMPTY_INSTANCES);
|
||||
|
||||
private DeepCloner(Map<Class<?>, Supplier<?>> parameterlessConstructors,
|
||||
Map<Class<?>, Function<DeepCloner, ?>> constructors,
|
||||
private DeepCloner(Map<Class<?>, Function<DeepCloner, ?>> constructors,
|
||||
Map<Class<?>, DelegateCreator<?>> delegateCreators,
|
||||
Map<Class<?>, EntityFieldDelegateCreator<?>> entityFieldDelegateCreators,
|
||||
Map<Class<?>, Cloner<?>> clonersWithId,
|
||||
Map<Class<?>, Cloner<?>> clonersWithoutId,
|
||||
Cloner<?> genericCloner) {
|
||||
this.parameterlessConstructors = parameterlessConstructors;
|
||||
this.constructors = constructors;
|
||||
this.clonersWithId = clonersWithId;
|
||||
this.clonersWithoutId = clonersWithoutId;
|
||||
|
@ -377,16 +357,10 @@ public class DeepCloner {
|
|||
@SuppressWarnings("unchecked")
|
||||
Function<DeepCloner, V> c = (Function<DeepCloner, V>) getFromClassRespectingHierarchy(this.constructors, clazz);
|
||||
if (c == null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Supplier<V> s = (Supplier<V>) getFromClassRespectingHierarchy(this.parameterlessConstructors, clazz);
|
||||
if (s == null) {
|
||||
try {
|
||||
res = clazz.newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
res = null;
|
||||
}
|
||||
} else {
|
||||
res = s.get();
|
||||
try {
|
||||
res = clazz.newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
res = null;
|
||||
}
|
||||
} else {
|
||||
res = c.apply(this);
|
||||
|
|
|
@ -80,10 +80,10 @@ public class ConcurrentHashMapStorageProviderFactory implements AmphibianProvide
|
|||
|
||||
private final static DeepCloner CLONER = new DeepCloner.Builder()
|
||||
.genericCloner(Serialization::from)
|
||||
.constructorDC(MapClientEntityImpl.class, MapClientEntityImpl::new)
|
||||
.constructor(MapProtocolMapperEntity.class, MapProtocolMapperEntityImpl::new)
|
||||
.constructorDC(MapGroupEntityImpl.class, MapGroupEntityImpl::new)
|
||||
.constructorDC(MapRoleEntityImpl.class, MapRoleEntityImpl::new)
|
||||
.constructor(MapClientEntityImpl.class, MapClientEntityImpl::new)
|
||||
.constructor(MapProtocolMapperEntity.class, MapProtocolMapperEntityImpl::new)
|
||||
.constructor(MapGroupEntityImpl.class, MapGroupEntityImpl::new)
|
||||
.constructor(MapRoleEntityImpl.class, MapRoleEntityImpl::new)
|
||||
.build();
|
||||
|
||||
private static final Map<String, StringKeyConvertor> KEY_CONVERTORS = new HashMap<>();
|
||||
|
|
|
@ -38,7 +38,7 @@ import static org.keycloak.models.map.common.DeepCloner.DUMB_CLONER;
|
|||
public class MapClientEntityClonerTest {
|
||||
|
||||
private final static DeepCloner CLONER = new DeepCloner.Builder()
|
||||
.constructorDC(MapClientEntityImpl.class, MapClientEntityImpl::new)
|
||||
.constructor(MapClientEntityImpl.class, MapClientEntityImpl::new)
|
||||
.constructor(MapProtocolMapperEntity.class, MapProtocolMapperEntityImpl::new)
|
||||
.build();
|
||||
|
||||
|
|
Loading…
Reference in a new issue