/*
* 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);
}
}