package org.gwtoolbox.ioc.core.rebind;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Set;
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.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import org.gwtoolbox.commons.generator.rebind.EasyTreeLogger;
import org.gwtoolbox.ioc.core.client.event.ApplicationEvent;
import org.gwtoolbox.ioc.core.client.event.ApplicationEventListener;
/**
* @author Uri Boness
*/
public class EventHandlerListenerClassGenerator {
public static String generate(EasyTreeLogger logger, JClassType componentType, Set<JMethod> handlerMethods, GeneratorContext context) throws UnableToCompleteException {
JClassType applicationEventType = context.getTypeOracle().findType(ApplicationEvent.class.getName());
Set<JMethod> actualHandlers = new HashSet<JMethod>();
for (JMethod method : handlerMethods) {
if (method.getParameterTypes()[0].isClassOrInterface().isAssignableTo(applicationEventType)) {
actualHandlers.add(method);
}
}
if (actualHandlers.isEmpty()) {
return null;
}
TypeOracle typeOracle = context.getTypeOracle();
String packageName = componentType.getPackage().getName();
String className = componentType.getSimpleSourceName() + "_EventListener";
String qualifiedBeanClassName = packageName + "." + className;
SourceWriter sourceWriter = getSourceWriter(logger, context, packageName, className);
if (sourceWriter == null) {
return qualifiedBeanClassName;
}
write(logger, sourceWriter, typeOracle, context, componentType, className, actualHandlers);
sourceWriter.commit(logger);
return qualifiedBeanClassName;
}
protected static SourceWriter getSourceWriter(
TreeLogger logger,
GeneratorContext context,
String packageName,
String listenerClassName) {
PrintWriter printWriter = context.tryCreate(logger, packageName, listenerClassName);
if (printWriter == null) {
return null;
}
ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(packageName, listenerClassName);
composerFactory.addImport(ApplicationEvent.class.getName());
composerFactory.addImport(ApplicationEventListener.class.getName());
composerFactory.addImplementedInterface(ApplicationEventListener.class.getName());
return composerFactory.createSourceWriter(context, printWriter);
}
protected static void write(
EasyTreeLogger logger,
SourceWriter writer,
TypeOracle typeOracle,
GeneratorContext context,
JClassType componentType,
String listenerClassName,
Set<JMethod> handlerMethods) throws UnableToCompleteException {
writer.println();
writer.println("private final " + componentType.getQualifiedSourceName() + " component;");
writer.println();
writer.println("public " + listenerClassName + "(" + componentType.getQualifiedSourceName() + " component) {");
writer.println(" this.component = component;");
writer.println("}");
writer.println();
writer.println("public void handle(ApplicationEvent event) {");
for (JMethod handlerMethod : handlerMethods) {
JParameter[] parameters = handlerMethod.getParameters();
if (parameters.length != 1) {
logger.error("Could not register event handler method '" + handlerMethod.getName() + "' in '" +
componentType.getQualifiedSourceName() + "' as it accepts more than one parameter. " +
"Event handler method should only accept one parameter which is an instance of 'ApplicationEvent'");
throw new UnableToCompleteException();
}
JParameter parameter = parameters[0];
JClassType eventType = typeOracle.findType(ApplicationEvent.class.getName());
if (parameter.getType().isClassOrInterface() == null || !parameter.getType().isClassOrInterface().isAssignableTo(eventType)) {
logger.error("Could not register event handler method '" + handlerMethod.getName() + "' in '" +
handlerMethod.getEnclosingType().getQualifiedSourceName() + "'. Event handler method should only " +
"accept one parameter which is an instance of 'ApplicationEvent'");
throw new UnableToCompleteException();
}
String eventClassName = parameter.getType().getQualifiedSourceName();
writer.println(" if (event instanceof " + eventClassName + ") {");
writer.println(" component." + handlerMethod.getName() + "((" + eventClassName + ")event);");
writer.println(" return;");
writer.println(" }");
}
writer.println("}");
}
}