Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.simpleflatmapper.reflect.DefaultReflectionService Maven / Gradle / Ivy
package org.simpleflatmapper.reflect;
import org.simpleflatmapper.reflect.asm.AsmFactory;
import org.simpleflatmapper.reflect.asm.AsmInstantiatorDefinitionFactory;
import org.simpleflatmapper.reflect.impl.BuilderInstantiatorDefinitionFactory;
import org.simpleflatmapper.reflect.impl.ImmutableOrgHelper;
import org.simpleflatmapper.reflect.impl.JavaLangClassMetaFactoryProducer;
import org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition;
import org.simpleflatmapper.reflect.instantiator.InstantiatorDefinitions;
import org.simpleflatmapper.reflect.instantiator.KotlinDefaultConstructorInstantiatorDefinition;
import org.simpleflatmapper.reflect.meta.AliasProvider;
import org.simpleflatmapper.reflect.meta.AliasProviderService;
import org.simpleflatmapper.reflect.meta.ArrayClassMeta;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.reflect.meta.FastTupleClassMeta;
import org.simpleflatmapper.reflect.meta.MapClassMeta;
import org.simpleflatmapper.reflect.meta.ObjectClassMeta;
//IFJAVA8_START
import org.simpleflatmapper.reflect.meta.OptionalClassMeta;
//IFJAVA8_END
import java.util.*;
import org.simpleflatmapper.reflect.meta.PassThroughClassMeta;
import org.simpleflatmapper.reflect.meta.TupleClassMeta;
import org.simpleflatmapper.util.BiConsumer;
import org.simpleflatmapper.util.Consumer;
import org.simpleflatmapper.util.ProducerServiceLoader;
import org.simpleflatmapper.util.TupleHelper;
import org.simpleflatmapper.util.TypeHelper;
import org.simpleflatmapper.util.UnaryFactory;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static org.simpleflatmapper.util.Asserts.requireNonNull;
public class DefaultReflectionService extends ReflectionService {
private static final UnaryFactory>[] predefined =
getPredifinedClassMetaFactory();
private static final Consumer>>[] predefinedBuilderProducers =
getPredifinedBuilderProducers();
private final AliasProvider aliasProvider;
private final boolean builderIgnoresNullValues;
private final boolean selfScoreFullName;
private final ConcurrentMap> metaCache = new ConcurrentHashMap>();
private final ConcurrentMap> builderMethods = new ConcurrentHashMap>();
private final Map asmFactoryPerClassLoader;
private final boolean isAsmActivated;
public DefaultReflectionService(final AsmFactory asmFactory) {
this(
asmFactory != null,
defaultAsmFactortyPerClassLoader(asmFactory),
AliasProviderService.getAliasProvider(),
true, false);
}
private static Map defaultAsmFactortyPerClassLoader(AsmFactory asmFactory) {
Map map = new HashMap();
if (asmFactory != null)
map.put(asmFactory.targetClassLoader, asmFactory);
return map;
}
private DefaultReflectionService(boolean isAsmActivated,
Map asmFactoryPerClassLoader,
AliasProvider aliasProvider,
boolean builderIgnoresNullValues,
boolean selfScoreFullName) {
this.isAsmActivated = isAsmActivated;
this.asmFactoryPerClassLoader = asmFactoryPerClassLoader;
this.aliasProvider = aliasProvider;
this.builderIgnoresNullValues = builderIgnoresNullValues;
this.selfScoreFullName = selfScoreFullName;
initPredefined();
}
private void initPredefined() {
for (UnaryFactory> factory : predefined) {
ClassMeta classMeta = factory.newInstance(this);
metaCache.put(classMeta.getType(), classMeta);
}
for(Consumer>> factory : predefinedBuilderProducers) {
factory.accept(new BiConsumer>() {
@Override
public void accept(String s, UnaryFactory typeMemberUnaryFactory) {
builderMethods.put(s, typeMemberUnaryFactory);
}
});
}
}
@Override
public void registerClassMeta(Type type, ClassMeta classMeta) {
metaCache.put(type, classMeta);
}
@Override
public ObjectSetterFactory getObjectSetterFactory() {
return new ObjectSetterFactory(this);
}
@Override
public InstantiatorFactory getInstantiatorFactory() {
return new InstantiatorFactory(this);
}
@Override
public boolean isAsmActivated() {
return isAsmActivated;
}
@Override
public AsmFactory getAsmFactory(ClassLoader classLoader) {
if (classLoader == null) // system class loader override with sfm one
classLoader = getClass().getClassLoader();
if (!isAsmActivated) return null;
synchronized (asmFactoryPerClassLoader) {
AsmFactory asmFactory = asmFactoryPerClassLoader.get(classLoader);
if (asmFactory == null) {
asmFactory = new AsmFactory(classLoader);
asmFactoryPerClassLoader.put(classLoader, asmFactory);
}
return asmFactory;
}
}
@SuppressWarnings("unchecked")
@Override
public ClassMeta getClassMeta(Type target) {
requireNonNull("target", target);
ClassMeta meta = (ClassMeta) metaCache.get(target);
if (meta == null) {
meta = newClassMeta(target);
requireNonNull("meta", meta);
metaCache.putIfAbsent(target, meta);
}
return meta;
}
@SuppressWarnings("unchecked")
private ClassMeta newClassMeta(Type target) {
Class clazz = TypeHelper.toClass(target);
if (target instanceof WildcardType) {
Type[] upperBounds = ((WildcardType) target).getUpperBounds();
if (upperBounds.length == 1) {
target = upperBounds[0];
}
}
if (clazz.isArray()) {
return newArrayMeta(clazz);
//IFJAVA8_START
} else if (Optional.class.isAssignableFrom(clazz)) {
return new OptionalClassMeta(target, this);
//IFJAVA8_END
} else if (clazz.isAnnotationPresent(PassThrough.class)) {
return new PassThroughClassMeta(target, this);
} else if (TupleHelper.isTuple(target)) {
return new TupleClassMeta(target, this);
} else if (isFastTuple(clazz)) {
return new FastTupleClassMeta(target, this);
} else if (Map.class.isAssignableFrom(clazz)) {
return (ClassMeta) newMapMeta(target);
} else if (ArrayClassMeta.supports(target)) {
return newCollectionMeta(target);
}
if (isAbstractOrInterface(target)) {
target = findImplementation(target);
}
return new ObjectClassMeta(target, getBuilderInstantiator(target), this);
}
private boolean isAbstractOrInterface(Type target) {
Class clazz = TypeHelper.toClass(target);
return clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers());
}
private Type findImplementation(Type target) {
Class clazz = TypeHelper.toClass(target);
Type implementation;
implementation = ImmutableOrgHelper.findImplementation(clazz);
if (implementation != null) return implementation;
return target;
}
private Member getBuilderInstantiator(Type target) {
String typeName = TypeHelper.toClass(target).getName();
UnaryFactory builderSupplier = builderMethods.get(typeName);
if (builderSupplier != null) {
return builderSupplier.newInstance(target);
}
return null;
}
@Override
public ClassMeta getClassMetaExtraInstantiator(Type target, Member builderInstantiator) {
return new ObjectClassMeta(target, builderInstantiator, this);
}
private ClassMeta> newMapMeta(Type type) {
TypeHelper.MapEntryTypes types = TypeHelper.getKeyValueTypeOfMap(type);
return new MapClassMeta, K, V>(type, types.getKeyType(), types.getValueType(), this);
}
private ClassMeta newArrayMeta(Class clazz) {
return ArrayClassMeta.of(clazz, clazz.getComponentType(), this);
}
private ClassMeta newCollectionMeta(Type type) {
return ArrayClassMeta.of(type, TypeHelper.getComponentTypeOfListOrArray(type), this);
}
private boolean isFastTuple(Class clazz) {
Class superClass = clazz.getSuperclass();
return superClass != null && "com.boundary.tuple.FastTuple".equals(superClass.getName());
}
@Override
public String getColumnName(Method method) {
return aliasProvider.getAliasForMethod(method);
}
@Override
public String getColumnName(Field field) {
return aliasProvider.getAliasForField(field);
}
@Override
public List extractInstantiator(Type target, Member extraInstantiator) throws IOException {
List list;
if (!ReflectionInstantiatorDefinitionFactory.areParameterNamePresent(target)) {
try {
list = AsmInstantiatorDefinitionFactory.extractDefinitions(target);
} catch (IllegalArgumentException e) {
// byte code version issue
list = ReflectionInstantiatorDefinitionFactory.extractDefinitions(target);
} catch(IOException e) {
// no access to class file
list = ReflectionInstantiatorDefinitionFactory.extractDefinitions(target);
}
} else {
list = ReflectionInstantiatorDefinitionFactory.extractDefinitions(target);
}
if (TypeHelper.isKotlinClass(target)) {
kotlinReducationForDefaultValue(list);
}
if (extraInstantiator == null) {
list.addAll(BuilderInstantiatorDefinitionFactory.extractDefinitions(target));
if (list.isEmpty()) {
Class enclosing = TypeHelper.toClass(target).getEnclosingClass();
while (enclosing != null) {
for(Method m : enclosing.getDeclaredMethods()) {
if (Modifier.isPublic(m.getModifiers())
&& Modifier.isStatic(m.getModifiers())
&& TypeHelper.toClass(target).isAssignableFrom(m.getReturnType())) {
list.add(ReflectionInstantiatorDefinitionFactory.definition(m));
}
}
enclosing = enclosing.getEnclosingClass();
}
}
} else {
if (extraInstantiator instanceof Method && TypeHelper.areEquals(target, ((Method)extraInstantiator).getGenericReturnType())) {
// factory method
list.add(ReflectionInstantiatorDefinitionFactory.definition(((Method)extraInstantiator)));
} else {
final BuilderInstantiatorDefinition builder =
BuilderInstantiatorDefinitionFactory.getDefinitionForBuilder(extraInstantiator, target);
if (builder == null) {
throw new IllegalArgumentException("Could not find any setters or build method on builder " + extraInstantiator);
}
list.add(builder);
}
}
Collections.sort(list, InstantiatorDefinitions.COMPARATOR);
return list;
}
private void kotlinReducationForDefaultValue(List list) {
// look for potential kotlin default value
List potentialKotlinDefaultValue = kotlingDefaultValueConstructor(list);
if (potentialKotlinDefaultValue.isEmpty()) return;
// remove them from original list
list.removeAll(potentialKotlinDefaultValue);
// match them to non default constructor
for(int i = 0; i < potentialKotlinDefaultValue.size(); i++) {
ExecutableInstantiatorDefinition def = potentialKotlinDefaultValue.get(i);
for(int j = 0; j < list.size(); j++) {
InstantiatorDefinition id = list.get(j);
if (isKotlinOriginalConstructor(def, id)) {
list.set(j, new KotlinDefaultConstructorInstantiatorDefinition((ExecutableInstantiatorDefinition) id, def));
break;
}
}
}
}
private List kotlingDefaultValueConstructor(List list) {
List potentialKotlinDefaultValue = new ArrayList();
for(int i = 0; i < list.size(); i++) {
InstantiatorDefinition id = list.get(i);
if (id instanceof ExecutableInstantiatorDefinition &&
((ExecutableInstantiatorDefinition)id).getExecutable() instanceof Constructor) {
Constructor c = (Constructor) ((ExecutableInstantiatorDefinition)id).getExecutable();
if (c.isSynthetic()) {
Class[] parameterTypes = c.getParameterTypes();
if (parameterTypes[parameterTypes.length -1].getName().equals("kotlin.jvm.internal.DefaultConstructorMarker")) {
// got one
potentialKotlinDefaultValue.add((ExecutableInstantiatorDefinition) id);
}
}
}
}
return potentialKotlinDefaultValue;
}
private boolean isKotlinOriginalConstructor(ExecutableInstantiatorDefinition def, InstantiatorDefinition id) {
if (id instanceof ExecutableInstantiatorDefinition) {
ExecutableInstantiatorDefinition eid = (ExecutableInstantiatorDefinition) id;
if (eid.getExecutable() instanceof Constructor) {
int nbParams = eid.getParameters().length;
int syntheticParameters = (nbParams / Integer.SIZE) + 1 + /* DefaultConstructorMarker */ 1;
if (nbParams + syntheticParameters != def.getParameters().length) {
return false;
}
for(int i = 0; i < nbParams; i++) {
if (!def.getParameters()[i].getType().equals(id.getParameters()[i].getType())) {
return false;
}
}
for(int i = nbParams; i < nbParams + syntheticParameters - 1; i++ ) {
if (!def.getParameters()[i].getType().equals(int.class)) {
return false;
}
}
return true;
}
}
return false;
}
@Override
public ObjectGetterFactory getObjectGetterFactory() {
return new ObjectGetterFactory(this);
}
@Override
public DefaultReflectionService withAliasProvider(AliasProvider aliasProvider) {
return new DefaultReflectionService(
isAsmActivated, asmFactoryPerClassLoader,
aliasProvider, builderIgnoresNullValues, selfScoreFullName);
}
@Override
public DefaultReflectionService withBuilderIgnoresNullValues(boolean builderIgnoresNullValues) {
return new DefaultReflectionService(
isAsmActivated, asmFactoryPerClassLoader,
aliasProvider, builderIgnoresNullValues, selfScoreFullName);
}
@Override
public DefaultReflectionService withSelfScoreFullName(boolean selfScoreFullName) {
return new DefaultReflectionService(
isAsmActivated, asmFactoryPerClassLoader,
aliasProvider, builderIgnoresNullValues, selfScoreFullName);
}
@Override
public boolean builderIgnoresNullValues() {
return builderIgnoresNullValues;
}
@Override
public boolean selfScoreFullName() {
return selfScoreFullName;
}
@Override
public void registerBuilder(String name, DefaultBuilderSupplier defaultBuilderSupplier) {
builderMethods.put(name, defaultBuilderSupplier);
}
private static Consumer>>[] getPredifinedBuilderProducers() {
final List>>> list = new ArrayList>>>();
Consumer>>> consumer = new Consumer>>>() {
@Override
public void accept(Consumer>> biConsumerConsumer) {
list.add(biConsumerConsumer);
}
};
ProducerServiceLoader.produceFromServiceLoader(
ServiceLoader.load(BuilderProducer.class),
consumer
);
consumer.accept(new Consumer>>() {
@Override
public void accept(BiConsumer> biConsumer) {
biConsumer.accept("javax.money.MonetaryAmount",
new DefaultBuilderSupplier("javax.money.Monetary", "getDefaultAmountFactory"));
}
});
return list.toArray(new Consumer[0]);
}
@SuppressWarnings("unchecked")
private static UnaryFactory>[] getPredifinedClassMetaFactory() {
final List>> list = new ArrayList>>();
Consumer>> consumer = new Consumer>>() {
@Override
public void accept(UnaryFactory> reflectionServiceClassMetaUnaryFactory) {
list.add(reflectionServiceClassMetaUnaryFactory);
}
};
new JavaLangClassMetaFactoryProducer().produce(consumer);
ProducerServiceLoader.produceFromServiceLoader(
ServiceLoader.load(ClassMetaFactoryProducer.class),
consumer
);
return list.toArray(new UnaryFactory[0]);
}
}