package org.pentaho.mantle.rebind;
import java.io.PrintWriter;
import java.util.ArrayList;
import org.pentaho.mantle.client.commands.AbstractCommand;
import org.pentaho.mantle.client.commands.CommandExec;
import org.pentaho.mantle.client.solutionbrowser.SolutionBrowserPerspective;
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.JPackage;
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.client.Command;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
public class CommandExecGenerator extends Generator {
private String packageName;
private String className;
private TypeOracle typeOracle;
private TreeLogger logger;
@Override
public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException {
this.logger = logger;
typeOracle = context.getTypeOracle();
try {
// get classType and save instance variables
JClassType classType = typeOracle.getType(typeName);
packageName = classType.getPackage().getName();
className = classType.getSimpleSourceName() + "Impl";
// Generate class source code
generateClass(logger, context);
} catch (Exception e) {
// record to logger that Map generation threw an exception
logger.log(TreeLogger.ERROR, "PropertyMap ERROR!!!", e);
}
// return the fully qualifed name of the class generated
return packageName + "." + className;
}
private void generateClass(TreeLogger logger, GeneratorContext context) {
// get print writer that receives the source code
PrintWriter printWriter = null;
printWriter = context.tryCreate(logger, packageName, className);
// print writer if null, source code has ALREADY been generated, return
if (printWriter == null)
return;
// init composer, set class properties, create source writer
ClassSourceFileComposerFactory composer = null;
composer = new ClassSourceFileComposerFactory(packageName, className);
composer.addImplementedInterface(CommandExec.class.getName());
composer.addImport(SolutionBrowserPerspective.class.getName());
SourceWriter sourceWriter = null;
sourceWriter = composer.createSourceWriter(context, printWriter);
sourceWriter.indent();
// generator constructor source code
generateConstructor(sourceWriter);
generateMethods(sourceWriter);
// close generated class
sourceWriter.outdent();
sourceWriter.println("}");
// commit generated class
context.commit(logger, printWriter);
}
private void generateMethods(SourceWriter sourceWriter) {
sourceWriter.println("public void execute(String commandName) { ");
sourceWriter.indent();
try {
// find Command implementors
ArrayList<JClassType> implementingTypes = new ArrayList<JClassType>();
JPackage pack = typeOracle.getPackage(AbstractCommand.class.getPackage().getName());
JClassType eventSourceType = typeOracle.getType(Command.class.getName());
for (JClassType type : pack.getTypes()) {
if (type.isAssignableTo(eventSourceType)) {
implementingTypes.add(type);
}
}
sourceWriter.println("if(false){}"); // placeholder
for (JClassType implementingType : implementingTypes) {
sourceWriter.println("else if(commandName.equals(\"" + implementingType.getSimpleSourceName() + "\")){");
if (implementingType.isDefaultInstantiable()) {
sourceWriter.println("new " + implementingType.getSimpleSourceName() + "().execute();");
} else {
logger.log(TreeLogger.WARN, "Cannot generate auto-scripts for Command type (" + implementingType.getSimpleSourceName()
+ "), needs at least a no-arg constructor");
}
sourceWriter.println("}");
}
} catch (Exception e) {
// record to logger that Map generation threw an exception
logger.log(TreeLogger.ERROR, "Error generating BindingContext!!!", e);
}
sourceWriter.outdent();
sourceWriter.println("}");
}
private void generateConstructor(SourceWriter sourceWriter) {
// start constructor source generation
sourceWriter.println("public " + className + "() { ");
sourceWriter.indent();
sourceWriter.println("super();");
sourceWriter.outdent();
sourceWriter.println("}");
}
private String boxPrimative(JType type) {
if (type.isPrimitive() != null) {
JPrimitiveType primative = type.isPrimitive();
return primative.getQualifiedBoxedSourceName();
} else {
return type.getQualifiedSourceName();
}
}
}