package com.feedly.cassandra.entity;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.UUID;
import me.prettyprint.hector.api.Serializer;
import com.feedly.cassandra.dao.CounterColumn;
public class PropertyMetadataFactory
{
public static final Set<Class<?>> PRIMITIVES;
public static final Set<String> PRIMITIVE_STRINGS;
static
{
Set<Class<?>> primitives = new HashSet<Class<?>>();
primitives.add(boolean.class);
primitives.add(Boolean.class);
primitives.add(byte.class);
primitives.add(byte.class);
primitives.add(char.class);
primitives.add(Character.class);
primitives.add(Date.class);
primitives.add(double.class);
primitives.add(Double.class);
primitives.add(float.class);
primitives.add(Float.class);
primitives.add(int.class);
primitives.add(Integer.class);
primitives.add(long.class);
primitives.add(Long.class);
primitives.add(short.class);
primitives.add(Short.class);
primitives.add(String.class);
primitives.add(UUID.class);
primitives.add(Object.class); //common super class for primitives
primitives.add(Number.class); //common super class for primitives
PRIMITIVES = Collections.unmodifiableSet(primitives);
Set<String> strings = new HashSet<String>();
for(Class<?> c : PRIMITIVES)
strings.add(c.getName());
PRIMITIVE_STRINGS = Collections.unmodifiableSet(strings);
}
public static SimplePropertyMetadata buildSimplePropertyMetadata(Field f,
String physicalName,
int ttl,
Method getter,
Method setter,
Class<? extends Serializer<?>> serializerClass,
boolean useCompositeKeySerializer)
{
PropertyMetadataBase pm = buildPropertyMetadata(f, physicalName, ttl, getter, setter, serializerClass, useCompositeKeySerializer);
try
{
return (SimplePropertyMetadata) pm;
}
catch(ClassCastException cce)
{
throw new IllegalArgumentException("expected simple type for " + physicalName + " but encountered " + f.getClass());
}
}
public static PropertyMetadataBase buildPropertyMetadata(Field f,
String physicalName,
int ttl,
Method getter,
Method setter,
Class<? extends Serializer<?>> serializerClass,
boolean useCompositeKeySerializer)
{
return buildPropertyMetadata(f.getName(), f.getGenericType(), f.getAnnotations(), physicalName, ttl, getter, setter, serializerClass, useCompositeKeySerializer);
}
public static PropertyMetadataBase buildPropertyMetadata(String name,
Type type,
Annotation[] annotations,
String physicalName,
int ttl,
Method getter,
Method setter,
Class<? extends Serializer<?>> serializerClass,
boolean useCompositeKeySerializer)
{
serializerClass = serializerClass(serializerClass);
if(type instanceof Class)
{
Class<?> clazz = (Class<?>) type;
if(isSimpleType(clazz) || clazz.equals(CounterColumn.class))
return new SimplePropertyMetadata(name, clazz, annotations, physicalName, ttl, getter, setter, serializerClass, useCompositeKeySerializer);
else
{
return new ObjectPropertyMetadata(name, clazz, annotations, physicalName, ttl, getter, setter);
}
}
else if(type instanceof ParameterizedType)
{
ParameterizedType ptype = (ParameterizedType) type;
Type rawType = ptype.getRawType();
if(Map.class.equals(rawType) || SortedMap.class.equals(rawType))
{
return new MapPropertyMetadata(name, ptype, annotations, SortedMap.class.equals(rawType), physicalName, ttl, getter, setter);
}
else if(List.class.equals(rawType))
{
return new ListPropertyMetadata(name, ptype, annotations, physicalName, ttl, getter, setter);
}
else
{
throw new IllegalArgumentException("collection type " + rawType + " not allowed, expected Map, SortedMap, or List.");
}
}
throw new IllegalArgumentException("type " + type + " not allowed");
}
private static Class<? extends Serializer<?>> serializerClass(Class<? extends Serializer<?>> value)
{
return Serializer.class.equals(value) ? null : value;
}
public static boolean isSimpleType(Field f)
{
return isSimpleType(f.getType());
}
public static boolean isPrimitiveType(String s)
{
return PRIMITIVE_STRINGS.contains(s);
}
public static boolean isSimpleType(Class<?> clazz)
{
if(clazz.isEnum())
return true;
return PRIMITIVES.contains(clazz);
}
}