net.sf.mmm.service.impl.gwt.rpc.client.rebind.RemoteInvocationServiceCallerGenerator.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.mmm.service.impl.gwt.rpc.client.rebind.RemoteInvocationServiceCallerGenerator.java

Source

/* Copyright (c) The m-m-m Team, Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0 */
package net.sf.mmm.service.impl.gwt.rpc.client.rebind;

import java.io.PrintWriter;
import java.io.Serializable;

import net.sf.mmm.service.api.rpc.RemoteInvocationService;
import net.sf.mmm.service.base.gwt.RemoteInvocationGenericServiceGwtAsync;
import net.sf.mmm.service.base.rpc.GenericRemoteInvocationRpcCall;
import net.sf.mmm.service.base.rpc.client.AbstractRemoteInvocationServiceClient;
import net.sf.mmm.service.impl.gwt.rpc.client.AbstractRemoteInvocationServiceCallerGwt;
import net.sf.mmm.util.exception.api.IllegalCaseException;
import net.sf.mmm.util.gwt.base.rebind.AbstractIncrementalGenerator;

import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

/**
 * This is the {@link AbstractIncrementalGenerator incremental GWT-generator} for generating the
 * {@link net.sf.mmm.service.api.rpc.client.RemoteInvocationServiceCaller} and according service-client stubs.
 * 
 * @author Joerg Hohwiller (hohwille at users.sourceforge.net)
 * @since 1.0.0
 */
// TODO hohwille Split off separate Generator for Service-Stub!
public class RemoteInvocationServiceCallerGenerator extends AbstractIncrementalGenerator {

