package com.feedly.cassandra.entity;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.BitSet;
import me.prettyprint.cassandra.serializers.CharSerializer;
import me.prettyprint.cassandra.serializers.ObjectSerializer;
import me.prettyprint.cassandra.serializers.SerializerTypeInferer;
import me.prettyprint.hector.api.Serializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.feedly.cassandra.entity.enhance.IEnhancedEntity;
public class EntityUtils
{
private static final Logger _logger = LoggerFactory.getLogger(EntityUtils.class.getName());
public static final boolean modifiersOk(Method method)
{
int m = method.getModifiers();
return Modifier.isPublic(m) && !Modifier.isStatic(m)
&& !Modifier.isAbstract(m);
}
public static final void initBitSet(Object o)
{
if(o instanceof IEnhancedEntity)
{
((IEnhancedEntity) o).setModifiedFields(new BitSet());
}
}
static boolean isBeanMethod(Method method)
{
if(!modifiersOk(method))
{
_logger.trace("invalid modifiers ", new Object[] { method.getModifiers(), ". excluding ", method.getName()});
return false;
}
if(method.getName().length() <= 3)
{
_logger.trace("method name == get. cannot infer property name. excluding ", method.getName());
return false;
}
if(method.getDeclaringClass().getPackage().getName().startsWith("java."))
{
_logger.trace("method declared by java class. excluding ", method.getName());
return false;
}
return true;
}
public static final boolean isValidSetter(Method setter)
{
if(!setter.getName().startsWith("set"))
{
_logger.trace("not a setter. excluding ", setter.getName());
return false;
}
if(!setter.getReturnType().equals(void.class))
{
_logger.trace("return value present. excluding ", setter.getName());
return false;
}
if(setter.getParameterTypes().length != 1)
{
_logger.trace("#parameters != 1. excluding ", setter.getName());
return false;
}
if(!isBeanMethod(setter))
return false;
return true;
}
static boolean isValidGetter(Method getter)
{
if(!getter.getName().startsWith("get"))
{
_logger.trace("not a getter. excluding ", getter.getName());
return false;
}
if(getter.getParameterTypes().length > 0)
{
_logger.trace("#parameters != 0. excluding ", getter.getName());
return false;
}
if(!isBeanMethod(getter))
return false;
return true;
}
public static Serializer<?> getSerializer(Class<?> type)
{
Serializer<?> s = SerializerTypeInferer.getSerializer(type);
if(s == null && type.equals(char.class))
s = CharSerializer.get();
if(s == null && (type.equals(Serializable.class) || type.isEnum()))
return ObjectSerializer.get();
return s;
}
public static boolean nullSafeEquals(Object o1, Object o2)
{
if(o1 == o2)
return true;
if(o1 == null || o2 == null)
return false;
return o1.equals(o2);
}
//not efficient, should be used only in exceptional cases
public static boolean beanFieldsEqual(Object o1, Object o2)
{
if(!o1.getClass().equals(o2.getClass()))
return false;
for(Field f : o1.getClass().getDeclaredFields())
{
try
{
f.setAccessible(true);
if(!f.getName().equals("__modifiedFields") &&
!f.getName().equals("__unmappedModified") &&
!nullSafeEquals(f.get(o1), f.get(o2)))
{
return false;
}
}
catch(Exception e)
{
return false;
}
}
return true;
}
}