Package com.totsp.gwittir.rebind.stream

Source Code of com.totsp.gwittir.rebind.stream.StreamClientGenerator

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.totsp.gwittir.rebind.stream;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JGenericType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamFactory;
import com.google.gwt.user.client.rpc.impl.ClientSerializationStreamWriter;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

import com.totsp.gwittir.client.stream.StreamControl;
import com.totsp.gwittir.client.stream.StreamServiceCallback;
import com.totsp.gwittir.client.stream.impl.StreamingServiceStub;
import com.totsp.gwittir.client.stream.StreamServiceIterator;

import java.io.PrintWriter;


/**
*
* @author kebernet
*/
public class StreamClientGenerator extends Generator {
    JType objectType;
    JClassType streamServiceIterator;

    @Override
    public String generate(TreeLogger logger, GeneratorContext context,
        String typeName) throws UnableToCompleteException {
        JClassType streamServiceType = null;

        try {
            this.objectType = context.getTypeOracle().getType("java.lang.Object");
            streamServiceType = context.getTypeOracle().getType(typeName);
            streamServiceIterator = context.getTypeOracle()
                                           .getType(StreamServiceIterator.class.getCanonicalName());
        } catch (NotFoundException ex) {
            logger.log(TreeLogger.ERROR, typeName, ex);

            return null;
        }

        this.generateRemoteService(logger, context, streamServiceType);
        this.generateRemoteServiceAsync(logger, context, streamServiceType);

        String className =  this.generateImplementation(logger, context, streamServiceType);
        logger.log( TreeLogger.Type.WARN, "Rebound: "+className);
        return className;
    }

    protected String generateImplementation(TreeLogger logger,
        GeneratorContext context, JClassType type) throws UnableToCompleteException {
        String packageName = type.getQualifiedSourceName() + "_impls";
        String className = type.getSimpleSourceName() + "_StreamServiceImpl";
        String remoteServiceName = type.getSimpleSourceName() + "_RemoteService";
        JClassType asyncType = null;
        try {
            asyncType = context.getTypeOracle().getType(type.getQualifiedSourceName() + "Async");
        } catch (NotFoundException ex) {
            logger.log( TreeLogger.Type.ERROR, "Unable to find async type for "+type, ex);
            throw new UnableToCompleteException();
        }

        ClassSourceFileComposerFactory mcf = new ClassSourceFileComposerFactory(packageName,
                className);
        mcf.setSuperclass(StreamingServiceStub.class.getCanonicalName());
        mcf.addImplementedInterface(type.getQualifiedSourceName() + "Async");
        mcf.addImport( SerializationStreamFactory.class.getCanonicalName() );
        mcf.addImport( GWT.class.getCanonicalName() );
        mcf.addImport( StreamServiceCallback.class.getCanonicalName() );
        mcf.addImport( ClientSerializationStreamWriter.class.getCanonicalName() );
        mcf.addImport( SerializationException.class.getCanonicalName() );
        PrintWriter pw = context.tryCreate(logger, packageName, className);
        if(pw == null){
             return packageName +"."+className;
        }
        SourceWriter sw = mcf.createSourceWriter(context, pw);

        String generatedRemoteService = type.getQualifiedSourceName() + "_impls"
                + "." +type.getSimpleSourceName() + "_RemoteService";
        sw.print( "private static final SerializationStreamFactory SERIALIZER =");
        sw.print( "(SerializationStreamFactory) GWT.create(");
        sw.print( generatedRemoteService );
        sw.println( ".class);");
        sw.print ( "private static final String REMOTE_SERVICE_INTERFACE_NAME = \"");
        sw.print ( packageName );
        sw.print (".");
        sw.print ( remoteServiceName );
        sw.println( "\";");
        sw.println("public SerializationStreamFactory getStreamFactory() { return SERIALIZER; }");
        for (JMethod method : type.getMethods()) {
          writeMethod(logger, sw, asyncType, method, StreamServiceCallback.class);
        }

        sw.outdent();
        sw.println("}");
        context.commit(logger, pw);

        return packageName + "." + className;
    }

