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

com.aitusoftware.proxygen.message.MessageFlyweightGenerator Maven / Gradle / Ivy

The newest version!
package com.aitusoftware.proxygen.message;

import com.aitusoftware.proxygen.common.Constants;
import com.aitusoftware.proxygen.common.MethodDescriptor;
import com.aitusoftware.proxygen.common.MethodDescriptorByReturnTypeSorter;
import com.aitusoftware.proxygen.common.ParameterDescriptor;
import com.aitusoftware.proxygen.common.Types;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.util.Arrays;
import java.util.List;

import static com.aitusoftware.proxygen.common.Types.getPrimitiveTypeSize;
import static com.aitusoftware.proxygen.common.Types.typeNameToType;

public final class MessageFlyweightGenerator
{
    private static final List REQUIRED_IMPORTS = Arrays.asList(
            "com.aitusoftware.transport.messaging.proxy.Decoder",
            "com.aitusoftware.transport.messaging.proxy.CoderCommon",
            "com.aitusoftware.transport.messaging.Sized",
            "java.nio.ByteBuffer"
    );

    public void generateFlyweight(
            final String packageName, final String className,
            final String interfaceName,
            final MethodDescriptor[] methods, final List imports,
            final Writer writer)
    {
        try
        {
            writer.append("package ").append(packageName).append(";\n\n");
            for (String _import : imports)
            {
                writer.append("import ").append(_import).append(";\n");
            }

            for (String _import : REQUIRED_IMPORTS)
            {
                writer.append("import ").append(_import).append(";\n");
            }

            writer.append("\n\npublic class ").append(className).
                    append(" implements ").append(interfaceName).
                    append(", ").append("Sized").
                    append(" {\n\n");
            writer.append("\tprivate ByteBuffer buffer;\n");
            writer.append("\tprivate int offset;\n\n");
            final StringBuilder resetBuilder = new StringBuilder();
            resetBuilder.append("\tpublic void reset(final ByteBuffer buffer) {\n").
                    append("\t\tthis.buffer = buffer;\n").
                    append("\t\tthis.offset = buffer.position();\n").
                    append("\t}\n\n");

            final StringBuilder lengthBuilder = new StringBuilder();
            lengthBuilder.append("\tpublic int length() {\n").
                    append("\t\t return ");

            final StringBuilder fieldBuilder = new StringBuilder();

            int paramOffset = 0;

            final StringBuilder charSequenceLengths = new StringBuilder();
            final StringBuilder lengthCachingMethods = new StringBuilder();
            final MethodDescriptor[] copy = new MethodDescriptor[methods.length];
            System.arraycopy(methods, 0, copy, 0, copy.length);
            Arrays.sort(copy, MethodDescriptorByReturnTypeSorter.INSTANCE);
            for (MethodDescriptor method : copy)
            {
                final MethodTranslator translator = new MethodTranslator(method.getName());
                final Class returnType = typeNameToType(method.getReturnType().getTypeName());
                if (Types.isPrimitive(returnType))
                {
                    lengthBuilder.append(getPrimitiveTypeSize(returnType)).
                            append(" + ");
                    writer.append("\tpublic ").append(method.getReturnType().getTypeName()).append(" ").
                            append(method.getName()).append("() {\n");

                    writer.append("\t\treturn ").append(bufferAccessFor(method.getReturnType(), paramOffset)).append("\n");
                    writer.append("\t}\n\n");
                    paramOffset += Types.getPrimitiveTypeSize(returnType);
                }
                else if (Types.isCharSequence(returnType))
                {
                    writer.append("\tpublic ").append(method.getReturnType().getTypeName()).append(" ").
                            append(method.getName()).append("() {\n");

                    writer.append("\t\treturn ").append("Decoder.decode").
                            append(Types.toMethodSuffix(method.getReturnType().getTypeName())).
                            append("At(buffer, offset + ").append(String.valueOf(paramOffset)).
                            append(charSequenceLengths).
                            append(", ").append(translator.fieldName).append(");").append("\n");
                    writer.append("\t}\n\n");

                    fieldBuilder.append("\tprivate final StringBuilder ").append(translator.fieldName).
                            append(" = new StringBuilder();\n");

                    lengthCachingMethods.append("\tprivate int _len_").append(translator.fieldName).append(" = -1;\n\n");
                    lengthCachingMethods.append("\tprivate int _calculateLengthOf").
                            append(Types.toMethodSuffix(translator.fieldName)).append("() {\n").
                            append("\t\tif (_len_").append(translator.fieldName).append(" == -1) {\n").
                            append("\t\t\t_len_").append(translator.fieldName).append(" = ");

                    lengthCachingMethods.append("CoderCommon.getSerialisedCharSequenceLengthAtOffset(buffer, offset + ").
                            append(String.valueOf(paramOffset)).
                            append(charSequenceLengths).
                            append(");\n\n");

                    lengthCachingMethods.append("\t\t}\n").append("\t\treturn _len_").append(translator.fieldName).append(";\n\t}\n");


                    lengthBuilder.append(" _calculateLengthOf").append(Types.toMethodSuffix(translator.fieldName)).append("() + ");
                    charSequenceLengths.append(" + _calculateLengthOf").append(Types.toMethodSuffix(translator.fieldName)).append("()");
                }
            }
            lengthBuilder.append("0;\n").append("\t}\n\n");

            writer.append("\tpublic ").append(interfaceName).append(" heapCopy() {\n");
            writer.append("\t\tfinal ").append(interfaceName).append(Constants.MESSAGE_BUILDER_SUFFIX);
            writer.append(" builder = new ").append(interfaceName).append(Constants.MESSAGE_BUILDER_SUFFIX).append("();\n");
            for (MethodDescriptor method : methods)
            {
                final MethodTranslator translator = new MethodTranslator(method.getName());
                writer.append("\t\tbuilder.").append(translator.setterName).append("(").
                        append(method.getName()).append("());\n");
            }
            writer.append("\t\treturn builder;\n");

            writer.append("\t}\n\n");

            writer.append(resetBuilder);
            writer.append(lengthBuilder);
            writer.append(fieldBuilder);
            writer.append(lengthCachingMethods);

            writer.append("}");
        }
        catch (IOException e)
        {
            throw new UncheckedIOException(e);
        }

    }

    private CharSequence bufferAccessFor(final ParameterDescriptor returnType, final int bufferOffset)
    {
        return "Decoder.decode" + Types.toMethodSuffix(returnType.getTypeName()) + "At(buffer, offset + " + bufferOffset + ");";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy