208 lines
10 KiB
Java
208 lines
10 KiB
Java
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.core.value.*;
|
|
import io.gitlab.jfronny.gson.compile.processor.Cl;
|
|
|
|
import javax.annotation.processing.Messager;
|
|
import javax.lang.model.element.AnnotationMirror;
|
|
import javax.lang.model.element.Modifier;
|
|
import javax.lang.model.type.TypeMirror;
|
|
import java.io.*;
|
|
import java.nio.file.*;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.function.UnaryOperator;
|
|
|
|
public abstract class GProcessor {
|
|
protected final ValueCreator valueCreator;
|
|
protected final Messager message;
|
|
protected final boolean hasManifold;
|
|
|
|
private final boolean isStatic;
|
|
private final String readStatement;
|
|
private final String writeStatement;
|
|
|
|
public GProcessor(ValueCreator valueCreator, Messager message, boolean hasManifold, boolean isStatic) {
|
|
this.valueCreator = valueCreator;
|
|
this.message = message;
|
|
this.hasManifold = hasManifold;
|
|
|
|
this.isStatic = isStatic;
|
|
this.readStatement = isStatic ? "read(reader)" : "return read(reader)";
|
|
this.writeStatement = isStatic ? "write(writer)" : "write(value, writer)";
|
|
}
|
|
|
|
public abstract void generateDelegatingAdapter(TypeSpec.Builder spec, TypeName classType, ClassName generatedClassName);
|
|
public abstract void generateSerialisation(TypeSpec.Builder spec, SerializableClass self, List<TypeVariableName> typeVariables, Set<SerializableClass> otherAdapters) throws ElementException;
|
|
|
|
protected String getSerializedName(Property<?> property) {
|
|
for (AnnotationMirror annotationMirror : property.getAnnotations()) {
|
|
if (annotationMirror.getAnnotationType().asElement().toString().equals(Cl.SERIALIZED_NAME.toString())) {
|
|
return (String) annotationMirror.getElementValues().values().iterator().next().getValue();
|
|
}
|
|
}
|
|
return property.getName();
|
|
}
|
|
|
|
protected MethodSpec.Builder extension(MethodSpec.Builder method) {
|
|
if (hasManifold) method.addAnnotation(Cl.MANIFOLD_EXTENSION);
|
|
return method;
|
|
}
|
|
|
|
protected MethodSpec.Builder extension(MethodSpec.Builder method, TypeName thizName) {
|
|
if (thizName == null) return extension(method);
|
|
if (hasManifold) {
|
|
method.addAnnotation(Cl.MANIFOLD_EXTENSION);
|
|
method.addParameter(ParameterSpec.builder(thizName, "value").addAnnotation(Cl.MANIFOLD_THIS).build());
|
|
}
|
|
else {
|
|
method.addParameter(thizName, "value");
|
|
}
|
|
return method;
|
|
}
|
|
|
|
protected void generateComments(Property<?> prop, CodeBlock.Builder code) {
|
|
for (AnnotationMirror annotation : prop.getAnnotations()) {
|
|
if (annotation.getAnnotationType().asElement().toString().equals(Cl.GCOMMENT.toString())) {
|
|
String comment = (String) annotation.getElementValues().values().iterator().next().getValue();
|
|
code.addStatement("if (writer.isLenient()) writer.comment($S)", comment);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void generateDelegateToAdapter(TypeSpec.Builder spec, TypeName classType, TypeMirror adapter) {
|
|
spec.addMethod(
|
|
extension(MethodSpec.methodBuilder("read"))
|
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
|
.addParameter(Cl.GSON_READER, "reader")
|
|
.addException(IOException.class)
|
|
.returns(isStatic ? TypeName.VOID : classType)
|
|
.addCode(isStatic ? "$T.read(reader);" : "return $T.read(reader);", adapter)
|
|
.build()
|
|
);
|
|
spec.addMethod(
|
|
extension(MethodSpec.methodBuilder("write"), isStatic ? null : classType)
|
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
|
.addParameter(Cl.GSON_WRITER, "writer")
|
|
.addException(IOException.class)
|
|
.addCode("$T.$L;", adapter, writeStatement)
|
|
.build()
|
|
);
|
|
}
|
|
|
|
public void generateAuxiliary(TypeSpec.Builder spec, TypeName classType, TypeMirror configure) {
|
|
final UnaryOperator<CodeBlock.Builder> configureReader = cb -> {
|
|
if (configure != null) cb.addStatement("$T.configure(reader)", configure);
|
|
return cb;
|
|
};
|
|
final UnaryOperator<CodeBlock.Builder> configureWriter = cb -> {
|
|
if (configure != null) cb.addStatement("$T.configure(writer)", configure);
|
|
return cb;
|
|
};
|
|
|
|
spec.addMethod(
|
|
extension(MethodSpec.methodBuilder("read"))
|
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
|
.addParameter(TypeName.get(Reader.class), "in")
|
|
.addException(IOException.class)
|
|
.returns(isStatic ? TypeName.VOID : classType)
|
|
.addCode(configureReader.apply(CodeBlock.builder().beginControlFlow("try ($1T reader = new $1T(in))", Cl.GSON_READER))
|
|
.addStatement(readStatement)
|
|
.endControlFlow()
|
|
.build())
|
|
.build()
|
|
);
|
|
|
|
spec.addMethod(
|
|
extension(MethodSpec.methodBuilder("read"))
|
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
|
.addParameter(TypeName.get(String.class), "json")
|
|
.addException(IOException.class)
|
|
.returns(isStatic ? TypeName.VOID : classType)
|
|
.addCode(CodeBlock.builder().beginControlFlow("try ($1T reader = new $1T(json))", StringReader.class)
|
|
.addStatement(readStatement)
|
|
.endControlFlow()
|
|
.build())
|
|
.build()
|
|
);
|
|
|
|
spec.addMethod(
|
|
extension(MethodSpec.methodBuilder("read"))
|
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
|
.addParameter(Cl.GSON_ELEMENT, "tree")
|
|
.addException(IOException.class)
|
|
.returns(isStatic ? TypeName.VOID : classType)
|
|
.addCode(configureReader.apply(CodeBlock.builder().beginControlFlow("try ($1T reader = new $1T(tree))", Cl.GSON_TREE_READER))
|
|
.addStatement(readStatement)
|
|
.endControlFlow()
|
|
.build())
|
|
.build()
|
|
);
|
|
|
|
spec.addMethod(
|
|
extension(MethodSpec.methodBuilder("read"))
|
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
|
.addParameter(Path.class, "path")
|
|
.addException(IOException.class)
|
|
.returns(isStatic ? TypeName.VOID : classType)
|
|
.addCode(CodeBlock.builder().beginControlFlow("try ($T reader = $T.newBufferedReader(path))", BufferedReader.class, Files.class)
|
|
.addStatement(readStatement)
|
|
.endControlFlow()
|
|
.build())
|
|
.build()
|
|
);
|
|
|
|
spec.addMethod(
|
|
extension(MethodSpec.methodBuilder("write"), isStatic ? null : classType)
|
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
|
.addParameter(Writer.class, "out")
|
|
.addException(IOException.class)
|
|
.addCode(configureWriter.apply(CodeBlock.builder().beginControlFlow("try ($1T writer = new $1T(out))", Cl.GSON_WRITER))
|
|
.addStatement(writeStatement)
|
|
.endControlFlow()
|
|
.build())
|
|
.build()
|
|
);
|
|
|
|
spec.addMethod(
|
|
extension(MethodSpec.methodBuilder("write"), isStatic ? null : classType)
|
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
|
.addParameter(Path.class, "path")
|
|
.addException(IOException.class)
|
|
.addCode(CodeBlock.builder().beginControlFlow("try ($1T writer = $2T.newBufferedWriter(path, $3T.CREATE, $3T.WRITE, $3T.TRUNCATE_EXISTING))", BufferedWriter.class, Files.class, StandardOpenOption.class)
|
|
.addStatement(writeStatement)
|
|
.endControlFlow()
|
|
.build())
|
|
.build()
|
|
);
|
|
|
|
spec.addMethod(
|
|
extension(MethodSpec.methodBuilder("toJson"), isStatic ? null : classType)
|
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
|
.addException(IOException.class)
|
|
.returns(String.class)
|
|
.addCode(CodeBlock.builder().beginControlFlow("try ($1T writer = new $1T())", StringWriter.class)
|
|
.addStatement(writeStatement)
|
|
.addStatement("return writer.toString()")
|
|
.endControlFlow()
|
|
.build())
|
|
.build()
|
|
);
|
|
|
|
spec.addMethod(
|
|
extension(MethodSpec.methodBuilder("toJsonTree"), isStatic ? null : classType)
|
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
|
.addException(IOException.class)
|
|
.returns(Cl.GSON_ELEMENT)
|
|
.addCode(configureWriter.apply(CodeBlock.builder().beginControlFlow("try ($1T writer = new $1T())", Cl.GSON_TREE_WRITER))
|
|
.addStatement(writeStatement)
|
|
.addStatement("return writer.get()")
|
|
.endControlFlow()
|
|
.build())
|
|
.build()
|
|
);
|
|
}
|
|
}
|