package io.gitlab.jfronny.gson.compile.processor.gprocessor; import com.squareup.javapoet.*; import io.gitlab.jfronny.gson.compile.processor.SerializableClass; import io.gitlab.jfronny.gson.compile.processor.adapter.Adapters; import io.gitlab.jfronny.gson.compile.processor.core.TypeHelper; import io.gitlab.jfronny.gson.compile.processor.core.value.*; import io.gitlab.jfronny.gson.compile.processor.Cl; import javax.annotation.processing.Messager; import javax.lang.model.element.Modifier; import java.io.IOException; import java.util.List; import java.util.Set; public class StaticProcessor extends GProcessor { public StaticProcessor(ValueCreator valueCreator, Messager message, boolean hasManifold) { super(valueCreator, message, hasManifold, true); } @Override public void generateDelegatingAdapter(TypeSpec.Builder spec, TypeName classType, ClassName generatedClassName) { throw new UnsupportedOperationException(); } // !!!WARNING!!! // A lot of this code is common between InstanceProcessor and StaticProcessor // Make sure they don't get out of sync! // (Or, alternatively, create one common solution for these) // !!!WARNING!!! @Override public void generateSerialisation(TypeSpec.Builder spec, SerializableClass self, List typeVariables, Set otherAdapters) throws ElementException { Value value = valueCreator.fromStatic(self.classElement()); Properties properties = value.getProperties(); // public static void write(JsonWriter writer) throws IOException { CodeBlock.Builder code = CodeBlock.builder(); code.addStatement("writer.beginObject()"); for (Property.Field param : properties.fields) { if (Properties.containsName(properties.getters, param)) continue; Runnable writeGet = () -> code.add("$T.$N", self.getTypeName(), param.getCallableName()); if (param.getType().getKind().isPrimitive()) { generateComments(param, code); code.addStatement("writer.name($S)", getSerializedName(param)); Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, message, writeGet); } else { code.beginControlFlow("if ($T.$N != null || writer.getSerializeNulls())", self.getTypeName(), param.getCallableName()); generateComments(param, code); code.addStatement("writer.name($S)", getSerializedName(param)); code.addStatement("if ($T.$N == null) writer.nullValue()", self.getTypeName(), param.getCallableName()); code.beginControlFlow("else"); Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, message, writeGet); code.endControlFlow(); code.endControlFlow(); } } for (Property.Getter param : properties.getters) { if (param.getType().getKind().isPrimitive()) { generateComments(param, code); code.addStatement("writer.name($S)", getSerializedName(param)); Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, message, () -> code.add("$T.$N()", self.getTypeName(), param.getCallableName())); } else { code.addStatement("$T $L$N = $T.$N()", param.getType(), "$", param.getCallableName(), self.getTypeName(), param.getCallableName()); code.beginControlFlow("if ($L$N != null || writer.getSerializeNulls())", "$", param.getCallableName()); generateComments(param, code); code.addStatement("writer.name($S)", getSerializedName(param)); code.addStatement("if ($L$N == null) writer.nullValue()", "$", param.getCallableName()); code.beginControlFlow("else"); Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, message, () -> code.add("$L$N", "$", param.getCallableName())); code.endControlFlow(); code.endControlFlow(); } } code.addStatement("writer.endObject()"); spec.addMethod(extension(MethodSpec.methodBuilder("write")) .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .addParameter(Cl.GSON_WRITER, "writer") .addException(IOException.class) .addCode(code.build()) .build()); } // public static void read(JsonReader reader) throws IOException { CodeBlock.Builder code = CodeBlock.builder(); code.beginControlFlow("if (reader.peek() == $T.NULL)", Cl.GSON_TOKEN) .addStatement("reader.nextNull()") .addStatement("return") .endControlFlow(); boolean isEmpty = true; for (Property param : properties.names) { isEmpty = false; code.addStatement("$T.$N = $L", self.getTypeName(), param.getName(), TypeHelper.getDefaultValue(param.getType())); } if (isEmpty) { code.addStatement("reader.skipValue()"); } else { code.addStatement("reader.beginObject()") .beginControlFlow("while (reader.hasNext())") .beginControlFlow("switch (reader.nextName())"); for (Property param : properties.names) { if (param.getType().getKind().isPrimitive()) { code.add("case $S -> $T.$N = ", getSerializedName(param), self.getTypeName(), param.getName()); Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, message); code.add(";\n"); } else { code.beginControlFlow("case $S ->", getSerializedName(param)) .beginControlFlow("if (reader.peek() == $T.NULL)", Cl.GSON_TOKEN) .addStatement("reader.nextNull()") .addStatement("$T.$N = null", self.getTypeName(), param.getName()); code.unindent().add("} else $T.$N = ", self.getTypeName(), param.getName()); Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, message); code.add(";\n") .endControlFlow(); } } code.add("default -> ") .addStatement("reader.skipValue()"); code.endControlFlow() .endControlFlow() .addStatement("reader.endObject()"); } spec.addMethod(extension(MethodSpec.methodBuilder("read")) .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .addParameter(Cl.GSON_READER, "reader") .addException(IOException.class) .addCode(code.build()) .build()); } } }