feat(serialize-generator): support alternate names in @SerializedName
ci/woodpecker/push/woodpecker Pipeline was successful Details

This commit is contained in:
Johannes Frohnmeyer 2024-04-24 20:25:12 +02:00
parent d1343208a3
commit faf7dfd18e
Signed by: Johannes
GPG Key ID: E76429612C2929F4
4 changed files with 78 additions and 49 deletions

View File

@ -11,6 +11,8 @@ import io.gitlab.jfronny.commons.serialize.generator.core.value.ValueCreator;
import javax.annotation.processing.Messager;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.type.TypeMirror;
import java.io.*;
@ -19,8 +21,10 @@ import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
public abstract class GProcessor {
protected final ValueCreator valueCreator;
@ -69,13 +73,26 @@ public abstract class GProcessor {
return null;
}
protected String getSerializedName(Property<?> property) {
protected List<String> getSerializedNames(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();
String value = null;
List<String> alternate = null;
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet()) {
switch (entry.getKey().getSimpleName().toString()) {
case "value" -> value = (String) entry.getValue().getValue();
case "alternate" -> alternate = ((List<?>) entry.getValue().getValue()).stream()
.map(s -> (AnnotationValue) s)
.map(s -> (String) s.getValue())
.toList();
}
}
if (value == null) value = property.getName();
if (alternate == null) return List.of(value);
return Stream.concat(Stream.of(value), alternate.stream()).toList();
}
}
return property.getName();
return List.of(property.getName());
}
protected MethodSpec.Builder extension(MethodSpec.Builder method) {

View File

@ -81,12 +81,12 @@ public class InstanceProcessor extends GProcessor {
Runnable writeGet = () -> code.add("value.$N", param.getCallableName());
if (param.getType().getKind().isPrimitive()) {
generateComments(param, code);
code.addStatement("writer.name($S)", getSerializedName(param));
code.addStatement("writer.name($S)", getSerializedNames(param).getFirst());
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, refs, message, writeGet);
} else {
code.beginControlFlow("if (value.$N != null || writer.isSerializeNulls())", param.getCallableName());
generateComments(param, code);
code.addStatement("writer.name($S)", getSerializedName(param));
code.addStatement("writer.name($S)", getSerializedNames(param).getFirst());
code.addStatement("if (value.$N == null) writer.nullValue()", param.getCallableName());
code.beginControlFlow("else");
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, refs, message, writeGet);
@ -98,13 +98,13 @@ public class InstanceProcessor extends GProcessor {
if (isIgnored(param)) continue;
if (param.getType().getKind().isPrimitive()) {
generateComments(param, code);
code.addStatement("writer.name($S)", getSerializedName(param));
code.addStatement("writer.name($S)", getSerializedNames(param).getFirst());
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, refs, message, () -> code.add("value.$N()", param.getCallableName()));
} else {
code.addStatement("$T $L$N = value.$N()", param.getType(), "$", param.getCallableName(), param.getCallableName());
code.beginControlFlow("if ($L$N != null || writer.isSerializeNulls())", "$", param.getCallableName());
generateComments(param, code);
code.addStatement("writer.name($S)", getSerializedName(param));
code.addStatement("writer.name($S)", getSerializedNames(param).getFirst());
code.addStatement("if ($L$N == null) writer.nullValue()", "$", param.getCallableName());
code.beginControlFlow("else");
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, refs, message, () -> code.add("$L$N", "$", param.getCallableName()));
@ -148,24 +148,30 @@ public class InstanceProcessor extends GProcessor {
.beginControlFlow("switch (reader.nextName())");
for (Property<?> param : properties.names) {
if (isIgnored(param) && getAlternative(properties, param) == null) continue;
code.beginControlFlow("case $S ->", getSerializedName(param));
if (param.getType().getKind().isPrimitive()) {
code.add("_$N = ", param.getName());
Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, refs, message);
code.add(";\n");
} else {
code.beginControlFlow("if (reader.peek() == $T.NULL)", Cl.GSON_TOKEN)
.addStatement("reader.nextNull()")
.addStatement("_$N = null", param.getName());
code.unindent().add("} else _$N = ", param.getName());
Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, refs, message);
code.add(";\n");
List<String> names = getSerializedNames(param);
for (String serializedName : names) {
code.beginControlFlow("case $S ->", serializedName);
code.addStatement("if (has_$N && !reader.isLenient()) throw new $T($S)", param.getName(), Cl.MALFORMED_DATA_EXCEPTION, "Duplicate entry for: " + names.getFirst());
if (param.getType().getKind().isPrimitive()) {
code.add("_$N = ", param.getName());
Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, refs, message);
code.add(";\n");
} else {
code.beginControlFlow("if (reader.peek() == $T.NULL)", Cl.GSON_TOKEN)
.addStatement("reader.nextNull()")
.addStatement("_$N = null", param.getName());
code.unindent().add("} else _$N = ", param.getName());
Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, refs, message);
code.add(";\n");
}
code.addStatement("has_$N = true", param.getName());
code.endControlFlow();
}
code.addStatement("has_$N = true", param.getName());
code.endControlFlow();
}
code.add("default -> ")
.addStatement("reader.skipValue()");
code.beginControlFlow("case String s -> ")
.addStatement("if (reader.isLenient()) reader.skipValue()")
.addStatement("else throw new $T($S + s)", Cl.MALFORMED_DATA_EXCEPTION, "Unexpected name: ")
.endControlFlow();
code.endControlFlow()
.endControlFlow()