    protected void writeMethod(TreeLogger logger, SourceWriter sw, JClassType asyncType, JMethod method , Class<?> callbackType) throws UnableToCompleteException{
      if (!(method.getReturnType() instanceof JClassType)) {
            logger.log(TreeLogger.Type.ERROR,
                method.getReturnType().getQualifiedSourceName() +
                " is not a class type.", null);
            throw new UnableToCompleteException();
        }
     
        JClassType returnType = (JClassType) method.getReturnType();
       
        if (!returnType.isAssignableTo(this.streamServiceIterator)) {
            logger.log(TreeLogger.Type.ERROR,
                returnType.getQualifiedSourceName() +
                " is not assignable to " +
                this.streamServiceIterator.getQualifiedSourceName());
            throw new UnableToCompleteException();
        }

//        String parameterType = "java.io.Serializable";
//        JGenericType generic = returnType.isGenericType();
//
//        if ((generic != null) && (generic.getTypeParameters().length > 1)) {
//            logger.log(TreeLogger.Type.ERROR, "WTF scoob?");
//            throw new UnableToCompleteException();
//        } else if (generic != null) {
//            parameterType = generic.getTypeParameters()[0].getQualifiedSourceName();
//        }

        sw.println("public "+StreamControl.class.getCanonicalName()+" " + method.getName() + " (");

        boolean first = true;

        for (JParameter param : method.getParameters()) {
            if (!first) {
                sw.print(", ");
            } else {
                first = false;
            }

            sw.print(param.getType().getQualifiedSourceName());
            sw.print(" ");
            sw.print(param.getName());
        }
        sw.println(" , "+callbackType.getCanonicalName()+" callback");
        sw.println(") {");
        sw.indent();
        sw.println("try{");
            sw.indent();
        sw.println( "ClientSerializationStreamWriter streamWriter = (ClientSerializationStreamWriter) SERIALIZER.createStreamWriter();");
        sw.println( "streamWriter.writeString(REMOTE_SERVICE_INTERFACE_NAME);");
        sw.println( "streamWriter.writeString(\""+ method.getName() +"\");");
        sw.println( "streamWriter.writeInt("+method.getParameters().length+");" );
        for(JParameter param : method.getParameters() ){
            sw.println( "streamWriter.writeString(\""+ this.getJSNIType(param.getType())+"\");");
        }
        for(JParameter param : method.getParameters() ){
            sw.println("streamWriter."+ this.getWriteCallName(param.getType()) +"("+param.getName()+");");
        }
        sw.outdent();
        try{
            JMethod asyncMethod = this.getAsyncMethod(asyncType, method);
            String callbackParam = asyncMethod.getParameters()[asyncMethod.getParameters().length-1].getName();
           
            sw.println("return invoke(streamWriter.toString(),"+callbackParam+");");
            sw.outdent();
            sw.println("}catch(Exception se){");
            sw.indent();
            sw.println("throw new RuntimeException(se);");
            sw.outdent();
            sw.println("}");
        } catch(UnableToCompleteException e){
            logger.log(TreeLogger.Type.ERROR, "Unabel to find matching async method for "+ method.getReadableDeclaration());
            throw e;
        }
        sw.println("}");
    }
   
   
    protected JMethod getAsyncMethod( JClassType asyncType, JMethod syncMethod ) throws UnableToCompleteException{
        for(JMethod sourceMethod : asyncType.getMethods() ){

            if( sourceMethod.getName(). equals(syncMethod.getName() )
                    && sourceMethod.getParameters().length == syncMethod.getParameters().length + 1){
                    boolean notIt = false;
                    for( int i=0; i < syncMethod.getParameters().length; i++ ){
                        if( !syncMethod.getParameters()[i].getType().equals( sourceMethod.getParameters()[i].getType() ) ){
                            notIt = true;
                            break;
                        }
                    }
                    if( notIt ){
                        continue;
                    } else {
                        return sourceMethod;
                    }
            }
        }
        throw new UnableToCompleteException();

    }

    protected String getJSNIType(JType type){
       if (type.isArray() != null ){
            return type.getJNISignature().replaceAll("/", ".");
       } else if( type.getJNISignature().length() > 1 ){
           return type.getQualifiedSourceName();
       } else {
           return type.getJNISignature();
       }
    }

    protected String getWriteCallName(JType type){
        if( getJSNIType(type).length() == 1){
            String typeName = type.toString();
            return "write"+typeName.substring(0,1).toUpperCase() + typeName.substring(1, typeName.length() );
        } else if( getJSNIType(type).equals("java.lang.String")  ){
            return "writeString";
        } else {
            return "writeObject";
        }
    }

