/**
* Copyright 2011 ArcBees Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.gwtplatform.dispatch.annotation.processor;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import com.gwtplatform.dispatch.annotation.helper.BuilderGenerationHelper;
import com.gwtplatform.dispatch.annotation.helper.GenerationHelper;
import com.gwtplatform.dispatch.annotation.helper.ReflectionHelper;
/**
* Processes {@link GenEvent} annotations.
* <p/>
* {@link GenEventProcessor} should only ever be called by tool infrastructure.
* See {@link javax.annotation.processing.Processor} for more details.
*/
@SupportedAnnotationTypes("com.gwtplatform.dispatch.annotation.GenEvent")
public class GenEventProcessor extends GenProcessor {
@Override
public void process(Element eventElement) {
BuilderGenerationHelper writer = null;
try {
ReflectionHelper reflection = new ReflectionHelper(getEnvironment(), (TypeElement) eventElement);
String eventElementSimpleName = reflection.getSimpleClassName();
String eventSimpleName = eventElementSimpleName + "Event";
String eventClassName = reflection.getClassName() + "Event";
@SuppressWarnings("resource")
Writer sourceWriter = getEnvironment().getFiler().createSourceFile(eventClassName,
eventElement).openWriter();
writer = new BuilderGenerationHelper(sourceWriter);
Collection<VariableElement> orderedElementFields = reflection.getOrderedFields();
Collection<VariableElement> allFields = reflection.getNonConstantFields();
Collection<VariableElement> optionalFields = reflection.getOptionalFields();
Collection<VariableElement> requiredFields = reflection.getNonConstantFields();
requiredFields.removeAll(optionalFields);
writer.generatePackageDeclaration(reflection.getPackageName());
writer.generateImports(
"com.google.gwt.event.shared.EventHandler",
"com.google.gwt.event.shared.GwtEvent",
"com.google.web.bindery.event.shared.HandlerRegistration",
null,
"com.google.gwt.event.shared.HasHandlers"
);
writer.generateClassHeader(eventSimpleName,
"GwtEvent<" + eventSimpleName + "." + eventElementSimpleName + "Handler>",
reflection.getClassRepresenter().getModifiers()
);
writer.generateFieldDeclarations(orderedElementFields);
if (!optionalFields.isEmpty()) { // has optional fields.
writer.setWhitespaces(2);
writer.generateBuilderClass(eventSimpleName, requiredFields, optionalFields);
writer.resetWhitespaces();
if (!requiredFields.isEmpty()) { // and required fields
writer.generateConstructorUsingFields(eventSimpleName, requiredFields, Modifier.PUBLIC);
}
writer.generateCustomBuilderConstructor(eventSimpleName, allFields);
generateFireSelfMethod(writer);
} else if (!requiredFields.isEmpty()) { // has only required fields
writer.generateEmptyConstructor(eventSimpleName, Modifier.PROTECTED);
writer.generateConstructorUsingFields(eventSimpleName, requiredFields, Modifier.PUBLIC);
generateFireFieldsStaticMethod(writer, requiredFields, eventSimpleName);
} else { // has no non-static fields
writer.generateEmptyConstructor(eventSimpleName, Modifier.PUBLIC);
generateFireFieldsStaticMethod(writer, requiredFields, eventSimpleName);
}
generateFireInstanceStaticMethod(writer, eventSimpleName);
generateHasHandlerInterface(writer, eventElementSimpleName);
generateHandlerInterface(writer, eventElementSimpleName);
generateStaticTypeField(writer, eventElementSimpleName);
generateTypeAccessorMethod(writer, eventElementSimpleName);
generateAssociatedTypeMethod(writer, eventElementSimpleName);
generateDispatchMethod(writer, eventElementSimpleName);
writer.generateFieldAccessors(orderedElementFields);
writer.generateEquals(eventSimpleName, orderedElementFields);
writer.generateHashCode(orderedElementFields);
writer.generateToString(eventSimpleName, orderedElementFields);
writer.generateFooter();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (writer != null) {
writer.close();
}
}
}
protected void generateAssociatedTypeMethod(GenerationHelper writer, String eventSimpleName) {
writer.println();
writer.println(" @Override");
writer.println(" public Type<{0}Handler> getAssociatedType() {", eventSimpleName);
writer.println(" return TYPE;");
writer.println(" }");
}
protected void generateDispatchMethod(GenerationHelper writer, String eventSimpleName) {
writer.println();
writer.println(" @Override");
writer.println(" protected void dispatch({0}Handler handler) {", eventSimpleName);
writer.println(" handler.on{0}(this);", eventSimpleName);
writer.println(" }");
}
protected void generateHasHandlerInterface(GenerationHelper writer, String eventSimpleName) {
writer.println();
writer.println(" public interface Has{0}Handlers extends HasHandlers {", eventSimpleName);
writer.println(" HandlerRegistration add{0}Handler({0}Handler handler);", eventSimpleName);
writer.println(" }");
}
protected void generateHandlerInterface(GenerationHelper writer, String eventSimpleName) {
writer.println();
writer.println(" public interface {0}Handler extends EventHandler {", eventSimpleName);
writer.println(" public void on{0}({0}Event event);", eventSimpleName);
writer.println(" }");
}
protected void generateFireInstanceStaticMethod(GenerationHelper writer, String simpleClassName) {
writer.println();
writer.println(" public static void fire(HasHandlers source, {0} eventInstance) {", simpleClassName);
writer.println(" source.fireEvent(eventInstance);");
writer.println(" }");
}
protected void generateFireFieldsStaticMethod(GenerationHelper writer,
Collection<VariableElement> requiredFields, String simpleClassName) {
String fields = writer.generateFieldList(requiredFields, false, false);
String fieldsWithTypes = writer.generateFieldList(requiredFields, true, requiredFields.size() > 0);
writer.println();
writer.println(" public static void fire(HasHandlers source{0}) {", fieldsWithTypes);
writer.println(" {0} eventInstance = new {0}({1});", simpleClassName, fields);
writer.println(" source.fireEvent(eventInstance);");
writer.println(" }");
}
protected void generateFireSelfMethod(GenerationHelper writer) {
writer.println();
writer.println(" public void fire(HasHandlers source) {");
writer.println(" source.fireEvent(this);");
writer.println(" }");
}
protected void generateStaticTypeField(GenerationHelper out, String eventSimpleName) {
out.println();
out.println(" private static final Type<{0}Handler> TYPE = new Type<{0}Handler>();", eventSimpleName);
}
protected void generateTypeAccessorMethod(GenerationHelper out, String eventSimpleName) {
out.println();
out.println(" public static Type<{0}Handler> getType() {", eventSimpleName);
out.println(" return TYPE;");
out.println(" }");
}
}