com.workday.postman.codegen.ParcelerGenerator Maven / Gradle / Ivy
/*
* Copyright 2015 Workday, Inc.
*
* This software is available under the MIT license.
* Please see the LICENSE.txt file in this project.
*/
package com.workday.postman.codegen;
import com.squareup.javawriter.JavaWriter;
import com.workday.meta.MetaTypeNames;
import com.workday.meta.MetaTypes;
import com.workday.meta.Modifiers;
import com.workday.postman.parceler.Parceler;
import com.workday.postman.util.Names;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
/**
* @author nathan.taylor
* @since 2013-9-25-17:51
*/
class ParcelerGenerator {
final ProcessingEnvironment processingEnv;
private final Collection parceledFields;
private final TypeElement elementToParcel;
private final String parcelerName;
final MetaTypes metaTypes;
private final Collection postCreateChildMethods;
String elementCompressedName;
final String elementQualifiedName;
private final List saveStatementWriters;
private static final SaveStatementWriter
DO_NOTHING_SAVE_STATEMENT_WRITER = DoNothingSaveStatementWriter.INSTANCE;
public ParcelerGenerator(ProcessingEnvironment processingEnv, TypeElement elementToParcel) {
this.processingEnv = processingEnv;
metaTypes = new MetaTypes(processingEnv);
this.elementToParcel = elementToParcel;
elementQualifiedName = elementToParcel.getQualifiedName().toString();
parcelerName = MetaTypeNames.constructTypeName(elementToParcel, Names.PARCELER_SUFFIX);
ParceledElementExtractor parceledElementExtractor =
new ParceledElementExtractor(processingEnv);
this.parceledFields = parceledElementExtractor.extractParceledFields(elementToParcel);
this.postCreateChildMethods =
parceledElementExtractor.extractPostCreateChildMethods(elementToParcel);
saveStatementWriters = createSaveStatementWriterList();
}
public void generateParceler() throws IOException {
JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(parcelerName);
JavaWriter writer = new JavaWriter(sourceFile.openWriter());
writer.emitPackage(processingEnv.getElementUtils().getPackageOf(
elementToParcel).getQualifiedName().toString());
writer.emitImports(getImports());
writer.emitEmptyLine();
elementCompressedName = writer.compressType(elementToParcel.getQualifiedName().toString());
writer.beginType(parcelerName, "class", EnumSet.of(Modifier.PUBLIC, Modifier.FINAL), null,
JavaWriter.type(Parceler.class, elementCompressedName));
writer.emitEmptyLine();
writeWriteToParcelMethod(writer);
writer.emitEmptyLine();
writeReadFromParcelMethod(writer);
writer.emitEmptyLine();
writeNewArrayMethod(writer);
writer.emitEmptyLine();
writer.endType();
writer.close();
}
private Set getImports() {
Set imports = new HashSet();
imports.add("android.os.Bundle");
imports.add("android.os.Parcel");
imports.add(Parceler.class.getCanonicalName());
return imports;
}
private void writeWriteToParcelMethod(JavaWriter writer) throws IOException {
List parameters = new ArrayList(4);
parameters.add(elementCompressedName);
parameters.add("object");
parameters.add("Parcel");
parameters.add("dest");
writer.emitAnnotation(Override.class);
writer.beginMethod("void", "writeToParcel", Modifiers.PUBLIC, parameters, null);
writer.emitStatement("Bundle bundle = new Bundle()");
for (VariableElement field : parceledFields) {
getSaveStatementWriter(field).writeFieldWriteStatement(field, writer);
}
writer.emitStatement("dest.writeBundle(bundle)");
writer.endMethod();
}
private void writeReadFromParcelMethod(JavaWriter writer) throws IOException {
writer.emitAnnotation(Override.class);
writer.beginMethod(elementCompressedName, "readFromParcel", Modifiers.PUBLIC, "Parcel",
"parcel");
writer.emitStatement("%s object = new %s()", elementCompressedName, elementCompressedName);
writer.emitStatement("Bundle bundle = parcel.readBundle()");
writer.emitStatement("bundle.setClassLoader(%s.class.getClassLoader())",
elementCompressedName);
for (VariableElement field : parceledFields) {
getSaveStatementWriter(field).writeFieldReadStatement(field,
postCreateChildMethods,
writer);
}
writer.emitStatement("return object");
writer.endMethod();
}
private void writeNewArrayMethod(JavaWriter writer) throws IOException {
writer.emitAnnotation(Override.class);
writer.beginMethod(String.format("%s[]", elementCompressedName),
"newArray",
Modifiers.PUBLIC,
"int",
"size");
writer.emitStatement("return new %s[size]", elementCompressedName);
writer.endMethod();
}
private com.workday.postman.codegen.SaveStatementWriter getSaveStatementWriter(
VariableElement field) {
for (com.workday.postman.codegen.SaveStatementWriter saveStatementWriter :
saveStatementWriters) {
if (saveStatementWriter.isApplicable(field)) {
return saveStatementWriter;
}
}
String errorMessage = String.format("%s.%s of type %s cannot be written to a Bundle.",
elementQualifiedName,
field.getSimpleName().toString(),
field.asType().toString());
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, errorMessage, field);
return DO_NOTHING_SAVE_STATEMENT_WRITER;
}
private List createSaveStatementWriterList() {
List list = new ArrayList<>();
list.add(new BoxableSaveStatementWriter(metaTypes));
list.add(new StringSaveStatementWriter(metaTypes));
list.add(new CharSequenceSaveStatementWriter(metaTypes));
list.add(new EnumSaveStatementWriter(metaTypes));
list.add(new ParcelableSaveStatementWriter(metaTypes));
list.add(new CollectionSaveStatementWriter(this));
list.add(new MapSaveStatementWriter(this));
list.add(new SerializableSaveStatementWriter(metaTypes));
return Collections.unmodifiableList(list);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy