Package org.fotap.heysync

Source Code of org.fotap.heysync.PublisherCreator

package org.fotap.heysync;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;

import java.lang.reflect.Method;
import java.util.List;

import static org.fotap.heysync.AsmHelper.*;
import static org.objectweb.asm.Opcodes.*;

/**
* @author <a href="mailto:peter.royal@pobox.com">peter royal</a>
*/
class PublisherCreator<T> extends ClassCreator<T> {
    private final List<Method> methods;

    PublisherCreator(Class<T> type, Type outputType, List<Method> methods) {
        super(type, outputType);
        this.methods = methods;
    }

    @Override
    protected void createFields() {
        writer.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, "SIGNAL", objectType.getDescriptor(), null, null)
                .visitEnd();

        for (int i = 0; i < methods.size(); i++) {
            createField(writer, methods.get(i), i);
        }
    }

    private void createField(ClassWriter writer, Method method, int index) {
        writer.visitField(ACC_PRIVATE + ACC_FINAL,
                fieldNameFor(method, index),
                publisherType.getDescriptor(),
                //Could put the generic signature... "Lorg/jetlang/channels/Publisher<Ljava/lang/String;>;",
                null,
                null)
                .visitEnd();
    }

    @Override
    protected void createConstructor() {
        constructorForPublishers();
        staticInitializer();
    }

    private void staticInitializer() {
        GeneratorAdapter adapter = method(ACC_STATIC, asmMethod("void <clinit> ()"));
        adapter.newInstance(objectType);
        adapter.dup();
        adapter.invokeConstructor(objectType, defaultConstructor);
        adapter.putStatic(outputType(), "SIGNAL", objectType);
        adapter.returnValue();
        adapter.endMethod();
    }

    private void constructorForPublishers() {
        GeneratorAdapter adapter = method(ACC_PUBLIC, asmConstructorMethod(methods.size()));
        adapter.loadThis();
        adapter.invokeConstructor(objectType, defaultConstructor);
        int arg = 0;

        for (int i = 0; i < methods.size(); i++) {
            adapter.loadThis();
            adapter.loadArg(arg++);
            adapter.putField(outputType(), fieldNameFor(methods.get(i), i), publisherType);
        }

        adapter.returnValue();
        adapter.endMethod();
    }

    private org.objectweb.asm.commons.Method asmConstructorMethod(int parameters) {
        StringBuilder builder = new StringBuilder().append("void <init> (");

        for (int i = 0; i < parameters; i++) {
            builder.append(publisherType.getClassName()).append(",");
        }

        builder.deleteCharAt(builder.length() - 1).append(")");
        return org.objectweb.asm.commons.Method.getMethod(builder.toString());
    }

    @Override
    protected void implementMethods() {
        for (int i = 0; i < methods.size(); i++) {
            implement(methods.get(i), i);
        }
    }

    private void implement(Method method, int index) {
        GeneratorAdapter adapter = method(ACC_PUBLIC, asmMethod(method));
        adapter.loadThis();
        adapter.getField(outputType(), fieldNameFor(method, index), publisherType);
        loadMessage(method, adapter);
        adapter.invokeInterface(publisherType, publishMethod);
        adapter.returnValue();
        adapter.endMethod();
    }

    private void loadMessage(Method method, GeneratorAdapter adapter) {
        Class<?>[] paramTypes = method.getParameterTypes();
        if (paramTypes.length > 1) {
            // Convert all method args into Object[] and push on to stack.
            adapter.loadArgArray();
        } else if (paramTypes.length == 1) {
            adapter.loadArg(0);
            Class<?> paramType = method.getParameterTypes()[0];
            if (paramType.isPrimitive()) {
                adapter.box(Type.getType(paramType));
            }
        } else {
            adapter.getStatic(outputType(), "SIGNAL", objectType);
        }
    }

    private String fieldNameFor(Method method, int index) {
        return method.getName() + "Publisher" + index;
    }
}
TOP

Related Classes of org.fotap.heysync.PublisherCreator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.