liquibase.serializer.ReflectionSerializer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of liquibase-core Show documentation
Show all versions of liquibase-core Show documentation
Liquibase is a tool for managing and executing database changes.
package liquibase.serializer;
import liquibase.exception.UnexpectedLiquibaseException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class ReflectionSerializer {
private static final ReflectionSerializer instance = new ReflectionSerializer();
public static ReflectionSerializer getInstance() {
return instance;
}
private final Map> reflectionCache = new ConcurrentHashMap<>();
private ReflectionSerializer() {
}
public Set getFields(Object object) {
if (!reflectionCache.containsKey(object.getClass())) {
Map fields = new HashMap<>();
Set allFields = new HashSet<>();
Class> classToExtractFieldsFrom = object.getClass();
while (!classToExtractFieldsFrom.equals(Object.class)) {
allFields.addAll(Arrays.asList(classToExtractFieldsFrom.getDeclaredFields()));
classToExtractFieldsFrom = classToExtractFieldsFrom.getSuperclass();
}
for (Field field : allFields) {
if ("serialVersionUID".equals(field.getName()) || "serializableFields".equals(field.getName())) {
continue;
}
if (field.isSynthetic() || "$VRc".equals(field.getName())) { //from emma
continue;
}
fields.put(field.getName(), field);
field.setAccessible(true);
}
reflectionCache.put(object.getClass(), fields);
}
return reflectionCache.get(object.getClass()).keySet();
}
private Field findField(Object object, String field) {
Field foundField = null;
Class> classToCheck = object.getClass();
while ((foundField == null) && !classToCheck.equals(Object.class)) {
try {
foundField = classToCheck.getDeclaredField(field);
} catch (NoSuchFieldException e) {
classToCheck = classToCheck.getSuperclass();
}
}
if (foundField == null) {
throw new UnexpectedLiquibaseException("No field " + field + " on " + object.getClass());
}
return foundField;
}
public Object getValue(Object object, String field) {
if (!reflectionCache.containsKey(object.getClass())) {
getFields(object); //fills cache
}
Map fieldsByName = reflectionCache.get(object.getClass());
Field foundField = fieldsByName.get(field);
try {
if (foundField == null) {
foundField = findField(object, field);
foundField.setAccessible(true);
fieldsByName.put(field, foundField);
}
return foundField.get(object);
} catch (Exception e) {
throw new UnexpectedLiquibaseException(e);
}
}
public void setValue(Object object, String field, Object value) {
try {
Field foundField = findField(object, field);
foundField.setAccessible(true);
foundField.set(object, value);
} catch (Exception e) {
throw new UnexpectedLiquibaseException(e);
}
}
public Class getDataTypeClass(Object object, String field) {
try {
Field foundField = findField(object, field);
Type dataType = foundField.getGenericType();
if (dataType instanceof Class) {
return (Class) dataType;
}
if (dataType instanceof ParameterizedType) {
return (Class) ((ParameterizedType) dataType).getRawType();
}
return Object.class;
} catch (Exception e) {
throw new UnexpectedLiquibaseException(e);
}
}
public Type[] getDataTypeClassParameters(Object object, String field) {
try {
Field foundField = findField(object, field);
Type dataType = foundField.getGenericType();
if (dataType instanceof ParameterizedType) {
return ((ParameterizedType) dataType).getActualTypeArguments();
}
return new Type[0];
} catch (Exception e) {
throw new UnexpectedLiquibaseException(e);
}
}
}