DataReprezTools.java
package eu.javaexperience.datareprez;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import eu.javaexperience.collection.map.BulkTransitMap;
import eu.javaexperience.collection.map.SmallMap;
import eu.javaexperience.datareprez.convertFrom.ClassObjectLike;
import eu.javaexperience.datareprez.convertFrom.DataWrapper;
import eu.javaexperience.datareprez.convertFrom.ModifiableObject;
import eu.javaexperience.exceptions.UnimplementedCaseException;
import eu.javaexperience.interfaces.ObjectWithProperty;
import eu.javaexperience.reflect.Mirror;
import eu.javaexperience.reflect.Mirror.BelongTo;
import eu.javaexperience.reflect.Mirror.FieldSelector;
import eu.javaexperience.reflect.Mirror.Select;
import eu.javaexperience.reflect.Mirror.Visibility;
import eu.javaexperience.reflect.NotatedCaster;
public class DataReprezTools
{
public static Class<?> put(DataArray arr,Object o)
{
return put(arr, arr.size(), o);
}
public static final String[] emptyStringArray = new String[0];
public static Class<?> put(DataArray arr, int i, Object o)
{
return put(null, arr, i, o);
}
/**
* vissztaért hogy milyen tipussal sikerült eltárolni az értéket.
* Void.class ha a megadott érték null volt.
* nullal tér vissza ha nem sikerült eltenni.
* DataObject.class - adatobjektum
* DataArray.class - adattömb
*
* Összes:
* Void.class
* String.class
* Long.class
* Integer.class
* Double.class
* Boolean.class
* DataObject.class
* DataArray.class
* Float.class (double)
* Character.class (String)
* Short.class (int)
* Byte.class (int)
* */
public static Class<?> put(DataWrapper dw, DataArray arr, int i, Object o)
{
if(o == null)
{
arr.putNull(i);
return Void.class;
}
else if(o instanceof String)
{
arr.putString(i,((String)o));
return String.class;
}
else if(o instanceof Long)
{
arr.putLong(i,((Long)o).longValue());
return Long.class;
}
else if(o instanceof Integer)
{
arr.putInt(i,((Integer)o).intValue());
return Integer.class;
}
if(o instanceof Double)
{
arr.putDouble(i,((Double)o).doubleValue());
return Double.class;
}
else if(o instanceof byte[])
{
arr.putBlob(i,(byte[]) o);
return byte[].class;
}
else if(o instanceof Boolean)
{
arr.putBoolean(i,(Boolean) o);
return Boolean.class;
}
else if(o instanceof DataObject)
{
if(arr.getCommonsClass().isAssignableFrom(((DataObject) o).getCommonsClass()))
{
arr.putObject(i,(DataObject)o);
}
else
{
DataObject dobj = ((DataObject) o).newObjectInstance();
DataReprezTools.copyInto(dobj, (DataObject)o);
arr.putObject(i, dobj);
}
return DataObject.class;
}
else if(o instanceof DataArray)
{
if(arr.getCommonsClass().isAssignableFrom(((DataArray) o).getCommonsClass()))
{
arr.putArray(i,(DataArray)o);
}
else
{
DataArray darr = ((DataArray) o).newArrayInstance();
DataReprezTools.copyInto(darr, (DataArray)o);
arr.putArray(i, darr);
}
return DataArray.class;
}
else if(o instanceof Float)
{
arr.putDouble(i,((Float)o).doubleValue());
return Float.class;
}
else if(o instanceof Character)
{
arr.putString(i,new String(new char[]{((Character)o)}));
return Character.class;
}
else if(o instanceof Short)
{
arr.putInt(i,((Short)o).intValue());
return Short.class;
}
else if(o instanceof Byte)
{
arr.putInt(i,((Byte)o).intValue());
return Byte.class;
}
if(null != dw)
{
Object wrap = dw.wrap(dw, arr, o);
if(null != wrap)
{
return put(dw, arr, i, wrap);
}
}
return null;
}
public static Class<?> put(DataObject obj,String key,Object o)
{
return put(null, obj, key, o);
}
/**
* Returns with the class of the stored object.
* Returns null when the types is not stored.
*
* All retunting types:
* Void.class (when null given)
* String.class
* Character.class
* Long.class
* Date.class
* Integer.class
* Byte.class
* Short.class
* Double.class
* Float.class
* Boolean.class
* DataObject.class
* DataArray.class
* */
public static Class<?> put(DataWrapper dw, DataObject obj, String key, Object o)
{
if(o == null)
{
obj.putNull(key);
return Void.class;
}
else if(o instanceof String)
{
obj.putString(key,((String)o));
return String.class;
}
else if(o instanceof Long)
{
obj.putLong(key,((Long)o).longValue());
return Long.class;
}
else if(o instanceof Integer)
{
obj.putInt(key,((Integer)o).intValue());
return Integer.class;
}
if(o instanceof Double)
{
obj.putDouble(key,((Double)o).doubleValue());
return Double.class;
}
else if(o instanceof byte[])
{
obj.putBlob(key,(byte[]) o);
return byte[].class;
}
else if(o instanceof Boolean)
{
obj.putBoolean(key,(Boolean) o);
return Boolean.class;
}
else if(o instanceof DataObject)
{
if(obj.getClass().isAssignableFrom(o.getClass()))
{
obj.putObject(key,(DataObject)o);
}
else
{
DataObject dobj = ((DataObject) o).newObjectInstance();
DataReprezTools.copyInto(dobj, (DataObject)o);
obj.putObject(key, dobj);
}
return DataObject.class;
}
else if(o instanceof DataArray)
{
if(obj.getClass().isAssignableFrom(o.getClass()))
{
obj.putArray(key,(DataArray)o);
}
else
{
DataArray darr = ((DataArray) o).newArrayInstance();
DataReprezTools.copyInto(darr, (DataArray)o);
obj.putArray(key, darr);
}
return DataArray.class;
}
else if(o instanceof Float)
{
obj.putDouble(key,((Float)o).doubleValue());
return Float.class;
}
else if(o instanceof Character)
{
obj.putString(key,new String(new char[]{((Character)o)}));
return Character.class;
}
else if(o instanceof Short)
{
obj.putInt(key,((Short)o).intValue());
return Short.class;
}
else if(o instanceof Byte)
{
obj.putInt(key,((Byte)o).intValue());
return Byte.class;
}
else if(o instanceof Date)
{
obj.putLong(key,((Date)o).getTime());
return Long.class;
}
else if(o.getClass().isArray())
{
DataArray arr = obj.newArrayInstance();
for(int i=0;i<Array.getLength(o);++i)
{
DataReprezTools.put(dw, arr, i, Array.get(o, i));
}
obj.putArray(key, arr);
return DataArray.class;
}
else if(o instanceof Collection)
{
Collection c = (Collection) o;
DataArray arr = obj.newArrayInstance();
int i = 0;
for(Object add:c)
{
DataReprezTools.put(dw, arr, i++, add);
}
obj.putArray(key, arr);
return DataArray.class;
}
if(null != dw)
{
Object wrap = dw.wrap(dw, obj, o);
if(null != wrap)
{
return put(dw, obj, key, wrap);
}
}
return null;
}
public static Class<?> isStorable(Object o)
{
if(o == null)
return Void.class;
else if(o instanceof String)
return String.class;
else if(o instanceof Long)
return Long.class;
else if(o instanceof Integer)
return Integer.class;
if(o instanceof Double)
return Double.class;
else if(o instanceof byte[])
return byte[].class;
else if(o instanceof Boolean)
return Boolean.class;
else if(o instanceof DataObject)
return DataObject.class;
else if(o instanceof DataArray)
return DataArray.class;
else if(o instanceof Float)
return Float.class;
else if(o instanceof Character)
return Character.class;
else if(o instanceof Short)
return Short.class;
else if(o instanceof Byte)
return Byte.class;
else if(o instanceof Date)
return Long.class;
//else if(o.getClass().isArray())
// return DataArray.class;
return null;
}
public static Object extractToJavaPrimitiveTypes(Object any)
{
if(any instanceof ArrayLike)
{
DataArray arr = (DataArray) any;
Object[] ret = new Object[arr.size()];
for(int i=0;i<ret.length;++i)
{
ret[i] = extractToJavaPrimitiveTypes(arr.get(i));
}
return ret;
}
else if(any instanceof ObjectWithProperty)
{
ObjectWithProperty obj = (ObjectWithProperty) any;
Map<String, Object> ret = new SmallMap<>();
for(String k:obj.keys())
{
ret.put(k, extractToJavaPrimitiveTypes(obj.get(k)));
}
return ret;
}
return any;
}
public static Object wrapRecursively
(
DataWrapper wrapper,
DataCommon carrierPrototype,
Object toWrap
)
{
return wrapper.wrap(wrapper, carrierPrototype, toWrap);
}
public static DataWrapper combineWrappers(final DataWrapper... wrappers)
{
return new DataWrapper()
{
@Override
public DataCommon wrap(DataWrapper topWrapper, DataCommon prototype, Object o)
{
DataCommon ret = null;
for(DataWrapper w:wrappers)
{
ret = w.wrap(this, prototype, o);
if(null != ret)
{
return ret;
}
}
return null;
}
};
}
public static DataWrapper createClassInstanceWrapper(final FieldSelector select)
{
return createClassInstanceWrapper(select, null);
}
public static DataWrapper createClassInstanceWrapper(final FieldSelector select, final String classFieldName)
{
return new DataWrapper()
{
@Override
public DataCommon wrap
(
DataWrapper topWrapper,
DataCommon prototype,
Object o
)
{
try
{
BulkTransitMap<String, Object> values = new BulkTransitMap<String, Object>();
Mirror.extractFieldsToMap(o, values, select);
DataObject ret = prototype.newObjectInstance();
for(Entry<String, Object> kv:values.entrySet())
{
String key = kv.getKey();
Object val = kv.getValue();
if(null == put(topWrapper, ret, key, val))
{
put(topWrapper, ret, key, topWrapper.wrap(topWrapper, prototype, val));
}
}
if(null != classFieldName)
{
ret.putString(classFieldName, o.getClass().getSimpleName());
}
return ret;
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
};
}
public static final DataWrapper WRAP_ARRAY_COLLECTION_MAP = new DataWrapper()
{
@Override
public DataCommon wrap
(
DataWrapper topWrapper,
DataCommon transferDatatype,
Object in
)
{
//for arrays
if(in.getClass().isArray())
{
int len = Array.getLength(in);
//return Array.get(o, 0);
DataArray arr = transferDatatype.newArrayInstance();
for(int i=0;i<len;++i)
{
Object add = Array.get(in, i);
if(null == DataReprezTools.put(topWrapper, arr, i, add))
{
DataReprezTools.put(topWrapper, arr, i, topWrapper.wrap(topWrapper, transferDatatype, add));
}
}
return arr;
}
else if(in instanceof Collection)
{
Collection src = (Collection) in;
DataArray arr = transferDatatype.newArrayInstance();
int i = 0;
for(Object o: src)
{
if(null == DataReprezTools.put(topWrapper, arr, i++, o))
{
DataReprezTools.put(topWrapper, arr, i++, topWrapper.wrap(topWrapper, transferDatatype, o));
}
}
return arr;
}
else if(in instanceof Map)
{
Map<Object, Object> m = (Map) in;
DataObject ret = transferDatatype.newObjectInstance();
for(Entry<Object, Object> kv:m.entrySet())
{
if(null == DataReprezTools.put(topWrapper, ret, String.valueOf(kv.getKey()), kv.getValue()))
{
Object value = topWrapper.wrap(topWrapper, transferDatatype, kv.getValue());
DataReprezTools.put(topWrapper, ret, String.valueOf(kv.getKey()), value);
}
}
return ret;
}
return null;
}
};
public static final DataWrapper WRAP_DATA_LIKE = new DataWrapper()
{
@Override
public DataCommon wrap(DataWrapper dw, DataCommon prototype, Object o)
{
if(o instanceof DataLike)
{
DataLike in = (DataLike) o;
switch (in.getDataReprezType())
{
case ARRAY:
{
ArrayLike arr = (ArrayLike) in;
DataArray ret = prototype.newArrayInstance();
for(int i=0;i<arr.size();++i)
{
Object add = arr.get(i);
if(null == put(ret, i, add))
{
put(ret, i, dw.wrap(dw, prototype, add));
}
}
return ret;
}
case OBJECT:
case CLASS_OBJECT:
case RESOURCE:
{
ObjectWithProperty obj = (ObjectWithProperty) in;
DataObject ret = prototype.newObjectInstance();
for(String key:obj.keys())
{
Object w = obj.get(key);
//if(null != w)
{
if(null == put(ret, key, w))
{
put(ret, key, dw.wrap(dw, prototype, w));
}
}
}
if(obj instanceof ClassObjectLike)
{
ret.putString("class", ((ClassObjectLike) obj).getClassIdentifier());
}
return ret;
}
case NULL:
case PRIMITIVE:
return null;
default:
throw new UnimplementedCaseException(in.getDataReprezType());
}
}
return null;
}
};
public static final DataWrapper WRAP_OBJECT_WITH_PROPERTIES = new DataWrapper()
{
@Override
public DataCommon wrap(DataWrapper dw, DataCommon prototype, Object o)
{
if(o instanceof ObjectWithProperty)
{
ObjectWithProperty obj = (ObjectWithProperty) o;
DataObject ret = prototype.newObjectInstance();
for(String key:obj.keys())
{
Object w = obj.get(key);
{
if(null == put(ret, key, w))
{
put(ret, key, dw.wrap(dw, prototype, w));
}
}
}
}
return null;
}
};
public static final DataWrapper WRAP_ENUM = new DataWrapper()
{
@Override
public DataCommon wrap(DataWrapper topWrapper, DataCommon prototype, Object o)
{
/*
* A weird java behavior. This kind of enum check not always works:
* null != o && o.getClass().isEnum()
*
* public enum Something
* {
* A()
* {
* public String getStr()
* {
* return "A";
* }
* },
*
* B()
* {
* public String getStr()
* {
* return "B";
* }
* },
* ;
* public abstract String getStr();
* }
*
* - Something.A.getClass.isEnum() => false
* - Something.A instanceof Enum => true
*
* Because A and B implemented as an anonymous instance inside `Something`
* which is not and enum itself.
* - Something.A.getClass.toString() => Something$1
*/
if(o instanceof Enum)
{
DataObject ret = prototype.newObjectInstance();
ret.putString("name", ((Enum)o).name());
ret.putInt("ordinal", ((Enum)o).ordinal());
ret.putString("class", o.getClass().getName());
return ret;
}
return null;
}
};
public static final DataWrapper WRAP_CLASS__OBJECT_WITH_PROPERTY = new DataWrapper()
{
@Override
public DataCommon wrap(DataWrapper topWrapper, DataCommon prototype, Object o)
{
if(o instanceof ObjectWithProperty)
{
ObjectWithProperty owp = (ObjectWithProperty) o;
DataObject ret = prototype.newObjectInstance();
for(String s:owp.keys())
{
DataReprezTools.put(topWrapper, ret, s, owp.get(s));
}
return ret;
}
return null;
}
};
public static void copyInto(DataObject dst, ObjectWithProperty src)
{
for(String s:src.keys())
{
put(dst, s, src.get(s));
}
}
public static void copyInto(ModifiableObject dst, ObjectWithProperty src)
{
for(String s:src.keys())
{
dst.set(s, src.get(s));
}
}
public static void copyInto(DataArray dst, ArrayLike src)
{
int s = src.size();
for(int i=0;i<s;++i)
{
put(dst, i, src.get(i));
}
}
public static <T> T getAsOrThrow(DataObject obj, String key, NotatedCaster c)
{
Object ret = obj.get(key);
if(null == ret)
{
throw new RuntimeException("`"+key+"` key not found");
}
ret = c.cast(ret);
if(null == ret)
{
throw new RuntimeException("Can't cast `"+ret+"` to "+c.getTypeFullQualifiedName());
}
return (T) ret;
}
public static <T> T getAsOrThrow(DataArray arr, int index, NotatedCaster c)
{
Object ret = arr.get(index);
if(null == ret)
{
throw new RuntimeException(index+" index not fount");
}
ret = c.cast(ret);
if(null == ret)
{
throw new RuntimeException("Can't cast `"+ret+"` to "+c.getTypeFullQualifiedName());
}
return (T) ret;
}
public static final DataWrapper DATA_WRAPPER_BUILT_IN = DataReprezTools.combineWrappers
(
DataReprezTools.WRAP_ENUM,
DataReprezTools.WRAP_ARRAY_COLLECTION_MAP,
DataReprezTools.WRAP_DATA_LIKE,
DataReprezTools.WRAP_CLASS__OBJECT_WITH_PROPERTY,
DataReprezTools.createClassInstanceWrapper(new FieldSelector(true, Visibility.Public, BelongTo.Instance, Select.All, Select.IsNot, Select.All))
);
}