net.amygdalum.testrecorder.ConfigurableSerializerFacade Maven / Gradle / Ivy
package net.amygdalum.testrecorder;
import static java.lang.System.identityHashCode;
import static java.lang.reflect.Proxy.isProxyClass;
import static java.util.Arrays.asList;
import static net.amygdalum.testrecorder.util.Distinct.distinct;
import static net.amygdalum.testrecorder.util.Types.baseType;
import static net.amygdalum.testrecorder.util.Types.isLiteral;
import static net.amygdalum.testrecorder.util.Types.serializableOf;
import static net.amygdalum.testrecorder.values.SerializedLiteral.literal;
import static net.amygdalum.testrecorder.values.SerializedNull.nullInstance;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import net.amygdalum.testrecorder.profile.AgentConfiguration;
import net.amygdalum.testrecorder.profile.Classes;
import net.amygdalum.testrecorder.profile.Fields;
import net.amygdalum.testrecorder.profile.SerializationProfile;
import net.amygdalum.testrecorder.serializers.ArraySerializer;
import net.amygdalum.testrecorder.serializers.EnumSerializer;
import net.amygdalum.testrecorder.serializers.GenericSerializer;
import net.amygdalum.testrecorder.serializers.LambdaSerializer;
import net.amygdalum.testrecorder.serializers.ProxySerializer;
import net.amygdalum.testrecorder.serializers.SerializerFacade;
import net.amygdalum.testrecorder.types.AnalyzedObject;
import net.amygdalum.testrecorder.types.ContextSnapshot;
import net.amygdalum.testrecorder.types.MethodSignature;
import net.amygdalum.testrecorder.types.OverrideSerializer;
import net.amygdalum.testrecorder.types.Profile;
import net.amygdalum.testrecorder.types.SerializationException;
import net.amygdalum.testrecorder.types.SerializedInput;
import net.amygdalum.testrecorder.types.SerializedOutput;
import net.amygdalum.testrecorder.types.SerializedReferenceType;
import net.amygdalum.testrecorder.types.SerializedValue;
import net.amygdalum.testrecorder.types.Serializer;
import net.amygdalum.testrecorder.types.SerializerSession;
import net.amygdalum.testrecorder.util.IdentityWorkSet;
import net.amygdalum.testrecorder.util.Logger;
import net.amygdalum.testrecorder.values.SerializedNull;
public class ConfigurableSerializerFacade implements SerializerFacade {
private Map, Serializer>> serializers;
private ArraySerializer arraySerializer;
private EnumSerializer enumSerializer;
private LambdaSerializer lambdaSerializer;
private ProxySerializer proxySerializer;
private GenericSerializer genericSerializer;
private List classExclusions;
private List classFacades;
private List fieldExclusions;
private List fieldFacades;
public ConfigurableSerializerFacade(AgentConfiguration config) {
serializers = setupSerializers(config);
arraySerializer = new ArraySerializer();
enumSerializer = new EnumSerializer();
lambdaSerializer = new LambdaSerializer();
proxySerializer = new ProxySerializer();
genericSerializer = new GenericSerializer();
classExclusions = classExclusions(config);
classFacades = classFacades(config);
fieldExclusions = fieldExclusions(config);
fieldFacades = fieldFacades(config);
}
private static List classExclusions(AgentConfiguration config) {
List excluded = new ArrayList<>(config.loadConfiguration(SerializationProfile.class)
.getClassExclusions());
excluded.addAll(testrecorderClasses());
return excluded;
}
private static List classFacades(AgentConfiguration config) {
List facades = new ArrayList<>(config.loadConfiguration(SerializationProfile.class)
.getClassFacades());
facades.addAll(testrecorderClasses());
return facades;
}
private static List testrecorderClasses() {
return asList(
Classes.byDescription(SnapshotManager.class),
Classes.byDescription(ContextSnapshot.class),
Classes.byDescription(SerializerFacade.class),
Classes.byDescription(ConfigurableSerializerFacade.class),
Classes.byDescription(SerializerSession.class),
Classes.byDescription(DefaultSerializerSession.class),
Classes.byDescription(Profile.class),
Classes.byDescription(Logger.class),
Classes.byPackage("net.amygdalum.testrecorder.values"));
}
private static List fieldExclusions(AgentConfiguration config) {
List excluded = new ArrayList<>(config.loadConfiguration(SerializationProfile.class)
.getFieldExclusions());
return excluded;
}
private static List fieldFacades(AgentConfiguration config) {
List facades = new ArrayList<>(config.loadConfiguration(SerializationProfile.class)
.getFieldFacades());
return facades;
}
private static Map, Serializer>> setupSerializers(AgentConfiguration config) {
IdentityHashMap, Serializer>> serializers = new IdentityHashMap<>();
for (Serializer> serializer : config.loadConfigurations(Serializer.class)) {
for (Class> clazz : serializer.getMatchingClasses()) {
Serializer> existing = serializers.putIfAbsent(clazz, serializer);
if (existing != null) {
if (compare(serializer, existing) > 0) {
serializers.put(clazz, serializer);
}
}
}
}
return serializers;
}
private static int compare(Serializer> serializer1, Serializer> serializer2) {
OverrideSerializer[] overrides1 = serializer1.getClass().getDeclaredAnnotationsByType(OverrideSerializer.class);
OverrideSerializer[] overrides2 = serializer2.getClass().getDeclaredAnnotationsByType(OverrideSerializer.class);
if (Arrays.stream(overrides1)
.filter(o -> o.value() == serializer2.getClass())
.findAny()
.isPresent()) {
return 1;
} else if (Arrays.stream(overrides2)
.filter(o -> o.value() == serializer1.getClass())
.findAny()
.isPresent()) {
return -1;
} else {
return 0;
}
}
@Override
public SerializedValue serialize(Type type, Object object, SerializerSession session) {
SerializedValue serializedObject = session.ref(object, type);
if (serializedObject != null) {
return serializedObject;
}
if (isGround(object)) {
return createGround(type, object);
} else {
return createObject(serializableOf(type), object, session);
}
}
private SerializedValue createGround(Type type, Object object) {
if (object == null) {
SerializedNull nullInstance = nullInstance();
return nullInstance;
} else if (baseType(type).isPrimitive()) {
return literal(baseType(type), object);
} else {
return literal(object);
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private SerializedValue createObject(Type type, Object object, SerializerSession session) {
Profile serialization = session.log(type);
try {
IdentityWorkSet © 2015 - 2025 Weber Informatics LLC | Privacy Policy