
com.bol.reflection.ReflectionCache Maven / Gradle / Ivy
package com.bol.reflection;
import com.bol.secure.Encrypted;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
public class ReflectionCache {
private static final Logger LOG = LoggerFactory.getLogger(ReflectionCache.class);
private static Map> cyclicClassReference = new ConcurrentReferenceHashMap<>();
public static List processDocument(Class objectClass) {
List result = cyclicClassReference.get(objectClass);
if (result != null) {
LOG.trace("cyclic reference found; {} is already mapped", objectClass.getName());
return result;
}
List nodes = new ArrayList<>();
cyclicClassReference.put(objectClass, nodes);
ReflectionUtils.doWithFields(objectClass, field -> {
String fieldName = field.getName();
try {
if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())) return;
if (field.isAnnotationPresent(Encrypted.class)) {
// direct @Encrypted annotation - crypt the corresponding field of BasicDbObject
nodes.add(new Node(fieldName, Collections.emptyList(), Node.Type.DIRECT));
} else {
Class> fieldType = field.getType();
Type fieldGenericType = field.getGenericType();
if (Collection.class.isAssignableFrom(fieldType)) {
List children = processParameterizedTypes(fieldGenericType);
if (!children.isEmpty()) nodes.add(new Node(fieldName, unwrap(children), Node.Type.LIST));
} else if (Map.class.isAssignableFrom(fieldType)) {
List children = processParameterizedTypes(fieldGenericType);
if (!children.isEmpty()) nodes.add(new Node(fieldName, unwrap(children), Node.Type.MAP));
} else {
// descending into sub-documents
List children = processDocument(fieldType);
if (!children.isEmpty()) nodes.add(new Node(fieldName, children, Node.Type.DOCUMENT));
}
}
} catch (Exception e) {
throw new IllegalArgumentException(objectClass.getName() + "." + fieldName, e);
}
});
return nodes;
}
static List processParameterizedTypes(Type type) {
if (type instanceof Class) {
List children = processDocument((Class) type);
if (!children.isEmpty()) return Collections.singletonList(new Node(null, children, Node.Type.DOCUMENT));
} else if (type instanceof ParameterizedType) {
ParameterizedType subType = (ParameterizedType) type;
Class rawType = (Class) subType.getRawType();
if (Collection.class.isAssignableFrom(rawType)) {
List children = processParameterizedTypes(subType.getActualTypeArguments()[0]);
if (!children.isEmpty()) return Collections.singletonList(new Node(null, children, Node.Type.LIST));
} else if (Map.class.isAssignableFrom(rawType)) {
List children = processParameterizedTypes(subType.getActualTypeArguments()[1]);
if (!children.isEmpty()) return Collections.singletonList(new Node(null, children, Node.Type.MAP));
} else throw new IllegalArgumentException("Unknown reflective raw type class " + rawType.getClass());
} else throw new IllegalArgumentException("Unknown reflective type class " + type.getClass());
return Collections.emptyList();
}
static List unwrap(List result) {
if (result.size() != 1) return result;
Node node = result.get(0);
if (node.fieldName != null) return result;
return node.children;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy