xapi.dev.generators.RunAsyncInjectionGenerator.java Source code

Java tutorial

Introduction

Here is the source code for xapi.dev.generators.RunAsyncInjectionGenerator.java

Source

/*
 * Copyright 2012, We The Internet Ltd.
 *
 * All rights reserved.
 *
 * Distributed under a modified BSD License as follow:
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution, unless otherwise
 * agreed to in a written document signed by a director of We The Internet Ltd.
 *
 * Neither the name of We The Internet nor the names of its contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
package xapi.dev.generators;

import java.io.PrintWriter;

import xapi.collect.api.Fifo;
import xapi.dev.util.DefermentWriter;
import xapi.dev.util.InjectionCallbackArtifact;
import xapi.gwt.collect.JsFifo;
import xapi.util.api.ApplyMethod;
import xapi.util.api.ProvidesValue;
import xapi.util.api.ReceivesValue;

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.RebindMode;
import com.google.gwt.core.ext.RebindResult;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

public class RunAsyncInjectionGenerator extends AbstractInjectionGenerator {

    @Override
    public RebindResult generateIncrementally(TreeLogger logger, GeneratorContext context, String typeName)
            throws UnableToCompleteException {
        Iterable<InjectionCallbackArtifact> artifacts = getInjectionMap(logger, context).getArtifacts();
        //        ctx.getArtifacts().find(InjectionCallbackArtifact.class);
        if (typeName.endsWith(".Callbacks")) {
            typeName = typeName.substring(0, typeName.length() - 10);
            logger.log(Type.INFO, "" + typeName);
            for (InjectionCallbackArtifact artifact : artifacts) {
                if (artifact.getAsyncInjectionName().equals(typeName)) {
                    //we have our injectable artifact!
                    int packageIndex = typeName.lastIndexOf('.');
                    String packageName = typeName.substring(0, packageIndex);
                    String generatedName = "RunAsync" + typeName.substring(packageIndex + 12);

                    typeName = packageName + "." + generatedName;
                    logger.log(Type.INFO, "WIN " + typeName + " <- " + artifact);

                    PrintWriter printWriter = context.tryCreate(logger, packageName, generatedName);
                    if (printWriter == null) {
                        logger.log(Type.TRACE, "Re-Using existing " + typeName);
                        return new RebindResult(RebindMode.USE_EXISTING, typeName);
                    }
                    ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(packageName,
                            generatedName);
                    composer.addImplementedInterface(ApplyMethod.class.getName());
                    composer.setPrivacy("public final");
                    composer.addImport(GWT.class.getName());
                    composer.addImport(ApplyMethod.class.getName());
                    composer.addImport(ProvidesValue.class.getName());
                    composer.addImport(ReceivesValue.class.getName());
                    composer.addImport(Runnable.class.getName());
                    composer.addImport(Fifo.class.getName());
                    composer.addImport(JsFifo.class.getName());
                    composer.addImport(Timer.class.getName());
                    composer.addImport(Scheduler.class.getName());
                    composer.addImport(ScheduledCommand.class.getCanonicalName());

                    SourceWriter sw = composer.createSourceWriter(printWriter);
                    sw.println("private static final Fifo<Object> callbacks;");
                    sw.println("static{");
                    sw.indent();
                    sw.println("callbacks = JsFifo.newFifo();");
                    for (String callback : artifact.getCallbacks()) {
                        sw.println("callbacks.give(GWT.create(" + callback + ".class));");
                    }
                    sw.outdent();
                    sw.println("}");

                    sw.println("@SuppressWarnings({\"unchecked\", \"rawtypes\"})");
                    sw.println("public void apply(final Object ... args){");

                    DefermentWriter defer = new DefermentWriter(sw);
                    defer.printStart();//used to optionally push callbacks into new execution block

                    //for now, we are only sending the service object as parameter
                    sw.println("  Object service = args[0], callback;");
                    sw.println("  while(!callbacks.isEmpty()){");
                    sw.indent();
                    sw.println("  callback = callbacks.take();");
                    sw.println("  if (callback instanceof ReceivesValue){");
                    sw.println("    ((ReceivesValue)callback).set(service);");
                    sw.println("  }");
                    sw.println("  else if (callback instanceof ApplyMethod){");
                    sw.println("    ((ApplyMethod)callback).apply(args);");
                    sw.println("  }");
                    sw.println("  else if (callback instanceof ProvidesValue){");
                    sw.println("    ((ProvidesValue<ReceivesValue>)callback).get().set(service);");
                    sw.println("  }");
                    sw.println("  else if (callback instanceof Runnable){");
                    sw.println("    ((Runnable)callback).run();");
                    sw.println("  }");
                    sw.println("}");
                    sw.outdent();

                    defer.printFinish();

                    sw.println("}");
                    //          sw.println("}");
                    sw.commit(logger);
                    context.commit(logger, printWriter);
                    return new RebindResult(RebindMode.USE_ALL_NEW, typeName);
                }
            }
        }
        logger.log(Type.INFO, "No callback class found for " + typeName + "; returning untransformed.");
        return new RebindResult(RebindMode.USE_EXISTING, typeName);
    }

}