All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jfirer.fse.serializer.CompileObjectSerializer Maven / Gradle / Ivy

The newest version!
package com.jfirer.fse.serializer;

import com.jfirer.baseutil.reflect.ReflectUtil;
import com.jfirer.baseutil.smc.SmcHelper;
import com.jfirer.baseutil.smc.compiler.CompileHelper;
import com.jfirer.baseutil.smc.model.ClassModel;
import com.jfirer.baseutil.smc.model.FieldModel;
import com.jfirer.baseutil.smc.model.MethodModel;
import com.jfirer.fse.*;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CompileObjectSerializer extends CycleFlagSerializer implements FseSerializer
{
    private Output output;

    @Override
    public void init(Class type, SerializerFactory serializerFactory)
    {
        List entries    = new ArrayList();
        List allFields  = getAllFields(type);
        ClassModel  classModel = new ClassModel("output_" + type.getSimpleName());
        classModel.addImport(Helper.class);
        classModel.addImport(Fse.class);
        classModel.addInterface(Output.class);
        int count = 0;
        try
        {
            Method      serialize      = Output.class.getMethod("serialize", new Class[]{Object.class, InternalByteArray.class, FseContext.class, int.class});
            Method      deSerialize    = Output.class.getMethod("deSerialize", new Class[]{InternalByteArray.class, FseContext.class});
            MethodModel serializeModel = new MethodModel(serialize, classModel);
            serializeModel.setParamterNames(new String[]{"o", "byteArray", "fseContext", "depth"});
            MethodModel deSerializeModel = new MethodModel(deSerialize, classModel);
            deSerializeModel.setParamterNames(new String[]{"byteArray", "fseContext"});
            classModel.putMethodModel(serializeModel);
            classModel.putMethodModel(deSerializeModel);
            StringBuilder serializeBody   = new StringBuilder();
            StringBuilder deSerializeBody = new StringBuilder();
            String        referenceName   = SmcHelper.getReferenceName(type, classModel);
            serializeBody.append(referenceName).append(" _target = (").append(referenceName).append(")o;\r\n");
            deSerializeBody.append(referenceName).append(" _target =new ").append(referenceName).append("();\r\n");
            deSerializeBody.append("fseContext.collectObject(_target);\r\n");
            for (Field each : allFields)
            {
                if (isFieldGetAndSetMethodExist(each) == false)
                {
                    continue;
                }
                if (each.getType().isPrimitive())
                {
                    if (each.getType() == int.class)
                    {
                        serializeBody.append("byteArray.writeVarInt(_target.").append(buildGetMethodName(each)).append("());\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("(byteArray.readVarInt());\r\n");
                    }
                    else if (each.getType() == byte.class)
                    {
                        serializeBody.append("byteArray.put(_target.").append(buildGetMethodName(each)).append("());\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("(byteArray.get());\r\n");
                    }
                    else if (each.getType() == char.class)
                    {
                        serializeBody.append("byteArray.writeVarChar(_target.").append(buildGetMethodName(each)).append("());\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("(byteArray.readVarChar());\r\n");
                    }
                    else if (each.getType() == long.class)
                    {
                        serializeBody.append("byteArray.writeVarLong(_target.").append(buildGetMethodName(each)).append("());\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("(byteArray.readVarLong());\r\n");
                    }
                    else if (each.getType() == float.class)
                    {
                        serializeBody.append("byteArray.writeFloat(_target.").append(buildGetMethodName(each)).append("());\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("(byteArray.readFloat());\r\n");
                    }
                    else if (each.getType() == short.class)
                    {
                        serializeBody.append("byteArray.writeShort(_target.").append(buildGetMethodName(each)).append("());\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("(byteArray.readShort());\r\n");
                    }
                    else if (each.getType() == double.class)
                    {
                        serializeBody.append("byteArray.writeDouble(_target.").append(buildGetMethodName(each)).append("());\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("(byteArray.readDouble());\r\n");
                    }
                    else if (each.getType() == boolean.class)
                    {
                        serializeBody.append("if(_target.").append(buildGetMethodName(each)).append("()){\r\n");
                        serializeBody.append("byteArray.put((byte)0);\r\n");
                        serializeBody.append("}else{\r\n");
                        serializeBody.append("byteArray.put((byte)1);\r\n");
                        serializeBody.append("}\r\n");
                        deSerializeBody.append("if(byteArray.get()==0){\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("(true);\r\n");
                        deSerializeBody.append("}\r\n");
                        deSerializeBody.append("else{\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("(false);\r\n");
                        deSerializeBody.append("}\r\n");
                    }
                }
                else
                {
                    int modifiers = each.getType().getModifiers();
                    if (Modifier.isFinal(modifiers) || (Modifier.isAbstract(modifiers) == false && Modifier.isInterface(modifiers)))
                    {
                        FseSerializer serializer = serializerFactory.getSerializer(each.getType());
                        Entry         entry      = new Entry();
                        entry.serializerName = "_s_" + count;
                        count++;
                        entry.serializer = serializer;
                        FieldModel fieldModel = new FieldModel(entry.serializerName, FseSerializer.class, classModel);
                        classModel.addField(fieldModel);
                        MethodModel setMethod = new MethodModel(classModel);
                        setMethod.setAccessLevel(MethodModel.AccessLevel.PUBLIC);
                        setMethod.setReturnType(void.class);
                        setMethod.setMethodName("set" + entry.serializerName);
                        setMethod.setParamterTypes(FseSerializer.class);
                        setMethod.setBody(entry.serializerName + "=$0;\r\n");
                        classModel.putMethodModel(setMethod);
                        entries.add(entry);
                        String propertyName = "_value_" + count;
                        count++;
                        serializeBody.append("Object " + propertyName + " = _target." + buildGetMethodName(each) + "();\r\n");
                        serializeBody.append("if(" + propertyName + " == null ){byteArray.put(Fse.NULL);}");
                        if (Modifier.isFinal(modifiers))
                        {
                            serializeBody.append("else{\r\n");
                            serializeBody.append(entry.serializerName).append(".writeToBytes(").append(propertyName).append("," + Fse.USE_FIELD_TYPE + ",byteArray,fseContext,depth);\r\n");
                            serializeBody.append("}\r\n");
                        }
                        else
                        {
                            serializeBody.append("else if(" + propertyName + ".getClass()==" + SmcHelper.getReferenceName(each.getType(), classModel) + ".class){\r\n");
                            serializeBody.append(entry.serializerName).append(".writeToBytes(").append(propertyName).append("," + Fse.USE_FIELD_TYPE + ",byteArray,fseContext,depth);\r\n");
                            serializeBody.append("}\r\n");
                            serializeBody.append("else{\r\n");
                            serializeBody.append("fseContext.serialize(" + propertyName + ",byteArray,depth);\r\n");
                            serializeBody.append("}\r\n");
                        }
                        String flagName = "_flag_" + count;
                        count++;
                        deSerializeBody.append("int " + flagName + " = byteArray.readVarInt();\r\n");
                        deSerializeBody.append("if(" + flagName + "==0){\r\n_target.").append(buildSetMethodName(each)).append("(null);\r\n}\r\n");
                        deSerializeBody.append("else if(" + flagName + "==Fse.USE_FIELD_TYPE){\r\n");
                        deSerializeBody.append("_target." + buildSetMethodName(each) + "((" + SmcHelper.getReferenceName(each.getType(), classModel) + ")" + entry.serializerName).append(".readBytes(byteArray,fseContext));\r\n");
                        deSerializeBody.append("}\r\n");
                        deSerializeBody.append("else if(" + flagName + "<0){\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("((" + SmcHelper.getReferenceName(each.getType(), classModel) + ")fseContext.getObjectByIndex(0-" + flagName + "));\r\n");
                        deSerializeBody.append("}\r\n");
                        deSerializeBody.append("else{\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("((" + SmcHelper.getReferenceName(each.getType(), classModel) + ")fseContext.getClassRegistry(" + flagName + ").getSerializer().readBytes(byteArray,fseContext));\r\n");
                        deSerializeBody.append("}\r\n");
                    }
                    else
                    {
                        serializeBody.append("fseContext.serialize(_target." + buildGetMethodName(each) + "(),byteArray,depth);\r\n");
                        String flagName = "_flag_" + count;
                        count++;
                        deSerializeBody.append("int " + flagName + " = byteArray.readVarInt();\r\n");
                        deSerializeBody.append("if(" + flagName + "==0){\r\n_target.").append(buildSetMethodName(each)).append("(null);\r\n}\r\n");
                        deSerializeBody.append("else if(" + flagName + "<0){\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("((" + SmcHelper.getReferenceName(each.getType(), classModel) + ")fseContext.getObjectByIndex(0-" + flagName + "));\r\n");
                        deSerializeBody.append("}\r\n");
                        deSerializeBody.append("else{\r\n");
                        deSerializeBody.append("_target.").append(buildSetMethodName(each)).append("((" + SmcHelper.getReferenceName(each.getType(), classModel) + ")fseContext.getClassRegistry(" + flagName + ").getSerializer().readBytes(byteArray,fseContext));\r\n");
                        deSerializeBody.append("}\r\n");
                    }
                }
            }
            serializeModel.setBody(serializeBody.toString());
            deSerializeBody.append("return _target;\r\n");
            deSerializeModel.setBody(deSerializeBody.toString());
            CompileHelper compileHelper = new CompileHelper();
            Class      compile       = compileHelper.compile(classModel);
            output = (Output) compile.newInstance();
            for (Entry entry : entries)
            {
                Method setMethod = compile.getMethod("set" + entry.serializerName, FseSerializer.class);
                setMethod.invoke(output, entry.serializer);
            }
        }
        catch (Throwable e)
        {
            ReflectUtil.throwException(e);
        }
    }

    private boolean isFieldGetAndSetMethodExist(Field field)
    {
        String getMethodName = buildGetMethodName(field);
        String setMethodName = buildSetMethodName(field);
        try
        {
            field.getDeclaringClass().getDeclaredMethod(getMethodName);
            field.getDeclaringClass().getDeclaredMethod(setMethodName, field.getType());
            return true;
        }
        catch (NoSuchMethodException e)
        {
            return false;
        }
    }

    private String buildGetMethodName(Field field)
    {
        if (field.getType().isPrimitive())
        {
            if (field.getType() == boolean.class)
            {
                return "is" + field.getName().toUpperCase().substring(0, 1) + field.getName().substring(1);
            }
            else
            {
                return "get" + field.getName().toUpperCase().substring(0, 1) + field.getName().substring(1);
            }
        }
        else
        {
            return "get" + field.getName().toUpperCase().substring(0, 1) + field.getName().substring(1);
        }
    }

    private String buildSetMethodName(Field field)
    {
        return "set" + field.getName().toUpperCase().substring(0, 1) + field.getName().substring(1);
    }

    private List getAllFields(Class type)
    {
        List list = new ArrayList();
        while (type != Object.class)
        {
            for (Field each : type.getDeclaredFields())
            {
                if (each.isAnnotationPresent(FseIgnore.class))
                {
                    continue;
                }
                int modifiers = each.getModifiers();
                if (Modifier.isStatic(modifiers))
                {
                    continue;
                }
                list.add(each);
            }
            type = type.getSuperclass();
        }
        Collections.sort(list, new Comparator()
        {
            @Override
            public int compare(Field o1, Field o2)
            {
                return o1.toString().compareTo(o2.toString());
            }
        });
        return list;
    }

    @Override
    public void doWriteToBytes(Object o, InternalByteArray byteArray, FseContext fseContext, int depth)
    {
        output.serialize(o, byteArray, fseContext, depth);
    }

    @Override
    public Object readBytes(InternalByteArray byteArray, FseContext fseContext)
    {
        return output.deSerialize(byteArray, fseContext);
    }

    public static interface Output
    {
        void serialize(Object o, InternalByteArray byteArray, FseContext fseContext, int depth);

        Object deSerialize(InternalByteArray byteArray, FseContext fseContext);
    }

    class Entry
    {
        String        serializerName;
        FseSerializer serializer;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy