package org.etk.orm.plugins.bean.type;
import java.lang.reflect.Type;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import org.etk.orm.api.annotations.SimpleType;
import org.etk.orm.plugins.bean.mapping.jcr.PropertyMetaType;
import org.etk.reflect.api.ClassTypeInfo;
import org.etk.reflect.api.TypeInfo;
import org.etk.reflect.api.TypeResolver;
import org.etk.reflect.api.annotation.AnnotationInfo;
import org.etk.reflect.api.annotation.AnnotationParameterInfo;
import org.etk.reflect.api.definition.ClassKind;
import org.etk.reflect.api.definition.LiteralKind;
import org.etk.reflect.core.AnnotationType;
import org.etk.reflect.core.TypeResolverImpl;
import org.etk.reflect.jlr.metadata.JLReflectionMetadata;
public class SimpleTypeResolver {
/** . */
static final TypeResolver<Type> typeDomain = TypeResolverImpl.create(JLReflectionMetadata.newInstance());
/** . */
private static final SimpleTypeResolver base;
/** . */
private static final EnumMap<LiteralKind, TypeInfo> literalWrappers;
static {
// The base mappings
SimpleTypeResolver _base = new SimpleTypeResolver(new HashMap<TypeInfo, PropertyTypeEntry>());
// Numeric
_base.add(SimpleTypeProviders.INTEGER.class);
_base.add(SimpleTypeProviders.LONG.class);
_base.add(SimpleTypeProviders.BOOLEAN.class);
_base.add(SimpleTypeProviders.FLOAT.class);
_base.add(SimpleTypeProviders.DOUBLE.class);
// String
_base.add(SimpleTypeProviders.STRING.class);
// Path
_base.add(SimpleTypeProviders.PATH.class);
// Name
_base.add(SimpleTypeProviders.NAME.class);
// Binary
_base.add(SimpleTypeProviders.BINARY.class);
_base.add(SimpleTypeProviders.BYTE_ARRAY.class);
// Date
_base.add(SimpleTypeProviders.DATE.class);
_base.add(SimpleTypeProviders.CALENDAR.class);
_base.add(SimpleTypeProviders.TIMESTAMP.class);
// Primitive unwrapping
EnumMap<LiteralKind, TypeInfo> _literalWrappers = new EnumMap<LiteralKind, TypeInfo>(LiteralKind.class);
_literalWrappers.put(LiteralKind.BOOLEAN, typeDomain.resolve(Boolean.class));
_literalWrappers.put(LiteralKind.INT, typeDomain.resolve(Integer.class));
_literalWrappers.put(LiteralKind.LONG, typeDomain.resolve(Long.class));
_literalWrappers.put(LiteralKind.FLOAT, typeDomain.resolve(Float.class));
_literalWrappers.put(LiteralKind.DOUBLE, typeDomain.resolve(Double.class));
//
base = _base;
literalWrappers = _literalWrappers;
}
/** . */
private final Map<TypeInfo, PropertyTypeEntry> typeMappings;
private SimpleTypeResolver(Map<TypeInfo, PropertyTypeEntry> typeMappings) {
this.typeMappings = typeMappings;
}
/**
* The default constructor.
*/
public SimpleTypeResolver() {
this(base);
}
/**
* Deep clone constructor.
*
* @param that that resolver to clone
*/
public SimpleTypeResolver(SimpleTypeResolver that) {
if (that == null) {
throw new NullPointerException();
}
//
HashMap<TypeInfo, PropertyTypeEntry> typeMappings = new HashMap<TypeInfo, PropertyTypeEntry>();
for (Map.Entry<TypeInfo, PropertyTypeEntry> entry : that.typeMappings.entrySet()) {
typeMappings.put(entry.getKey(), new PropertyTypeEntry(entry.getValue()));
}
//
this.typeMappings = typeMappings;
}
private synchronized <I, E> void add(Class<? extends SimpleTypeProvider<I, E>> provider) {
ClassTypeInfo bilto = (ClassTypeInfo)typeDomain.resolve(provider);
SimpleTypeMappingImpl<I> a = new SimpleTypeMappingImpl<I>(bilto);
PropertyTypeEntry existing = typeMappings.get(a.external);
if (existing == null) {
typeMappings.put(a.external, new PropertyTypeEntry(a));
} else {
existing.add(a);
}
}
public synchronized SimpleTypeMapping resolveType(TypeInfo typeInfo) {
return resolveType(typeInfo, null);
}
public synchronized SimpleTypeMapping resolveType(
TypeInfo typeInfo,
PropertyMetaType<?> propertyMT) {
SimpleTypeMapping jcrType = null;
if (typeInfo instanceof ClassTypeInfo) {
ClassTypeInfo cti = (ClassTypeInfo)typeInfo;
if (cti.getKind() == ClassKind.ENUM) {
jcrType = new EnumSimpleTypeMapping(cti);
}
}
//
if (jcrType == null) {
if (typeInfo instanceof org.etk.reflect.api.SimpleTypeInfo) {
org.etk.reflect.api.SimpleTypeInfo sti = (org.etk.reflect.api.SimpleTypeInfo)typeInfo;
if (sti.isPrimitive()) {
typeInfo = literalWrappers.get(sti.getLiteralType());
}
}
PropertyTypeEntry entry = typeMappings.get(typeInfo);
if (entry != null) {
if (propertyMT != null) {
jcrType = entry.get(propertyMT);
} else {
jcrType = entry.getDefault();
}
}
}
//
if (jcrType == null) {
if (typeInfo instanceof ClassTypeInfo) {
ClassTypeInfo cti = (ClassTypeInfo)typeInfo;
AnnotationType<AnnotationInfo, ClassTypeInfo> at = AnnotationType.get((ClassTypeInfo)typeDomain.resolve(SimpleType.class));
AnnotationInfo ai = cti.getDeclaredAnnotation(at);
if (ai != null) {
AnnotationParameterInfo param = ai.getParameter("value");
ClassTypeInfo abc = (ClassTypeInfo)param.getValue();
SimpleTypeMappingImpl vtii = new SimpleTypeMappingImpl(abc);
if (propertyMT != null && propertyMT != vtii.getPropertyMetaType()) {
throw new UnsupportedOperationException("todo " + vtii.getPropertyMetaType() + " " + propertyMT);
}
typeMappings.put(typeInfo, new PropertyTypeEntry(vtii));
jcrType = vtii;
}
}
}
//
return jcrType;
}
}