View File

@ -46,12 +46,12 @@ public class StaticProcessor extends GProcessor {
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));
code.addStatement("writer.name($S)", getSerializedNames(param).getFirst());
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, refs, message, writeGet);
} else {
code.beginControlFlow("if ($T.$N != null || writer.isSerializeNulls())", self.getTypeName(), param.getCallableName());
generateComments(param, code);
code.addStatement("writer.name($S)", getSerializedName(param));
code.addStatement("writer.name($S)", getSerializedNames(param).getFirst());
code.addStatement("if ($T.$N == null) writer.nullValue()", self.getTypeName(), param.getCallableName());
code.beginControlFlow("else");
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, refs, message, writeGet);
@ -63,13 +63,13 @@ public class StaticProcessor extends GProcessor {
if (isIgnored(param)) continue;
if (param.getType().getKind().isPrimitive()) {
generateComments(param, code);
code.addStatement("writer.name($S)", getSerializedName(param));
code.addStatement("writer.name($S)", getSerializedNames(param).getFirst());
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, refs, 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.isSerializeNulls())", "$", param.getCallableName());
generateComments(param, code);
code.addStatement("writer.name($S)", getSerializedName(param));
code.addStatement("writer.name($S)", getSerializedNames(param).getFirst());
code.addStatement("if ($L$N == null) writer.nullValue()", "$", param.getCallableName());
code.beginControlFlow("else");
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, refs, message, () -> code.add("$L$N", "$", param.getCallableName()));
@ -113,8 +113,8 @@ public class StaticProcessor extends GProcessor {
code.addStatement("$T.$N = $L", self.getTypeName(), param.getName(), TypeHelper.getDefaultValue(param.getType()));
} else {
code.addStatement("$T _$N = $L", param.getType(), param.getName(), TypeHelper.getDefaultValue(param.getType()));
code.addStatement("boolean has_$N = false", param.getName());
}
code.addStatement("boolean has_$N = false", param.getName());
}
if (isEmpty) {
code.addStatement("reader.skipValue()");
@ -127,30 +127,36 @@ public class StaticProcessor extends GProcessor {
param = altMap.get(param);
if (param == null) continue;
}
code.beginControlFlow("case $S ->", getSerializedName(param));
if (param.getType().getKind().isPrimitive()) {
if (param instanceof Property.Field) code.add("$T.$N = ", self.getTypeName(), param.getName());
else code.add("_$N = ", param.getName());
Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, refs, message);
code.add(";\n");
} else {
code.beginControlFlow("if (reader.peek() == $T.NULL)", Cl.GSON_TOKEN)
.addStatement("reader.nextNull()");
if (param instanceof Property.Field) {
code.addStatement("$T.$N = null", self.getTypeName(), param.getName());
code.unindent().add("} else $T.$N = ", self.getTypeName(), param.getName());
List<String> names = getSerializedNames(param);
for (String serializedName : names) {
code.beginControlFlow("case $S ->", serializedName);
code.addStatement("if (has_$N && !reader.isLenient()) throw new $T($S)", param.getName(), Cl.MALFORMED_DATA_EXCEPTION, "Duplicate entry for: " + names.getFirst());
if (param.getType().getKind().isPrimitive()) {
if (param instanceof Property.Field) code.add("$T.$N = ", self.getTypeName(), param.getName());
else code.add("_$N = ", param.getName());
Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, refs, message);
code.add(";\n");
} else {
code.addStatement("_$N = null", param.getName());
code.unindent().add("} else _$N = ", param.getName());
code.beginControlFlow("if (reader.peek() == $T.NULL)", Cl.GSON_TOKEN)
.addStatement("reader.nextNull()");
if (param instanceof Property.Field) {
code.addStatement("$T.$N = null", self.getTypeName(), param.getName());
code.unindent().add("} else $T.$N = ", self.getTypeName(), param.getName());
} else {
code.addStatement("_$N = null", param.getName());
code.unindent().add("} else _$N = ", param.getName());
}
Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, refs, message);
code.add(";\n");
}
Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, refs, message);
code.add(";\n");
code.addStatement("has_$N = true", param.getName());
code.endControlFlow();
}
if (!(param instanceof Property.Field)) code.addStatement("has_$N = true", param.getName());
code.endControlFlow();
}
code.add("default -> ")
.addStatement("reader.skipValue()");
code.beginControlFlow("case String s -> ")
.addStatement("if (reader.isLenient()) reader.skipValue()")
.addStatement("else throw new $T($S + s)", Cl.MALFORMED_DATA_EXCEPTION, "Unexpected name: ")
.endControlFlow();
code.endControlFlow()
.endControlFlow()

View File

@ -24,7 +24,7 @@ public class Main {
public Boolean someBool;
@GComment("Halal")
@SerializedName("bingChiller")
@SerializedName(value = "bingChiller", alternate = {"bingChiller2", "bingChiller3"})
public String getBass() {
return "Yes";
}