org.simpleflatmapper.reflect.meta.MapClassMeta Maven / Gradle / Ivy
package org.simpleflatmapper.reflect.meta;
import org.simpleflatmapper.converter.ContextFactory;
import org.simpleflatmapper.converter.ConverterService;
import org.simpleflatmapper.converter.DefaultContextFactoryBuilder;
import org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition;
import org.simpleflatmapper.reflect.InstantiatorDefinition;
import org.simpleflatmapper.reflect.ReflectionService;
import org.simpleflatmapper.util.Consumer;
import org.simpleflatmapper.util.Predicate;
import org.simpleflatmapper.util.TypeHelper;
import org.simpleflatmapper.converter.ContextualConverter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class MapClassMeta, K, V> implements ClassMeta {
private final ReflectionService reflectionService;
private final ContextualConverter keyConverter;
private final ContextFactory keyContextFactory;
private final ClassMeta valueClassMeta;
private final Type type;
private final Constructor constructor;
public MapClassMeta(Type type, Type keyType, Type valueType, ReflectionService reflectionService) {
this.type = type;
DefaultContextFactoryBuilder contextFactoryBuilder = new DefaultContextFactoryBuilder();
this.keyConverter = ConverterService.getInstance().findConverter(CharSequence.class, keyType, contextFactoryBuilder);
this.keyContextFactory = contextFactoryBuilder.build();
this.reflectionService = reflectionService;
this.valueClassMeta = reflectionService.getClassMeta(valueType);
this.constructor = getConstructor(type);
}
public MapClassMeta(ReflectionService reflectionService, ContextualConverter keyConverter, ContextFactory keyContextFactory, ClassMeta valueClassMeta, Type type, Constructor constructor) {
this.reflectionService = reflectionService;
this.keyConverter = keyConverter;
this.keyContextFactory = keyContextFactory;
this.valueClassMeta = valueClassMeta;
this.type = type;
this.constructor = constructor;
}
@Override
public ClassMeta withReflectionService(ReflectionService reflectionService) {
return new MapClassMeta(reflectionService, keyConverter, keyContextFactory, reflectionService.getClassMeta(valueClassMeta.getType()), type, constructor);
}
private Constructor getConstructor(Type type) {
Class implClass = findMapImpl(type);
try {
return implClass.getDeclaredConstructor();
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("No empty constructor for " + implClass);
}
}
private Class findMapImpl(Type type) {
Class clazz = TypeHelper.toClass(type);
if (clazz.isInterface()) {
if (Map.class.equals(clazz)) {
return HashMap.class;
} else if(ConcurrentMap.class.equals(clazz)) {
return ConcurrentHashMap.class;
}
} else if (!Modifier.isAbstract(clazz.getModifiers())) {
return clazz;
}
throw new IllegalArgumentException("No known Map impl for " + type);
}
@Override
public ReflectionService getReflectionService() {
return reflectionService;
}
@Override
public PropertyFinder newPropertyFinder() {
return new MapPropertyFinder(this, valueClassMeta, keyConverter, keyContextFactory, reflectionService.selfScoreFullName());
}
@Override
public Type getType() {
return type;
}
@Override
public List getInstantiatorDefinitions() {
return Arrays.asList(new ExecutableInstantiatorDefinition(constructor));
}
@Override
public void forEachProperties(Consumer> consumer) {
throw new UnsupportedOperationException("Cannot list properties as non static");
}
@Override
public int getNumberOfProperties() {
return 10000;
}
@Override
public boolean needTransformer() {
return false;
}
}