    /**
     * The constructor.
     */
    public RemoteInvocationServiceCallerGenerator() {

        super();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getVersionId() {

        return 1;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void generateImportStatements(JClassType inputType, TreeLogger logger,
            ClassSourceFileComposerFactory sourceComposerFactory, GeneratorContext context) {

        sourceComposerFactory.addImport(RemoteInvocationService.class.getName());
        sourceComposerFactory.addImport(RemoteInvocationGenericServiceGwtAsync.class.getName());
        sourceComposerFactory.addImport(AbstractRemoteInvocationServiceCallerGwt.class.getName());
        // sourceComposerFactory.addImport(Inject.class.getName());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void generateClassDeclaration(JClassType inputType, TreeLogger logger,
            ClassSourceFileComposerFactory sourceComposerFactory, GeneratorContext context) {

        sourceComposerFactory.setSuperclass(AbstractRemoteInvocationServiceCallerGwt.class.getSimpleName());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void generateClassContents(JClassType inputType, TreeLogger logger, SourceWriter sourceWriter,
            String simpleName, GeneratorContext context) {

        generateSourcePublicConstructorDeclaration(sourceWriter, simpleName);

        // generate CDI constructor
        // sourceWriter.print("@");
        // sourceWriter.println(Inject.class.getSimpleName());
        // sourceWriter.print("public ");
        // sourceWriter.print(simpleName);
        // sourceWriter.print("(");
        // sourceWriter.print(RemoteInvocationGenericServiceGwtAsync.class.getSimpleName());
        // sourceWriter.print(" genericService");
        // sourceWriter.println(") {");
        // sourceWriter.indent();
        // sourceWriter.println("super(genericService);");

        // generate service clients and register in constructor...
        TypeOracle typeOracle = context.getTypeOracle();
        JClassType dabayServiceType = typeOracle.findType(RemoteInvocationService.class.getName());
        for (JClassType type : typeOracle.getTypes()) {
            if ((type.isAssignableTo(dabayServiceType)) && (!type.equals(dabayServiceType))
                    && (type.isInterface() != null)) {
                sourceWriter.print("registerService(");
                sourceWriter.print(type.getQualifiedSourceName());
                sourceWriter.print(".class, new ");
                sourceWriter.print(generateServiceClient(type, inputType.getPackage().getName(), logger, context));
                sourceWriter.println("());");
            }
        }
        generateSourceCloseBlock(sourceWriter);
    }

    /**
     * This method generates a service-client implementation of a {@link RemoteInvocationService}-interface
     * given by <code>serviceInterface</code>.
     * 
     * @param serviceInterface is the {@link RemoteInvocationService}-interface.
     * @param packageName is the {@link Package#getName() package name}.
     * @param logger is the {@link TreeLogger}.
     * @param context is the {@link GeneratorContext}.
     * @return the qualified name of the generated class.
     */
    protected String generateServiceClient(JClassType serviceInterface, String packageName, TreeLogger logger,
            GeneratorContext context) {

        String simpleName = serviceInterface.getName() + "ClientImpl";
        logger.log(TreeLogger.INFO, getClass().getSimpleName() + ": Generating " + simpleName);
        ClassSourceFileComposerFactory sourceComposerFactory = new ClassSourceFileComposerFactory(packageName,
                simpleName);

        // imports
        sourceComposerFactory.addImport(RemoteInvocationService.class.getName());
        sourceComposerFactory.addImport(Serializable.class.getName());
        sourceComposerFactory.addImport(GenericRemoteInvocationRpcCall.class.getName());
        sourceComposerFactory.addImport(AbstractRemoteInvocationServiceClient.class.getName());

        sourceComposerFactory.addImplementedInterface(serviceInterface.getQualifiedSourceName());
        sourceComposerFactory.setSuperclass(AbstractRemoteInvocationServiceClient.class.getSimpleName());
        PrintWriter writer = context.tryCreate(logger, packageName, simpleName);
        if (writer != null) {
            SourceWriter sourceWriter = sourceComposerFactory.createSourceWriter(context, writer);
            // generate constructor
            sourceWriter.print("public ");
            sourceWriter.print(simpleName);
            sourceWriter.println("() {");
            sourceWriter.indent();
            sourceWriter.println("super();");
            sourceWriter.outdent();
            sourceWriter.println("}");

            // generate service-interface methods to implement
            for (JMethod method : serviceInterface.getOverridableMethods()) {

                generateServiceClientMethod(serviceInterface, sourceWriter, method);
            }

            sourceWriter.commit(logger);
        }
        return sourceComposerFactory.getCreatedClassName();
    }

    /**
     * This method generates the implementation of a method for a service-client.
     * 
     * @param serviceInterface is the {@link RemoteInvocationService}-interface.
     * @param sourceWriter is the {@link SourceWriter}.
     * @param method is the {@link JMethod} to generate.
     */
    private void generateServiceClientMethod(JClassType serviceInterface, SourceWriter sourceWriter,
            JMethod method) {

        // generate method declaration...
        sourceWriter.print("public ");
        JType returnType = method.getReturnType();
        sourceWriter.print(returnType.getQualifiedSourceName());
        sourceWriter.print(" ");
        sourceWriter.print(method.getName());
        sourceWriter.print("(");
        String separator = "";
        JParameter[] parameters = method.getParameters();
        for (JParameter parameter : parameters) {
            if (separator.length() == 0) {
                separator = ", ";
            } else {
                sourceWriter.print(separator);
            }
            sourceWriter.print(parameter.getType().getQualifiedSourceName());
            sourceWriter.print(" ");
            sourceWriter.print(parameter.getName());
        }
        sourceWriter.println("){");

        // generate method body...
        sourceWriter.indent();

        // generate statement for argument array
        sourceWriter.print(Serializable.class.getSimpleName());
        sourceWriter.print("[] _arguments = new ");
        sourceWriter.print(Serializable.class.getSimpleName());
        sourceWriter.print("[");
        sourceWriter.print(Integer.toString(parameters.length));
        sourceWriter.println("];");

        String[] signatureArray = new String[parameters.length];
        // fill in arguments
        for (int i = 0; i < parameters.length; i++) {
            // assign argument statement
            JParameter parameter = parameters[i];
            sourceWriter.print("_arguments[");
            sourceWriter.print(Integer.toString(i));
            sourceWriter.print("] = ");
            sourceWriter.print(parameter.getName());
            sourceWriter.println(";");

            // assign argument type for signature
            signatureArray[i] = parameter.getType().getQualifiedSourceName();
        }

        // generate statement to create call
        sourceWriter.print(GenericRemoteInvocationRpcCall.class.getSimpleName());
        sourceWriter.print(" _call = new ");
        sourceWriter.print(GenericRemoteInvocationRpcCall.class.getSimpleName());
        sourceWriter.print("(");
        sourceWriter.print(serviceInterface.getQualifiedSourceName());
        sourceWriter.print(".class.getName(), \"");
        sourceWriter.print(method.getName());
        sourceWriter.print("\", ");
        sourceWriter.print(Integer.toString(GenericRemoteInvocationRpcCall.getSignature(signatureArray)));
        sourceWriter.println(", _arguments);");

        // add recorded call
        sourceWriter.print("addCall(_call, ");
        sourceWriter.print(returnType.getQualifiedSourceName());
        sourceWriter.println(".class);");

        // generate dummy return statement
        JPrimitiveType primitiveReturnType = returnType.isPrimitive();
        if (primitiveReturnType == null) {
            sourceWriter.println("return null;");
        } else {
            switch (primitiveReturnType) {
            case VOID:
                // nothing to return
                break;
            case BOOLEAN:
                sourceWriter.println("return false;");
                break;
            case BYTE:
            case DOUBLE:
            case FLOAT:
            case INT:
            case LONG:
            case SHORT:
                sourceWriter.println("return 0;");
                break;
            case CHAR:
                sourceWriter.println("return ' ';");
                break;
            default:
                throw new IllegalCaseException(JPrimitiveType.class, primitiveReturnType);
            }
        }
        sourceWriter.outdent();
        sourceWriter.println("}");
    }
}