com.github.gilbertotorrezan.gwtviews.rebind.PresenterGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gwt-views Show documentation
Show all versions of gwt-views Show documentation
A simple but powerful View controller for GWT
The newest version!
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Gilberto Torrezan Filho
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package com.github.gilbertotorrezan.gwtviews.rebind;
import java.io.PrintWriter;
import java.util.Date;
import com.github.gilbertotorrezan.gwtviews.client.AutoPresenter;
import com.github.gilbertotorrezan.gwtviews.client.CachePolicy;
import com.github.gilbertotorrezan.gwtviews.client.CachedPresenter;
import com.github.gilbertotorrezan.gwtviews.client.Presenter;
import com.github.gilbertotorrezan.gwtviews.client.View;
import com.github.gilbertotorrezan.gwtviews.client.ViewContainer;
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.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
/**
* Class used by the code generator to create the default {@link Presenter}s of Views and ViewContainers.
*
* @author Gilberto Torrezan Filho
*
* @since v.1.0.0
* @see AutoPresenter
*/
public class PresenterGenerator extends Generator {
@Override
public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException {
final TypeOracle typeOracle = context.getTypeOracle();
JClassType mainType = typeOracle.findType(typeName);
JParameterizedType parameterized = mainType.getImplementedInterfaces()[0].isParameterized();
JClassType viewType = parameterized.getTypeArgs()[0];
final String className = viewType.getQualifiedSourceName();
String name = mainType.getName().substring(mainType.getName().lastIndexOf('.')+1);
name = name.substring(0, name.length() - "Presenter".length());
name = name + "_" + name + "PresenterImpl";
PrintWriter writer = context.tryCreate(logger, viewType.getPackage().getName(), name);
if (writer == null){
return viewType.getPackage().getName() + "." + name;
}
ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(viewType.getPackage().getName(), name);
factory.addImplementedInterface(AutoPresenter.class.getName());
factory.addImport(Presenter.class.getPackage().getName()+".*");
factory.addImport("com.google.gwt.user.client.History");
factory.addImport("com.google.gwt.core.client.GWT");
factory.addImport("com.google.gwt.user.client.ui.Widget");
factory.addImport("javax.annotation.Generated");
factory.addImport("java.util.*");
factory.addAnnotationDeclaration("@Generated("
+ "value=\""+PresenterGenerator.class.getName()+"\", "
+ "date=\""+new Date()+"\", "
+ "comments=\"Generated by GWT-Views project.\")");
View view = viewType.getAnnotation(View.class);
ViewContainer viewContainer = viewType.getAnnotation(ViewContainer.class);
CachePolicy cache;
JClassType injectorType = null;
String injectorMethod = null;
if (view == null){
cache = CachePolicy.ALWAYS;
}
else {
cache = view.cache();
}
if (cache == CachePolicy.SAME_URL){
factory.setSuperclass(CachedPresenter.class.getName());
}
SourceWriter sourceWriter = factory.createSourceWriter(context, writer);
sourceWriter.println("//AUTO GENERATED FILE BY GWT-VIEWS AT " + getClass().getName() + ". DO NOT EDIT!\n");
if (cache == CachePolicy.ALWAYS){
sourceWriter.println("private Widget view; //the cached view");
}
Class> injector = view == null ? void.class : view.injector();
if (injector.equals(void.class)){
injector = viewContainer == null ? void.class : viewContainer.injector();
}
if (!injector.equals(void.class)){
try {
injectorType = typeOracle.findType(injector.getName());
injectorMethod = view != null ? view.injectorMethod() : viewContainer.injectorMethod();
injectorMethod = getInjectorMethod(logger, injectorType, injectorMethod, className);
}
catch (Exception e) {
logger.log(Type.ERROR, "Error loading the injector class \"" + injector.getName() + "\": " + e, e);
throw new UnableToCompleteException();
}
}
if (cache == CachePolicy.SAME_URL){
sourceWriter.println("\n@Override\npublic Widget createNewView(URLToken url) {");
}
else {
sourceWriter.println("\n@Override\npublic Widget getView(URLToken url) {");
}
sourceWriter.indent();
switch (cache) {
case NEVER: {
sourceWriter.println("//code for the CachePolicy.NEVER:");
printInjectorMethod(sourceWriter, className, injectorType, injectorMethod);
}
break;
case ALWAYS: {
sourceWriter.println("//code for the CachePolicy.ALWAYS:");
sourceWriter.println("if (this.view == null) {");
sourceWriter.indent();
printInjectorMethod(sourceWriter, className, injectorType, injectorMethod);
sourceWriter.println("this.view = view;");
sourceWriter.outdent();
sourceWriter.println("}");
}
break;
case SAME_URL: {
sourceWriter.println("//code for the CachePolicy.SAME_URL:");
printInjectorMethod(sourceWriter, className, injectorType, injectorMethod);
}
break;
}
sourceWriter.println("return view;");
sourceWriter.outdent();
sourceWriter.println("}\n");
sourceWriter.outdent();
sourceWriter.println("}\n");
context.commit(logger, writer);
return factory.getCreatedClassName();
}
private String getInjectorMethod(TreeLogger logger, JClassType injector, String injectorMethod, String className) throws UnableToCompleteException {
if (injectorMethod != null && !injectorMethod.isEmpty()){
try {
injector.getMethod(injectorMethod, new JType[0]);
}
catch (NotFoundException e) {
logger.log(Type.WARN, "The injector method \"" + injectorMethod + "\" was not found on class " + injector.getQualifiedSourceName());
//a compiler error will be trigged if the method really doesn't exist
}
return injectorMethod;
}
else {
String methodName = null;
JMethod[] methods = injector.getInheritableMethods();
for (JMethod method : methods) {
JType returnType = method.getReturnType();
if (returnType.getQualifiedSourceName().equals(className)){
if (methodName != null){
logger.log(Type.ERROR, "The injector " + injector.getName() + " has more than one method with " + className
+ " as return type. Use the \"injectorMethod\" property to specify which one should be used.");
throw new UnableToCompleteException();
}
methodName = method.getName();
}
}
if (methodName == null){
logger.log(Type.INFO, "The injector " + injector.getName() + " has no methods with " + className
+ " as return type. The View will not be injected.");
return null;
}
return methodName;
}
}
private void printInjectorMethod(SourceWriter sourceWriter, String className, JClassType injectorType, String injectorMethod){
if (injectorType != null && injectorMethod != null){
sourceWriter.println(injectorType.getQualifiedSourceName() + " injector = NavigationManager.getInjectorInstance(" + injectorType.getQualifiedSourceName() + ".class);");
sourceWriter.println("if (injector == null) injector = GWT.create(" + injectorType.getQualifiedSourceName() + ".class);");
sourceWriter.println("Widget view = (" + className + ") injector." + injectorMethod + "();");
}
else {
sourceWriter.println("Widget view = GWT.create( " + className + ".class);");
}
}
}