    protected void generateRemoteService(TreeLogger logger,
        GeneratorContext context, JClassType type)
        throws UnableToCompleteException {
        String packageName = type.getQualifiedSourceName() + "_impls";
        String className = type.getSimpleSourceName() + "_RemoteService";
        ClassSourceFileComposerFactory mcf = new ClassSourceFileComposerFactory(packageName,
                className);
        mcf.makeInterface();
        mcf.addImplementedInterface(
            "com.google.gwt.user.client.rpc.RemoteService");

        PrintWriter pw = context.tryCreate(logger, packageName, className);
        if( pw == null ){
           return;
        }
        SourceWriter sw = mcf.createSourceWriter(context, pw);

        for (JMethod method : type.getMethods()) {
            if (!(method.getReturnType() instanceof JClassType)) {
                logger.log(TreeLogger.Type.ERROR,
                    method.getReturnType().getQualifiedSourceName() +
                    " is not a class type.", null);
                throw new UnableToCompleteException();
            }

            JClassType returnType = (JClassType) method.getReturnType();

            if (!returnType.isAssignableTo(this.streamServiceIterator)) {
                logger.log(TreeLogger.Type.ERROR,
                    returnType.getQualifiedSourceName() +
                    " is not assignable to " +
                    this.streamServiceIterator.getQualifiedSourceName());
                throw new UnableToCompleteException();
            }

            String parameterType = "java.io.Serializable";
//            JGenericType generic = returnType.isGenericType();
//
//            if ((generic != null) && (generic.getTypeParameters().length > 1)) {
//                logger.log(TreeLogger.Type.ERROR, "WTF scoob?");
//                throw new UnableToCompleteException();
//            } else if (generic != null) {
//                parameterType = generic.getTypeParameters()[0].getQualifiedSourceName();
//            }


            parameterType = this.determineParameterType(returnType);
            sw.println("public " + parameterType + " " + method.getName() + " ( ");

            boolean first = true;

            for (JParameter param : method.getParameters()) {
                if (!first) {
                    sw.print(", ");
                } else {
                    first = false;
                }

                sw.print(param.getType().getQualifiedSourceName());
                sw.print(" ");
                sw.print(param.getName());
            }

            sw.println(" )");

            if ((method.getThrows() != null) &&
                    (method.getThrows().length > 0)) {
                sw.print(" throws ");
                first = true;

                for (JType throwable : method.getThrows()) {
                    if (!first) {
                        sw.print(", ");
                    } else {
                        first = false;
                    }

                    sw.print(throwable.getQualifiedSourceName());
                }
            }

            sw.println(";");
            sw.outdent();
            sw.println("}");
            context.commit(logger, pw);
        }
    }

    protected String determineParameterType(JType type){
        String parameterType = type.toString();;
        parameterType = parameterType.substring( parameterType.indexOf("<")+1, parameterType.lastIndexOf(">"));
        return parameterType;
    }

    protected void generateRemoteServiceAsync(TreeLogger logger,
        GeneratorContext context, JClassType type)
        throws UnableToCompleteException {
        String packageName = type.getQualifiedSourceName() + "_impls";
        String className = type.getSimpleSourceName() + "_RemoteServiceAsync";
        ClassSourceFileComposerFactory mcf = new ClassSourceFileComposerFactory(packageName,
                className);
        mcf.makeInterface();
        PrintWriter pw = context.tryCreate(logger, packageName, className);
        if(pw == null){
            return;
        }
        SourceWriter sw = mcf.createSourceWriter(context, pw);

        for (JMethod method : type.getMethods()) {
            if (!(method.getReturnType() instanceof JClassType)) {
                logger.log(TreeLogger.Type.ERROR,
                    method.getReturnType().getQualifiedSourceName() +
                    " is not a class type.", null);
                throw new UnableToCompleteException();
            }

            JClassType returnType = (JClassType) method.getReturnType();

            if (!returnType.isAssignableTo(this.streamServiceIterator)) {
                logger.log(TreeLogger.Type.ERROR,
                    returnType.getQualifiedSourceName() +
                    " is not assignable to " +
                    this.streamServiceIterator.getQualifiedSourceName());
                throw new UnableToCompleteException();
            }

            //String parameterType = this.determineParameterType(returnType);
            /*JGenericType generic = returnType.isGenericType();

            logger.log(TreeLogger.Type.WARN, "Generic Type: "+generic);
            if ((generic != null) && (generic.getTypeParameters().length > 1)) {
                logger.log(TreeLogger.Type.ERROR, "WTF scoob?");
                throw new UnableToCompleteException();
            } else if (generic != null) {
                parameterType = generic.getTypeParameters()[0].getQualifiedSourceName();
            }
            */
            sw.println("public void " + method.getName() + " (");

            boolean first = true;

            for (JParameter param : method.getParameters()) {
                if (!first) {
                    sw.print(", ");
                } else {
                    first = false;
                }

                sw.print(param.getType().getQualifiedSourceName());
                sw.print(" ");
                sw.print(param.getName());
            }

            sw.print(", " + AsyncCallback.class.getCanonicalName() + " cb" +
                System.currentTimeMillis());
            sw.print(" ) ");

            sw.println(";");
            sw.outdent();
            sw.println("}");
            context.commit(logger, pw);
        }
    }
}
TOP

Related Classes of com.totsp.gwittir.rebind.stream.StreamClientGenerator

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.