Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alibaba.fastjson2.internal.processor.JSONCompiledAnnotationProcessor Maven / Gradle / Ivy
package com.alibaba.fastjson2.internal.processor;
import com.alibaba.fastjson2.*;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import com.alibaba.fastjson2.internal.codegen.Label;
import com.alibaba.fastjson2.internal.graalmeta.ReflectionMetadata;
import com.alibaba.fastjson2.reader.FieldReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import com.alibaba.fastjson2.reader.ObjectReaderAdapter;
import com.alibaba.fastjson2.reader.ObjectReaders;
import com.alibaba.fastjson2.writer.FieldWriter;
import com.alibaba.fastjson2.writer.ObjectWriterAdapter;
import com.alibaba.fastjson2.writer.ObjectWriters;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.TypeTag;
import com.sun.tools.javac.processing.JavacFiler;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.TreeTranslator;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Names;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import java.io.*;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import static com.alibaba.fastjson2.JSONWriter.Feature.*;
import static com.alibaba.fastjson2.internal.processor.CodeGenUtils.*;
import static com.alibaba.fastjson2.internal.processor.JavacTreeUtils.*;
import static com.alibaba.fastjson2.internal.processor.JavacTreeUtils.qualIdent;
import static com.alibaba.fastjson2.util.JDKUtils.*;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes({
"com.alibaba.fastjson2.annotation.JSONCompiled",
"com.alibaba.fastjson2.annotation.JSONBuilder",
"com.alibaba.fastjson2.annotation.JSONCreator",
"com.alibaba.fastjson2.annotation.JSONField",
"com.alibaba.fastjson2.annotation.JSONType"
})
public class JSONCompiledAnnotationProcessor
extends AbstractProcessor {
private Messager messager;
private JavacTrees javacTrees;
private Names names;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
ProcessingEnvironment unwrappedProcessingEnv = unwrapProcessingEnv(processingEnv);
super.init(unwrappedProcessingEnv);
this.messager = unwrappedProcessingEnv.getMessager();
this.javacTrees = JavacTrees.instance(unwrappedProcessingEnv);
Context context = ((JavacProcessingEnvironment) unwrappedProcessingEnv).getContext();
this.names = Names.instance(context);
initialize(TreeMaker.instance(context), names, unwrappedProcessingEnv.getElementUtils());
}
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
Analysis analysis = new Analysis(processingEnv);
Set extends Element> compiledJsons = roundEnv.getElementsAnnotatedWith(analysis.jsonCompiledElement);
if (!compiledJsons.isEmpty()) {
analysis.processAnnotation(analysis.jsonCompiledDeclaredType, compiledJsons);
}
Map structs = analysis.analyze();
Set extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(JSONCompiled.class);
Set reflects = new HashSet<>(elementsAnnotatedWith.size() * 2);
elementsAnnotatedWith.forEach(element -> {
StructInfo structInfo = structs.get(element.toString());
java.util.List attributeInfos = structInfo.getReaderAttributes();
int fieldsSize = attributeInfos.size();
Class readSuperClass = getReadSuperClass(fieldsSize);
Class writeSuperClass = getWriteSuperClass(fieldsSize);
JCTree tree = javacTrees.getTree(element);
pos(tree.pos);
tree.accept(new TreeTranslator() {
@Override
public void visitClassDef(JCTree.JCClassDecl beanClassDecl) {
super.visitClassDef(beanClassDecl);
String beanClassFQN = beanClassDecl.sym.toString();
if (element.toString().equals(beanClassFQN)) {
// initialization
String innerReadClassFQN = findConverterName(structInfo, "_FASTJSONReader");
String innerReadClassName = innerReadClassFQN.substring(innerReadClassFQN.lastIndexOf('.') + 1);
JCTree.JCExpression beanType = null;
if (beanClassFQN.contains(".")) {
if (element instanceof Symbol.ClassSymbol) {
Symbol.ClassSymbol classSymbol = (Symbol.ClassSymbol) element;
String owner = classSymbol.owner.toString();
int dotIdx = owner.indexOf(".");
beanType = field(dotIdx == -1 ? ident(owner) : qualIdent(owner),
beanClassFQN.substring(beanClassFQN.lastIndexOf(".") + 1));
}
} else {
int dotIdx = beanClassFQN.indexOf(".");
beanType = dotIdx == -1 ? ident(beanClassFQN) : qualIdent(beanClassFQN);
}
JCTree.JCNewClass beanNew = newClass(null, null, beanType, null, null);
JCTree.JCIdent objectType = ident("Object");
// add deserializer class
addInnerClassIfAbsent(beanClassDecl, beanClassFQN, innerReadClassName, "deserializer");
// generate inner read class
JCTree.JCClassDecl innerReadClass = genInnerClass(innerReadClassName, readSuperClass);
// generate fields if necessary
final boolean generatedFields = fieldsSize < 128;
if (generatedFields) {
innerReadClass.defs = innerReadClass.defs.prependList(genFields(attributeInfos, readSuperClass));
}
// generate constructor
innerReadClass.defs = innerReadClass.defs.append(genReadConstructor(beanType, beanNew, attributeInfos, readSuperClass, generatedFields));
// generate createInstance
innerReadClass.defs = innerReadClass.defs.append(genCreateInstance(objectType, beanNew));
// generate readObject
innerReadClass.defs = innerReadClass.defs.append(
genReadObject(objectType, beanType, beanNew, attributeInfos, structInfo, false));
// generate readJSONBObject
innerReadClass.defs = innerReadClass.defs.append(
genReadObject(objectType, beanType, beanNew, attributeInfos, structInfo, true));
// link with inner class
beanClassDecl.defs = beanClassDecl.defs.append(innerReadClass);
// initialization
String innerWriteClassFQN = findConverterName(structInfo, "_FASTJSONWriter");
String innerWriteClassName = innerWriteClassFQN.substring(innerWriteClassFQN.lastIndexOf('.') + 1);
// add serializer class
addInnerClassIfAbsent(beanClassDecl, beanClassFQN, innerWriteClassName, "serializer");
// generate inner read class
JCTree.JCClassDecl innerWriteClass = genInnerClass(innerWriteClassName, writeSuperClass);
// generate fields if necessary
if (generatedFields) {
innerWriteClass.defs = innerWriteClass.defs.prependList(genFields(attributeInfos, writeSuperClass));
}
// generate constructor
innerWriteClass.defs = innerWriteClass.defs.append(genWriteConstructor(beanType, beanNew, attributeInfos, writeSuperClass, generatedFields));
// generate write
innerWriteClass.defs = innerWriteClass.defs.append(genWrite(objectType, beanType, beanNew, attributeInfos, structInfo, false));
// link with inner class
beanClassDecl.defs = beanClassDecl.defs.append(innerWriteClass);
// generate source if debug is true
if (isDebug(beanClassDecl)) {
messager.printMessage(Diagnostic.Kind.WARNING, "Whoops! You have changed the debug of " +
"JSONCompiled from false to true for " + structInfo.binaryName + ", which means the " +
"additional source file being generated. It's usually not recommended to enable debug " +
"until you are in developer mode");
genSource(structInfo, javacTrees.getPath(element));
}
// generate reflect-config.json only for graal
if (GRAAL) {
ReflectionMetadata readMeta = new ReflectionMetadata();
readMeta.setName(innerReadClassFQN);
readMeta.setAllPublicConstructors(true);
reflects.add(readMeta);
ReflectionMetadata writeMeta = new ReflectionMetadata();
writeMeta.setName(innerWriteClassFQN);
writeMeta.setAllPublicConstructors(true);
reflects.add(writeMeta);
}
}
}
});
});
if (!reflects.isEmpty()) {
genReflect(reflects);
}
return true;
}
private void addInnerClassIfAbsent(JCTree.JCClassDecl beanClassDecl,
String beanClassFQN,
String innerClassName,
String key) {
JCTree.JCExpression jsonTypeIdent = qualIdent("com.alibaba.fastjson2.annotation.JSONType");
List annotations = beanClassDecl.mods.annotations;
Optional jsonTypeAnnoOpt = annotations.stream()
.filter(a -> a.getAnnotationType().type.tsym.toString().equals(jsonTypeIdent.type.tsym.toString()))
.findAny();
String beanClassName = beanClassFQN.substring(beanClassFQN.lastIndexOf('.') + 1);
JCTree.JCIdent lhs = ident(key);
JCTree.JCFieldAccess rhs = field(field(ident(beanClassName), innerClassName), names._class);
if (jsonTypeAnnoOpt.isPresent()) {
JCTree.JCAnnotation jsonTypeAnno = jsonTypeAnnoOpt.get();
Optional jsonTypeAsgOpt = jsonTypeAnno.args.stream()
.map(a -> (JCTree.JCAssign) a)
.filter(a2 -> key.equals(a2.lhs.toString()))
.findAny();
if (jsonTypeAsgOpt.isPresent()) {
JCTree.JCAssign deserializerAssign = jsonTypeAsgOpt.get();
if ("Void.class".equals(deserializerAssign.rhs.toString())) {
deserializerAssign.rhs = rhs;
}
} else {
jsonTypeAnno.args = jsonTypeAnno.args.prepend(assign(lhs, rhs));
}
} else {
JCTree.JCAnnotation jsonTypeAnno = annotation(jsonTypeIdent, List.of(assign(lhs, rhs)));
beanClassDecl.mods.annotations = annotations.prepend(jsonTypeAnno);
}
}
private JCTree.JCClassDecl genInnerClass(String className, Class superClass) {
if (ObjectReaderAdapter.class.isAssignableFrom(superClass)) {
return defClass(Flags.PUBLIC | Flags.STATIC | Flags.FINAL,
className,
null,
qualIdent(superClass.getName()),
null,
null);
} else if (ObjectWriterAdapter.class.isAssignableFrom(superClass)) {
return defClass(Flags.PUBLIC | Flags.STATIC | Flags.FINAL,
className,
null,
qualIdent(superClass.getName()),
List.of(qualIdent("com.alibaba.fastjson2.writer.ObjectWriter")),
null);
} else {
return null;
}
}
private List genFields(java.util.List attributeInfos, Class superClass) {
ListBuffer stmts = new ListBuffer<>();
int fieldsSize = attributeInfos.size();
if (ObjectReaderAdapter.class.isAssignableFrom(superClass)) {
JCTree.JCExpression fieldReaderType = qualIdent(FieldReader.class.getName());
JCTree.JCExpression objectReaderType = qualIdent(ObjectReader.class.getName());
if (superClass == ObjectReaderAdapter.class) {
for (int i = 0; i < fieldsSize; ++i) {
stmts.append(defVar(Flags.PRIVATE, fieldReader(i), fieldReaderType));
}
for (int i = 0; i < fieldsSize; i++) {
stmts.append(defVar(Flags.PRIVATE, fieldObjectReader(i), objectReaderType));
}
}
for (int i = 0; i < fieldsSize; ++i) {
AttributeInfo field = attributeInfos.get(i);
String fieldType = field.type.toString();
if (fieldType.startsWith("java.util.List<") || fieldType.startsWith("java.util.Map fields,
Class superClass,
boolean generatedFields) {
JCTree.JCMemberReference lambda = constructorRef(beanType);
JCTree.JCExpression fieldReaderType = qualIdent(FieldReader.class.getName());
ListBuffer fieldReaders = new ListBuffer<>();
JCTree.JCExpression objectReadersType = qualIdent(ObjectReaders.class.getName());
int fieldsSize = fields.size();
for (int i = 0; i < fieldsSize; ++i) {
JCTree.JCMethodInvocation readerMethod = genFieldReader(beanType, fields.get(i), objectReadersType);
if (readerMethod != null) {
fieldReaders.append(readerMethod);
}
}
JCTree.JCNewArray fieldReadersArray = newArray(fieldReaderType, null, List.from(fieldReaders));
long features = 0L;
JCTree.JCMethodInvocation superMethod = method(
ident(names._super),
List.of(
field(beanType, names._class),
defNull(),
defNull(),
literal(features),
lambda,
defNull(),
fieldReadersArray
)
);
ListBuffer stmts = new ListBuffer<>();
stmts.append(exec(superMethod));
// initialize fields if necessary
if (superClass == ObjectReaderAdapter.class && generatedFields) {
stmts.appendList(genInitFields(fieldsSize, superClass));
}
return defMethod(Flags.PUBLIC, names.init, type(TypeTag.VOID), null, null, null, block(stmts.toList()), null);
}
private JCTree.JCMethodDecl genWriteConstructor(
JCTree.JCExpression beanType,
JCTree.JCNewClass beanNew,
java.util.List fields,
Class superClass,
boolean generatedFields) {
JCTree.JCExpression fieldWriterType = qualIdent(FieldWriter.class.getName());
ListBuffer fieldWriters = new ListBuffer<>();
JCTree.JCExpression objectWritersType = qualIdent(ObjectWriters.class.getName());
int fieldsSize = fields.size();
for (int i = 0; i < fieldsSize; ++i) {
JCTree.JCMethodInvocation writerMethod = null;
AttributeInfo attributeInfo = fields.get(i);
if (attributeInfo.getMethod != null) {
writerMethod = writerMethod(beanType, objectWritersType, attributeInfo, true);
} else if (attributeInfo.field != null) {
String fieldName = attributeInfo.field.getSimpleName().toString();
if (fieldName.equals(attributeInfo.name)) {
writerMethod = writerMethod(beanType, objectWritersType, attributeInfo, false);
} else {
writerMethod = writerMethod(beanType, objectWritersType, attributeInfo, false);
}
} else {
messager.printMessage(Diagnostic.Kind.WARNING, "not implemented yet");
}
if (writerMethod != null) {
fieldWriters.append(writerMethod);
}
}
JCTree.JCNewArray fieldReadersArray = newArray(fieldWriterType, null, List.from(fieldWriters));
JCTree.JCMethodInvocation fieldReadersList = method(qualIdent("java.util.Arrays"), "asList", fieldReadersArray);
JCTree.JCMethodInvocation superMethod = method(
ident(names._super),
List.of(
field(beanType, names._class),
defNull(),
defNull(),
literal(0L),
fieldReadersList
)
);
ListBuffer stmts = new ListBuffer<>();
stmts.append(exec(superMethod));
// initialize fields if necessary
if (superClass == ObjectWriterAdapter.class && generatedFields) {
stmts.appendList(genInitFields(fields.size(), superClass));
}
return defMethod(Flags.PUBLIC, names.init, type(TypeTag.VOID), null, null, null, block(stmts.toList()), null);
}
private JCTree.JCMethodInvocation writerMethod(
JCTree.JCExpression beanType,
JCTree.JCExpression objectWritersType,
AttributeInfo attributeInfo,
boolean isMethodReference) {
String type = attributeInfo.type.toString();
if ("boolean".equals(type)
|| "char".equals(type)
|| "byte".equals(type)
|| "short".equals(type)
|| "int".equals(type)
|| "long".equals(type)
|| "float".equals(type)
|| "double".equals(type)) {
if (isMethodReference) {
String methodName = attributeInfo.getMethod.getSimpleName().toString();
JCTree.JCMemberReference memberedReference = methodRef(beanType, methodName);
return method(objectWritersType, "fieldWriter", literal(attributeInfo.name), memberedReference);
} else {
String fieldName = attributeInfo.field.getSimpleName().toString();
JCTree.JCLambda lambda = lambda(
defVar("bean", beanType),
field(ident("bean"), fieldName)
);
return method(objectWritersType, "fieldWriter", literal(fieldName), lambda);
}
} else if ("java.lang.Class".equals(type)) {
if (isMethodReference) {
String methodName = attributeInfo.getMethod.getSimpleName().toString();
JCTree.JCMemberReference memberedReference = methodRef(beanType, methodName);
return method(
objectWritersType,
"fieldWriter",
literal(attributeInfo.name),
field(beanType, names._class),
memberedReference
);
} else {
String fieldName = attributeInfo.field.getSimpleName().toString();
JCTree.JCLambda lambda = lambda(
defVar("bean", beanType),
field(ident("bean"), fieldName)
);
return method(
objectWritersType,
"fieldWriter",
literal(fieldName),
field(beanType, names._class),
lambda
);
}
} else if ("java.lang.Type".equals(type)) {
if (isMethodReference) {
String methodName = attributeInfo.getMethod.getSimpleName().toString();
JCTree.JCMemberReference memberedReference = methodRef(beanType, methodName);
return method(
objectWritersType,
"fieldWriter",
literal(attributeInfo.name),
field(beanType, names._class),
field(beanType, names._class),
memberedReference
);
} else {
String fieldName = attributeInfo.field.getSimpleName().toString();
JCTree.JCLambda lambda = lambda(
List.of(
defVar("bean", beanType)
),
field(ident("bean"), fieldName)
);
return method(
objectWritersType,
"fieldWriter",
literal(fieldName),
field(beanType, names._class),
field(beanType, names._class),
lambda
);
}
} else if ("java.util.List".equals(type)) {
if (isMethodReference) {
String methodName = attributeInfo.getMethod.getSimpleName().toString();
JCTree.JCMemberReference memberedReference = methodRef(beanType, methodName);
return method(objectWritersType, "fieldWriterListString", literal(attributeInfo.name), memberedReference);
} else {
String fieldName = attributeInfo.field.getSimpleName().toString();
JCTree.JCLambda lambda = lambda(
defVar("bean", beanType),
field(ident("bean"), fieldName)
);
return method(objectWritersType, "fieldWriterListString", literal(fieldName), lambda);
}
} else if (type.startsWith("java.util.List")
|| type.startsWith("java.util.ArrayList")
|| type.startsWith("java.util.LinkedList")
|| type.startsWith("java.util.concurrent.CopyOnWriteArrayList")) {
String itemType;
if (type.contains("<")) {
itemType = type.substring(type.indexOf("<") + 1, type.length() - 1);
} else {
itemType = type;
}
JCTree.JCFieldAccess itemTypeClass = field(qualIdent(itemType), names._class);
if (isMethodReference) {
String methodName = attributeInfo.getMethod.getSimpleName().toString();
JCTree.JCMemberReference memberedReference = methodRef(beanType, methodName);
return method(objectWritersType, "fieldWriterList", literal(attributeInfo.name), itemTypeClass, memberedReference);
} else {
String fieldName = attributeInfo.field.getSimpleName().toString();
JCTree.JCLambda lambda = lambda(
defVar("bean", beanType),
field(ident("bean"), fieldName)
);
return method(objectWritersType, "fieldWriterList", literal(fieldName), itemTypeClass, lambda);
}
} else {
JCTree.JCFieldAccess fieldClass;
if (type.contains("[")) {
fieldClass = field(arrayIdentType(type), names._class);
} else {
int idx = type.indexOf("<");
if (idx != -1) {
type = type.substring(0, idx);
}
fieldClass = field(identType(type), names._class);
}
if (isMethodReference) {
String methodName = attributeInfo.getMethod.getSimpleName().toString();
JCTree.JCMemberReference memberedReference = methodRef(beanType, methodName);
return method(objectWritersType, "fieldWriter", literal(attributeInfo.name), fieldClass, memberedReference);
} else {
String fieldName = attributeInfo.field.getSimpleName().toString();
JCTree.JCLambda lambda = lambda(
defVar("bean", beanType),
field(ident("bean"), fieldName)
);
return method(objectWritersType, "fieldWriter", literal(fieldName), fieldClass, lambda);
}
}
}
private JCTree.JCMethodInvocation genFieldReader(
JCTree.JCExpression beanType,
AttributeInfo attributeInfo,
JCTree.JCExpression objectReadersType
) {
if (attributeInfo.setMethod == null && attributeInfo.field == null) {
messager.printMessage(Diagnostic.Kind.WARNING, "not implemented yet");
return null;
}
JCTree.JCMethodInvocation readerMethod;
String fieldType = attributeInfo.type.toString();
JCTree.JCLiteral fieldName = literal(attributeInfo.name);
JCTree.JCExpression lambda = null;
if (attributeInfo.setMethod != null) {
lambda = methodRef(beanType, attributeInfo.setMethod.getSimpleName().toString());
}
JCTree.JCExpression identType;
String methodName = null;
switch (fieldType) {
case "byte":
methodName = "fieldReaderByte";
identType = type(TypeTag.BYTE);
break;
case "short":
identType = type(TypeTag.SHORT);
methodName = "fieldReaderShort";
break;
case "int":
identType = type(TypeTag.INT);
methodName = "fieldReaderInt";
break;
case "long":
identType = type(TypeTag.LONG);
methodName = "fieldReaderLong";
break;
case "char":
identType = type(TypeTag.CHAR);
methodName = "fieldReaderChar";
break;
case "float":
identType = type(TypeTag.FLOAT);
methodName = "fieldReaderFloat";
break;
case "double":
identType = type(TypeTag.DOUBLE);
methodName = "fieldReaderDouble";
break;
case "boolean":
identType = type(TypeTag.BOOLEAN);
methodName = "fieldReaderBool";
break;
case "java.lang.String":
identType = qualIdent("java.lang.String");
methodName = "fieldReaderString";
break;
default:
identType = getFieldValueType(fieldType);
break;
}
if (lambda == null) {
JCTree.JCVariableDecl object = defVar("o", beanType);
JCTree.JCExpression valueType = identType;
if (fieldType.startsWith("java.util.Map<")) {
valueType = qualIdent("java.util.Map");
}
JCTree.JCVariableDecl fieldValue = defVar("v", valueType);
List args = List.of(object, fieldValue);
lambda = lambda(
args,
assign(
field(
ident("o"),
attributeInfo.field.getSimpleName().toString()),
ident("v")));
}
if (methodName != null) {
return method(objectReadersType, methodName, fieldName, lambda);
}
readerMethod = genFieldReaderList(objectReadersType, fieldType, fieldName, lambda);
if (readerMethod != null) {
return readerMethod;
}
readerMethod = genFieldReaderMap(objectReadersType, fieldType, fieldName, lambda);
if (readerMethod != null) {
return readerMethod;
}
if (fieldType.indexOf('<') == -1) {
readerMethod = method(
objectReadersType,
"fieldReader",
fieldName,
field(getFieldValueType(fieldType), names._class),
lambda
);
} else {
JCTree.JCFieldAccess fieldClassRef = field(beanType, names._class);
String fieldReaderMethodName;
List args;
if (attributeInfo.setMethod != null) {
fieldReaderMethodName = "fieldReaderWithMethod";
args = List.of(literal(attributeInfo.name), fieldClassRef, literal(methodName));
} else {
JCTree.JCLiteral fieldNameLiteral = literal(attributeInfo.field.getSimpleName().toString());
if (fieldName.toString().equals(attributeInfo.name)) {
args = List.of(fieldNameLiteral, fieldClassRef);
} else {
args = List.of(literal(attributeInfo.name), fieldClassRef, fieldNameLiteral);
}
fieldReaderMethodName = "fieldReaderWithField";
}
readerMethod = method(objectReadersType, fieldReaderMethodName, args);
}
return readerMethod;
}
private JCTree.JCMethodInvocation genFieldReaderList(
JCTree.JCExpression objectReadersType,
String fieldType,
JCTree.JCLiteral fieldName,
JCTree.JCExpression lambda
) {
String listType = null, itemType = null;
String[] listTypes = {"java.util.List", "java.util.ArrayList"};
for (String item : listTypes) {
if (fieldType.startsWith(item)) {
if (fieldType.length() != item.length()
&& fieldType.charAt(item.length()) == '<'
) {
int lastIndex = fieldType.lastIndexOf('>');
String temp = fieldType.substring(item.length() + 1, lastIndex);
if (temp.indexOf(',') == -1 && temp.indexOf('?') == -1) {
listType = item;
itemType = temp;
}
break;
}
}
}
if (listType == null) {
return null;
}
JCTree.JCMethodInvocation readerMethod;
if ("java.lang.String".equals(itemType) && "java.util.List".equals(listType)) {
readerMethod = method(
objectReadersType,
"fieldReaderListStr",
fieldName,
lambda
);
} else {
readerMethod = method(
objectReadersType,
"fieldReaderList",
fieldName,
field(getFieldValueType(itemType), names._class),
constructorRef(qualIdent("java.util.ArrayList")),
lambda
);
}
return readerMethod;
}
private JCTree.JCMethodInvocation genFieldReaderMap(
JCTree.JCExpression objectReadersType,
String fieldType,
JCTree.JCLiteral fieldName,
JCTree.JCExpression lambda
) {
String mapType = null, keyType = null, valueType = null;
String[] mapTypes = {"java.util.Map", "java.util.HashMap", "java.util.TreeMap"};
for (String item : mapTypes) {
if (fieldType.startsWith(item)) {
if (fieldType.length() != item.length()
&& fieldType.charAt(item.length()) == '<'
) {
int lastIndex = fieldType.lastIndexOf('>');
String keyValueType = fieldType.substring(item.length() + 1, lastIndex);
if (keyValueType.indexOf('<') == -1 && keyValueType.indexOf('?') == -1) {
int commaIndex = keyValueType.indexOf(',');
if (commaIndex == -1) {
continue;
}
keyType = keyValueType.substring(0, commaIndex);
valueType = keyValueType.substring(commaIndex + 1);
if (keyType.indexOf('<') != -1
|| keyType.indexOf('?') != -1
|| valueType.indexOf('<') != -1
|| valueType.indexOf('?') != -1
) {
keyType = null;
valueType = null;
continue;
}
mapType = item;
}
break;
}
}
}
if (mapType == null) {
return null;
}
return method(
objectReadersType,
"fieldReaderMap",
fieldName,
field(getFieldValueType(mapType), names._class),
field(getFieldValueType(keyType), names._class),
field(getFieldValueType(valueType), names._class),
lambda
);
}
private List genInitFields(int fieldsSize, Class superClass) {
ListBuffer stmts = new ListBuffer<>();
if (ObjectReaderAdapter.class.isAssignableFrom(superClass)) {
JCTree.JCFieldAccess fieldReaders = field(ident(names._this), "fieldReaders");
for (int i = 0; i < fieldsSize; ++i) {
stmts.append(exec(assign(ident(fieldReader(i)), indexed(fieldReaders, literal(i)))));
}
} else if (ObjectWriterAdapter.class.isAssignableFrom(superClass)) {
JCTree.JCFieldAccess fieldWriters = field(ident(names._this), "fieldWriterArray");
for (int i = 0; i < fieldsSize; ++i) {
stmts.append(exec(assign(ident(fieldWriter(i)), cast(qualIdent(FieldWriter.class.getName()), indexed(fieldWriters, literal(i))))));
}
}
return stmts.toList();
}
private JCTree.JCMethodDecl genCreateInstance(JCTree.JCIdent objectType, JCTree.JCNewClass beanNew) {
JCTree.JCVariableDecl featuresVar = defVar("features", TypeTag.LONG);
return defMethod(Flags.PUBLIC, "createInstance", objectType, List.of(featuresVar), block(defReturn(beanNew)));
}
private JCTree.JCMethodDecl genReadObject(
JCTree.JCIdent objectType,
JCTree.JCExpression beanType,
JCTree.JCNewClass beanNew,
java.util.List attributeInfos,
StructInfo structInfo,
boolean isJsonb
) {
int fieldNameLengthMin = 0, fieldNameLengthMax = 0;
for (int i = 0; i < attributeInfos.size(); ++i) {
String fieldName = attributeInfos.get(i).name;
int fieldNameLength = fieldName.getBytes(StandardCharsets.UTF_8).length;
if (i == 0) {
fieldNameLengthMin = fieldNameLength;
fieldNameLengthMax = fieldNameLength;
} else {
fieldNameLengthMin = Math.min(fieldNameLength, fieldNameLengthMin);
fieldNameLengthMax = Math.max(fieldNameLength, fieldNameLengthMax);
}
}
JCTree.JCVariableDecl jsonReaderVar = defVar("jsonReader", qualIdent(JSONReader.class.getName()));
JCTree.JCIdent jsonReaderIdent = ident(jsonReaderVar);
JCTree.JCVariableDecl fieldTypeVar = defVar("fieldType", qualIdent(Type.class.getName()));
JCTree.JCVariableDecl fieldNameVar = defVar("fieldName", objectType);
JCTree.JCVariableDecl featuresVar = defVar("features", TypeTag.LONG);
JCTree.JCReturn nullReturn = defReturn(defNull());
ListBuffer readObjectBody = new ListBuffer<>();
JCTree.JCMethodInvocation nextIfNullMethod = method(jsonReaderIdent, "nextIfNull");
readObjectBody.append(defIf(nextIfNullMethod, nullReturn));
readObjectBody.append(exec(method(jsonReaderIdent, "nextIfObjectStart")));
JCTree.JCVariableDecl features2Var = defVar(
Flags.PARAMETER,
"features2",
TypeTag.LONG,
bitOr(
ident("features"),
field(ident(names._this), "features")
)
);
readObjectBody.append(features2Var);
JCTree.JCVariableDecl objectVar = defVar("object", beanType, beanNew);
JCTree.JCIdent objectIdent = ident(objectVar);
readObjectBody.append(objectVar);
int fieldsSize = attributeInfos.size();
JCTree.JCLabeledStatement loopLabel = label("_while");
JCTree.JCWhileLoop loopHead = whileLoop(unary(JCTree.Tag.NOT, method(jsonReaderIdent, "nextIfObjectEnd")), null);
ListBuffer loopBody = new ListBuffer<>();
boolean switchGen = false;
if (fieldNameLengthMin >= 2 && fieldNameLengthMax <= 43) {
loopBody.appendList(genRead243(attributeInfos, jsonReaderIdent, structInfo, loopLabel, objectIdent, beanType, isJsonb));
switchGen = true;
}
JCTree.JCFieldAccess readFieldNameHashCode = field(jsonReaderIdent, "readFieldNameHashCode");
JCTree.JCVariableDecl hashCode64Var = defVar("hashCode64", TypeTag.LONG, method(readFieldNameHashCode));
JCTree.JCExpression hashCode64 = ident(hashCode64Var);
loopBody.append(hashCode64Var);
if (switchGen && !isJsonb) {
loopBody.append(
exec(method(
field(ident(names._this), "readFieldValue"),
List.of(hashCode64, jsonReaderIdent, ident(features2Var), ident(objectVar))
)));
} else {
if (fieldsSize <= 6) {
for (int i = 0; i < fieldsSize; ++i) {
AttributeInfo attributeInfo = attributeInfos.get(i);
List readFieldValueStmts = genReadFieldValue(
attributeInfo,
jsonReaderIdent,
i,
structInfo,
loopLabel,
objectIdent,
beanType,
isJsonb);
loopBody.appendList(List.of(defIf(eq(hashCode64, attributeInfo.nameHashCode), block(readFieldValueStmts))));
}
} else {
Map> map = new TreeMap<>();
Map mapping = new TreeMap<>();
Map mappingIndex = new TreeMap<>();
for (int i = 0; i < fieldsSize; ++i) {
AttributeInfo attr = attributeInfos.get(i);
long fieldNameHash = attr.nameHashCode;
int hashCode32 = (int) (fieldNameHash ^ (fieldNameHash >>> 32));
java.util.List hashCode64List = map.computeIfAbsent(hashCode32, k -> new ArrayList<>());
hashCode64List.add(fieldNameHash);
mapping.put(fieldNameHash, attr);
mappingIndex.put(fieldNameHash, i);
}
int[] hashCode32Keys = new int[map.size()];
int off = 0;
for (Integer key : map.keySet()) {
hashCode32Keys[off++] = key;
}
Arrays.sort(hashCode32Keys);
JCTree.JCVariableDecl hashCode32Var = getHashCode32Var(hashCode64);
loopBody.append(hashCode32Var);
JCTree.JCExpression hashCode32 = ident(hashCode32Var);
JCTree.JCLabeledStatement switchLabel = label("_switch");
ListBuffer cases = new ListBuffer<>();
for (int i = 0; i < hashCode32Keys.length; ++i) {
java.util.List hashCode64Array = map.get(hashCode32Keys[i]);
List stmts = List.nil();
Long fieldNameHash = null;
if (hashCode64Array.size() == 1 && hashCode64Array.get(0) == hashCode32Keys[i]) {
fieldNameHash = hashCode64Array.get(0);
int index = mappingIndex.get(fieldNameHash);
AttributeInfo attributeInfo = mapping.get(fieldNameHash);
stmts = stmts.appendList(genReadFieldValue(
attributeInfo,
jsonReaderIdent,
index,
structInfo,
loopLabel,
objectIdent,
beanType,
isJsonb));
stmts.append(defContinue(loopLabel));
} else {
for (int j = 0; j < hashCode64Array.size(); ++j) {
fieldNameHash = hashCode64Array.get(j);
int index = mappingIndex.get(fieldNameHash);
AttributeInfo field = mapping.get(fieldNameHash);
List stmtsIf = genReadFieldValue(
field,
jsonReaderIdent,
index,
structInfo,
loopLabel,
objectIdent,
beanType,
isJsonb);
stmts = stmts.append(defIf(eq(hashCode64, fieldNameHash), block(stmtsIf)));
stmts.append(defContinue(loopLabel));
}
stmts.append(defBreak(switchLabel));
}
cases.append(defCase(getHashCode32Var(literal(fieldNameHash)).getInitializer(), stmts));
}
switchLabel.body = defSwitch(hashCode32, cases.toList());
loopBody.append(switchLabel);
}
loopBody.append(
defIf(
method(
ident(names._this),
"readFieldValueWithLCase",
jsonReaderIdent,
objectIdent,
ident(hashCode64Var),
ident(features2Var)
),
defContinue(loopLabel)
)
);
JCTree.JCFieldAccess processExtraField = field(ident(names._this), "processExtra");
loopBody.append(exec(method(processExtraField, jsonReaderIdent, objectIdent, ident(features2Var))));
}
loopHead.body = block(loopBody.toList());
loopLabel.body = loopHead;
readObjectBody.append(loopLabel);
if (!isJsonb) {
readObjectBody.append(exec(method(jsonReaderIdent, "nextIfComma")));
}
readObjectBody.append(defReturn(objectIdent));
return defMethod(
Flags.PUBLIC,
isJsonb ? "readJSONBObject" : "readObject",
objectType,
List.of(jsonReaderVar, fieldTypeVar, fieldNameVar, featuresVar),
block(readObjectBody.toList())
);
}
private JCTree.JCMethodDecl genWrite(
JCTree.JCIdent objectType,
JCTree.JCExpression beanType,
JCTree.JCNewClass beanNew,
java.util.List attributeInfos,
StructInfo structInfo,
boolean jsonb
) {
int fieldNameLengthMin = 0, fieldNameLengthMax = 0;
for (int i = 0; i < attributeInfos.size(); ++i) {
String fieldName = attributeInfos.get(i).name;
int fieldNameLength = fieldName.getBytes(StandardCharsets.UTF_8).length;
if (i == 0) {
fieldNameLengthMin = fieldNameLength;
fieldNameLengthMax = fieldNameLength;
} else {
fieldNameLengthMin = Math.min(fieldNameLength, fieldNameLengthMin);
fieldNameLengthMax = Math.max(fieldNameLength, fieldNameLengthMax);
}
}
ListBuffer writeBody = new ListBuffer<>();
MethodWriterContext mwc = new MethodWriterContext(beanType, objectType, jsonb);
mwc.genVariantsMethodBefore(writeBody);
writeBody.append(
defIfReturn(
ne(bitAnd(mwc.contextFeatures, IgnoreErrorGetter.mask | UnquoteFieldName.mask), 0L),
exec(method(
names._super,
"write",
mwc.jsonWriter,
mwc.object,
mwc.fieldName,
mwc.fieldType,
mwc.features
))
)
);
writeBody.append(
defIfReturn(
mwc.jsonWriterField("jsonb"),
defIf(
ne(bitAnd(mwc.contextFeatures, literal(BeanToArray.mask)), 0L),
block(exec(method(
names._this,
"writeArrayMappingJSONB",
mwc.jsonWriter,
mwc.object,
mwc.fieldName,
mwc.fieldType,
mwc.features))
),
block(exec(method(
names._this,
"writeJSONB",
mwc.jsonWriter,
mwc.object,
mwc.fieldName,
mwc.fieldType,
mwc.features))
)
)
)
);
writeBody.append(
defIfReturn(
ne(bitAnd(mwc.contextFeatures, BeanToArray.mask), 0L),
exec(method(
names._this,
"writeArrayMapping",
mwc.jsonWriter,
mwc.object,
mwc.fieldName,
mwc.fieldType,
mwc.features))
)
);
writeBody.append(
defIfReturn(
method(names._this, "hasFilter", mwc.jsonWriter),
exec(
method(
names._this,
"writeWithFilter",
mwc.jsonWriter,
mwc.object,
mwc.fieldName,
mwc.fieldType,
mwc.features
)
)
)
);
writeBody.append(
defIfReturn(
ne(bitAnd(mwc.contextFeatures, IgnoreNoneSerializable.mask), 0L),
exec(mwc.jsonWriterMethod("writeNull"))
)
);
writeBody.append(
defIfReturn(
ne(bitAnd(mwc.contextFeatures, ErrorOnNoneSerializable.mask), 0L),
exec(method(names._this, "errorOnNoneSerializable"))
)
);
writeBody.append(exec(mwc.jsonWriterMethod("startObject")));
JCTree.JCVariableDecl var7Var = defVar("var7", true);
writeBody.append(var7Var);
writeBody.append(
defIf(
and(
notNull(mwc.object),
and(
ne(method(mwc.object, "getClass"), mwc.fieldType),
method(
mwc.jsonWriter,
"isWriteTypeInfo",
mwc.object,
mwc.fieldType,
mwc.features
)
)
),
block(exec(
assign(
ident(var7Var),
bitXor(
method(names._this, "writeTypeInfo", mwc.jsonWriter),
literal(true)
)
)
)),
null));
for (int i = 0; i < attributeInfos.size(); ++i) {
AttributeInfo attributeInfo = attributeInfos.get(i);
writeBody.appendList(
genWriteField(
mwc,
attributeInfo,
i
)
);
}
writeBody.append(exec(mwc.jsonWriterMethod("endObject")));
return defMethod(
Flags.PUBLIC,
"write",
type(TypeTag.VOID),
List.of(
defVar("jsonWriter", qualIdent(JSONWriter.class.getName())),
defVar("object", objectType),
defVar("fieldName", objectType),
defVar("fieldType", qualIdent(Type.class.getName())),
defVar("features", TypeTag.LONG)
),
block(writeBody.toList())
);
}
private JCTree.JCStatement genWriteFieldName(MethodWriterContext mwc, AttributeInfo attributeInfo, int i) {
String methodName;
if (!mwc.jsonb) {
byte[] fieldNameUTF8 = attributeInfo.name.getBytes(StandardCharsets.UTF_8);
boolean asciiName = true;
for (int j = 0; j < fieldNameUTF8.length; j++) {
if (fieldNameUTF8[j] < 0) {
asciiName = false;
break;
}
}
int length = fieldNameUTF8.length;
if (length >= 2 && length <= 16 && asciiName) {
long name1 = 0;
int name12 = 0;
long name1SQ = 0;
int name1SQ2 = 0;
byte[] bytes = new byte[8];
switch (length) {
case 2:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 2);
bytes[3] = '"';
bytes[4] = ':';
methodName = "writeName2Raw";
break;
case 3:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 3);
bytes[4] = '"';
bytes[5] = ':';
methodName = "writeName3Raw";
break;
case 4:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 4);
bytes[5] = '"';
bytes[6] = ':';
methodName = "writeName4Raw";
break;
case 5:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 5);
bytes[6] = '"';
bytes[7] = ':';
methodName = "writeName5Raw";
break;
case 6:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 6);
bytes[7] = '"';
methodName = "writeName6Raw";
break;
case 7:
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
methodName = "writeName7Raw";
break;
case 8: {
bytes = fieldNameUTF8;
methodName = "writeName8Raw";
break;
}
case 9: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
byte[] name1Bytes = new byte[4];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = '"';
name1Bytes[3] = ':';
name12 = UNSAFE.getInt(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
name1Bytes[2] = '\'';
name1SQ2 = UNSAFE.getInt(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName9Raw";
break;
}
case 10: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
byte[] name1Bytes = new byte[8];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = fieldNameUTF8[9];
name1Bytes[3] = '"';
name1Bytes[4] = ':';
name1 = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
name1Bytes[3] = '\'';
name1SQ = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName10Raw";
break;
}
case 11: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
byte[] name1Bytes = new byte[8];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = fieldNameUTF8[9];
name1Bytes[3] = fieldNameUTF8[10];
name1Bytes[4] = '"';
name1Bytes[5] = ':';
name1 = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
name1Bytes[4] = '\'';
name1SQ = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName11Raw";
break;
}
case 12: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
byte[] name1Bytes = new byte[8];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = fieldNameUTF8[9];
name1Bytes[3] = fieldNameUTF8[10];
name1Bytes[4] = fieldNameUTF8[11];
name1Bytes[5] = '"';
name1Bytes[6] = ':';
name1 = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
name1Bytes[5] = '\'';
name1SQ = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName12Raw";
break;
}
case 13: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
byte[] name1Bytes = new byte[8];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = fieldNameUTF8[9];
name1Bytes[3] = fieldNameUTF8[10];
name1Bytes[4] = fieldNameUTF8[11];
name1Bytes[5] = fieldNameUTF8[12];
name1Bytes[6] = '"';
name1Bytes[7] = ':';
name1 = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
name1Bytes[6] = '\'';
name1SQ = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName13Raw";
break;
}
case 14: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
byte[] name1Bytes = new byte[8];
name1Bytes[0] = fieldNameUTF8[7];
name1Bytes[1] = fieldNameUTF8[8];
name1Bytes[2] = fieldNameUTF8[9];
name1Bytes[3] = fieldNameUTF8[10];
name1Bytes[4] = fieldNameUTF8[11];
name1Bytes[5] = fieldNameUTF8[12];
name1Bytes[6] = fieldNameUTF8[13];
name1Bytes[7] = '"';
name1 = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
name1Bytes[7] = '\'';
name1SQ = UNSAFE.getLong(name1Bytes, ARRAY_BYTE_BASE_OFFSET);
methodName = "writeName14Raw";
break;
}
case 15: {
bytes[0] = '"';
System.arraycopy(fieldNameUTF8, 0, bytes, 1, 7);
name1 = UNSAFE.getLong(fieldNameUTF8, ARRAY_BYTE_BASE_OFFSET + 7);
name1SQ = name1;
methodName = "writeName15Raw";
break;
}
case 16: {
System.arraycopy(fieldNameUTF8, 0, bytes, 0, 8);
name1 = UNSAFE.getLong(fieldNameUTF8, ARRAY_BYTE_BASE_OFFSET + 8);
name1SQ = name1;
methodName = "writeName16Raw";
break;
}
default:
throw new IllegalStateException("length : " + length);
}
long nameIn64DoubleQuote = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET);
for (int j = 0; j < bytes.length; j++) {
if (bytes[j] == '"') {
bytes[j] = '\'';
}
}
long nameIn64SingleQuote = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET);
JCTree.JCConditional ternary = ternary(mwc.nameDirect, literal(nameIn64DoubleQuote), literal(nameIn64SingleQuote));
if (length == 9) {
ListBuffer stmts = new ListBuffer<>();
JCTree.JCConditional ternary2 = ternary(mwc.nameDirect, name12, name1SQ2);
JCTree.JCVariableDecl name1Var = defVar("name1", TypeTag.INT, ternary2);
stmts.append(defVar("name1", TypeTag.INT, ternary2));
stmts.append(exec(mwc.jsonWriterMethod(methodName, ternary, name1Var)));
return block(stmts.toList());
} else if (length > 9) {
JCTree.JCConditional ternary2 = ternary(mwc.nameDirect, name1, name1SQ);
return exec(mwc.jsonWriterMethod(methodName, ternary, ternary2));
} else {
return exec(mwc.jsonWriterMethod(methodName, ternary));
}
}
} else {
byte[] fieldNameUTF8 = JSONB.toBytes(attributeInfo.name);
int length = fieldNameUTF8.length;
byte[] bytes = Arrays.copyOf(fieldNameUTF8, 16);
switch (length) {
case 2:
methodName = "writeName2Raw";
break;
case 3:
methodName = "writeName3Raw";
break;
case 4:
methodName = "writeName4Raw";
break;
case 5:
methodName = "writeName5Raw";
break;
case 6:
methodName = "writeName6Raw";
break;
case 7:
methodName = "writeName7Raw";
break;
case 8:
methodName = "writeName8Raw";
break;
case 9:
methodName = "writeName9Raw";
break;
case 10:
methodName = "writeName10Raw";
break;
case 11:
methodName = "writeName11Raw";
break;
case 12:
methodName = "writeName12Raw";
break;
case 13:
methodName = "writeName13Raw";
break;
case 14:
methodName = "writeName14Raw";
break;
case 15:
methodName = "writeName15Raw";
break;
case 16:
methodName = "writeName16Raw";
break;
default:
break;
}
}
return exec(method(field(names._this, fieldWriter(i)), mwc.jsonb ? "writeFieldNameJSONB" : "writeFieldName", mwc.jsonWriter));
}
private ListBuffer genWriteField(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
if ("boolean".equals(type)) {
return genWriteFieldValueBooleanV(mwc, attributeInfo, i);
} else if ("boolean[]".equals(type)
|| "byte[]".equals(type)
|| "char[]".equals(type)
|| "short[]".equals(type)
|| "float[]".equals(type)
|| "double[]".equals(type)) {
return stmts.appendList(genWriteFieldValueArray(mwc, attributeInfo, i));
} else if ("int".equals(type)) {
return stmts.appendList(genWriteFieldValueInt32V(mwc, attributeInfo, i));
} else if ("char".equals(type)
|| "byte".equals(type)
|| "int".equals(type)
|| "short".equals(type)
|| "float".equals(type)
|| "double".equals(type)) {
stmts.append(genWriteFieldName(mwc, attributeInfo, i));
return stmts.appendList(genWriteFieldValue(mwc, attributeInfo, i, null));
} else if ("int[]".equals(type)) {
return stmts.appendList(genWriteFieldValueIntVA(mwc, attributeInfo, i));
} else if ("long".equals(type)) {
return stmts.appendList(genWriteFieldValueInt64V(mwc, attributeInfo, i));
} else if ("long[]".equals(type)) {
return stmts.appendList(genWriteFieldValueInt64VA(mwc, attributeInfo, i));
} else if ("java.lang.Integer".equals(type)) {
return stmts.appendList(genWriteInt32(mwc, attributeInfo, i));
} else if ("java.lang.Long".equals(type)) {
return stmts.appendList(genWriteInt64(mwc, attributeInfo, i));
} else if ("java.lang.Float".equals(type)) {
return stmts.appendList(genWriteFloat(mwc, attributeInfo, i));
} else if ("java.lang.Double".equals(type)) {
return stmts.appendList(genWriteDouble(mwc, attributeInfo, i));
} else if ("java.math.BigDecimal".equals(type)) {
return stmts.appendList(genWriteBigDecimal(mwc, attributeInfo, i));
} else if ("java.lang.Boolean".equals(type)) {
return stmts.appendList(genWriteBoolean(mwc, attributeInfo, i));
} else if ("java.lang.String".equals(type)) {
return stmts.appendList(genWriteFieldValueString(mwc, attributeInfo, i));
} else if (attributeInfo.type instanceof com.sun.tools.javac.code.Type.ClassType
&& ((com.sun.tools.javac.code.Type.ClassType) attributeInfo.type).supertype_field != null
&& "java.lang.Enum".equals(((com.sun.tools.javac.code.Type.ClassType) attributeInfo.type).supertype_field.tsym.toString())) {
return stmts.appendList(genWriteFieldValueEnum(mwc, attributeInfo, i));
} else if ("java.util.Date".equals(type)) {
return stmts.appendList(genWriteFieldValueDate(mwc, attributeInfo, i));
} else if (type.contains("java.util.List")) {
return stmts.appendList(genWriteFieldValueList(mwc, attributeInfo, i));
} else {
return stmts.appendList(genWriteFieldValueObject(mwc, attributeInfo, i));
}
}
private ListBuffer genWriteFieldValue(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i,
JCTree.JCExpression fieldValue
) {
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
if (fieldValue == null) {
fieldValue = genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType);
}
List fieldValueExprs = List.of(fieldValue);
JCTree.JCBinary writeAsStringBinary = ne(
bitAnd(
field(field(ident(names._this), fieldWriter(i)), "features"),
WriteNonStringValueAsString.mask
),
0
);
if ("boolean".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeBool", fieldValueExprs)));
} else if ("char".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeChar", fieldValueExprs)));
} else if ("byte".equals(type)) {
stmts.append(defIf(writeAsStringBinary,
block(exec(mwc.jsonWriterMethod("writeString", fieldValueExprs))),
block(exec(mwc.jsonWriterMethod("writeInt8", fieldValueExprs)))));
} else if ("short".equals(type)) {
stmts.append(defIf(writeAsStringBinary,
block(exec(mwc.jsonWriterMethod("writeString", fieldValueExprs))),
block(exec(mwc.jsonWriterMethod("writeInt16", fieldValueExprs)))));
} else if ("int".equals(type)) {
stmts.append(defIf(writeAsStringBinary,
block(exec(mwc.jsonWriterMethod("writeString", fieldValueExprs))),
block(exec(mwc.jsonWriterMethod("writeInt32", fieldValueExprs)))));
} else if ("Integer".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeInt32", fieldValueExprs)));
} else if ("long".equals(type)) {
stmts.append(defIf(writeAsStringBinary,
block(exec(mwc.jsonWriterMethod("writeString", fieldValueExprs))),
block(exec(mwc.jsonWriterMethod("writeInt64", fieldValueExprs)))));
} else if ("Long".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeInt64", fieldValueExprs)));
} else if ("float".equals(type)) {
stmts.append(defIf(writeAsStringBinary,
block(exec(mwc.jsonWriterMethod("writeString", fieldValueExprs))),
block(exec(mwc.jsonWriterMethod("writeFloat", fieldValueExprs)))));
} else if ("double".equals(type)) {
stmts.append(defIf(writeAsStringBinary,
block(exec(mwc.jsonWriterMethod("writeString", fieldValueExprs))),
block(exec(mwc.jsonWriterMethod("writeDouble", fieldValueExprs)))));
} else if ("boolean[]".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeBool", fieldValueExprs)));
} else if ("char[]".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeString", fieldValueExprs)));
} else if ("byte[]".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeBinary", fieldValueExprs)));
} else if ("short[]".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeInt16", fieldValueExprs)));
} else if ("int[]".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeInt32", fieldValueExprs)));
} else if ("long[]".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeInt64", fieldValueExprs)));
} else if ("float[]".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeFloat", fieldValueExprs)));
} else if ("double[]".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeDouble", fieldValueExprs)));
} else if ("BigDecimal".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeDecimal", fieldValueExprs)));
} else if ("Enum".equals(type)) {
stmts.append(exec(mwc.jsonWriterMethod("writeEnum", fieldValueExprs)));
} else {
throw new UnsupportedOperationException();
}
return stmts;
}
private ListBuffer genWriteFieldValueBooleanV(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
JCTree.JCVariableDecl boolVar = defVar("bool" + i, TypeTag.BOOLEAN, genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(boolVar);
stmts.append(defIf(unary(JCTree.Tag.NOT, ident(boolVar)), block(List.nil())));
stmts.append(exec(method(field(names._this, fieldWriter(i)), "writeBool", mwc.jsonWriter, boolVar)));
return stmts;
}
private ListBuffer genWriteFieldValueArray(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
String type = attributeInfo.type.toString();
String methodName;
ListBuffer stmts = new ListBuffer<>();
List fieldValueExprs = List.of(mwc.jsonWriter, genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
if ("char[]".equals(type)) {
methodName = "writeString";
} else if ("boolean[]".equals(type)) {
methodName = "writeBool";
} else if ("byte[]".equals(type)) {
methodName = "writeBinary";
} else if ("short[]".equals(type)) {
methodName = "writeInt16";
} else if ("float[]".equals(type)) {
methodName = "writeFloat";
} else if ("double[]".equals(type)) {
methodName = "writeDouble";
} else if ("enum".equals(type)) {
methodName = "writeEnumJSONB";
} else {
throw new UnsupportedOperationException();
}
return stmts.append(exec(method(field(names._this, fieldWriter(i)), methodName, fieldValueExprs)));
}
private ListBuffer genWriteFieldValueInt32V(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
JCTree.JCVariableDecl int32Var = defVar("int32" + i, TypeTag.INT, genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(int32Var);
ListBuffer ifStmts = new ListBuffer<>();
ifStmts.append(genWriteFieldName(mwc, attributeInfo, i));
ifStmts.appendList(
genWriteFieldValue(mwc, attributeInfo, i, ident(int32Var)));
stmts.append(defIf(
or(ne(int32Var, 0), not(mwc.notWriteDefaultValue)),
block(ifStmts.toList())));
return stmts;
}
private ListBuffer genWriteFieldValueIntVA(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String elemType = ((ArrayType) attributeInfo.type).getComponentType().toString();
JCTree.JCVariableDecl intArrayVar = defVar("intArray" + i, arrayIdentType(elemType), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(intArrayVar);
ListBuffer notZeroStmts = new ListBuffer<>();
notZeroStmts.append(genWriteFieldName(mwc, attributeInfo, i));
notZeroStmts.append(exec(mwc.jsonWriterMethod("writeArrayNull")));
ListBuffer nullStmts = new ListBuffer<>();
nullStmts.append(defIf(mwc.writeNulls, block(notZeroStmts.toList())));
ListBuffer notNullStmts = new ListBuffer<>();
notNullStmts.append(genWriteFieldName(mwc, attributeInfo, i));
notNullStmts.append(exec(mwc.jsonWriterMethod("writeInt32", intArrayVar)));
stmts.append(defIf(eq(intArrayVar, defNull()), block(nullStmts.toList()), block(notNullStmts.toList())));
return stmts;
}
private ListBuffer genWriteFieldValueInt64V(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
JCTree.JCVariableDecl int64Var = defVar("int64" + i, TypeTag.LONG, genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(int64Var);
ListBuffer ifStmts = new ListBuffer<>();
ifStmts.append(genWriteFieldName(mwc, attributeInfo, i));
ifStmts.appendList(genWriteFieldValue(mwc, attributeInfo, i, ident(int64Var)));
stmts.append(defIf(or(ne(int64Var, 0), not(mwc.notWriteDefaultValue)),
block(ifStmts.toList()),
null));
return stmts;
}
private ListBuffer genWriteFieldValueInt64VA(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String elemType = ((ArrayType) attributeInfo.type).getComponentType().toString();
JCTree.JCVariableDecl longArrayVar = defVar("longArray" + i, arrayIdentType(elemType), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(longArrayVar);
ListBuffer notZeroStmts = new ListBuffer<>();
notZeroStmts.append(genWriteFieldName(mwc, attributeInfo, i));
notZeroStmts.append(exec(mwc.jsonWriterMethod("writeArrayNull")));
ListBuffer nullStmts = new ListBuffer<>();
nullStmts.append(defIf(mwc.writeNulls, block(notZeroStmts.toList())));
ListBuffer notNullStmts = new ListBuffer<>();
notNullStmts.append(genWriteFieldName(mwc, attributeInfo, i));
notNullStmts.append(exec(mwc.jsonWriterMethod("writeInt64", longArrayVar)));
stmts.append(defIf(eq(longArrayVar, defNull()), block(nullStmts.toList()), block(notNullStmts.toList())));
return stmts;
}
private ListBuffer genWriteBigDecimal(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
JCTree.JCVariableDecl fieldValue = defVar("bigDecimal" + i, qualIdent(type), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(fieldValue);
stmts.append(
defIf(
or(notNull(fieldValue), isEnable(mwc.contextFeatures, WriteNulls)),
block(
genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod("writeDecimal", fieldValue))
)
)
);
return stmts;
}
private ListBuffer genWriteBoolean(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
JCTree.JCVariableDecl fieldValue = defVar("Boolean" + i, qualIdent(type), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(fieldValue);
stmts.append(
defIf(
or(notNull(fieldValue), isEnable(mwc.contextFeatures, WriteNulls)),
block(
genWriteFieldName(mwc, attributeInfo, i),
defIf(
notNull(fieldValue),
block(
exec(mwc.jsonWriterMethod("writeBool", fieldValue))
),
block(
exec(mwc.jsonWriterMethod("writeNull"))
)
)
)
)
);
return stmts;
}
private ListBuffer genWriteInt32(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
JCTree.JCVariableDecl integerVar = defVar("integer" + i, qualIdent(type), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(integerVar);
stmts.append(
defIf(
ne(integerVar, defNull()),
block(
genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod("writeInt32", integerVar))
),
defIf(
isEnable(mwc.contextFeatures, WriteNulls, NullAsDefaultValue, WriteNullNumberAsZero),
block(
genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod("writeNumberNull"))
)
)
)
);
return stmts;
}
private ListBuffer genWriteInt64(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
JCTree.JCVariableDecl integerVar = defVar("long" + i, qualIdent(type), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(integerVar);
stmts.append(
defIf(
ne(integerVar, defNull()),
block(
genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod("writeInt64", integerVar))
),
defIf(
isEnable(mwc.contextFeatures, WriteNulls, NullAsDefaultValue, WriteNullNumberAsZero),
block(
genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod("writeInt64Null"))
)
)
)
);
return stmts;
}
private ListBuffer genWriteFloat(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
JCTree.JCVariableDecl floatVar = defVar("float" + i, qualIdent(type), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(floatVar);
ListBuffer notZeroStmts = new ListBuffer<>();
notZeroStmts.append(genWriteFieldName(mwc, attributeInfo, i));
notZeroStmts.append(exec(mwc.jsonWriterMethod("writeNumberNull")));
ListBuffer nullStmts = new ListBuffer<>();
JCTree.JCExpression writeAsStringBinary = literal(BrowserCompatible.mask | WriteBooleanAsNumber.mask | WriteNullStringAsEmpty.mask);
nullStmts.append(defIf(ne(bitAnd(mwc.contextFeatures, writeAsStringBinary), 0), block(notZeroStmts.toList())));
ListBuffer notNullStmts = new ListBuffer<>();
notNullStmts.append(exec(method(field(names._this, fieldWriter(i)), "writeFloat", mwc.jsonWriter, floatVar)));
stmts.append(defIf(eq(floatVar, defNull()), block(nullStmts.toList()), block(notNullStmts.toList())));
return stmts;
}
private ListBuffer genWriteDouble(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
JCTree.JCVariableDecl doubleVar = defVar("double" + i, qualIdent(type), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(doubleVar);
ListBuffer notZeroStmts = new ListBuffer<>();
notZeroStmts.append(genWriteFieldName(mwc, attributeInfo, i));
notZeroStmts.append(exec(mwc.jsonWriterMethod("writeNumberNull")));
ListBuffer nullStmts = new ListBuffer<>();
JCTree.JCExpression writeAsStringBinary = literal(BrowserCompatible.mask | WriteBooleanAsNumber.mask | WriteNullStringAsEmpty.mask);
nullStmts.append(defIf(ne(bitAnd(mwc.contextFeatures, writeAsStringBinary), 0), block(notZeroStmts.toList())));
ListBuffer notNullStmts = new ListBuffer<>();
notNullStmts.append(exec(method(field(names._this, fieldWriter(i)), "writeDouble", mwc.jsonWriter, doubleVar)));
stmts.append(defIf(eq(doubleVar, defNull()), block(nullStmts.toList()), block(notNullStmts.toList())));
return stmts;
}
private ListBuffer genWriteFieldValueString(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
final long writeNullFeatures = WriteNulls.mask | NullAsDefaultValue.mask | WriteNullStringAsEmpty.mask;
final long writeNullAsEmptyFeatures = JSONWriter.Feature.NullAsDefaultValue.mask | JSONWriter.Feature.WriteNullStringAsEmpty.mask;
JCTree.JCIdent fieldValue = ident("string" + i);
ListBuffer stmts = new ListBuffer<>();
stmts.append(genWriteFieldName(mwc, attributeInfo, i));
stmts.append(
defVar(
fieldValue.name,
qualIdent(attributeInfo.type.toString()),
genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType)
)
);
stmts.append(
defIf(
notNull(fieldValue),
block(exec(mwc.jsonWriterMethod("writeString", fieldValue))),
block(defIf(
ne(bitAnd(mwc.contextFeatures, writeNullFeatures), 0L),
defIf(
ne(bitAnd(mwc.contextFeatures, writeNullAsEmptyFeatures), 0L),
block(exec(mwc.jsonWriterMethod("writeString", ""))),
block(exec(mwc.jsonWriterMethod("writeStringNull")))
)
))
)
);
return stmts;
}
private ListBuffer genWriteFieldValueEnum(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
JCTree.JCVariableDecl enumVar = defVar("enum" + i, qualIdent(type), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(enumVar);
stmts.append(
defIf(
ne(enumVar, defNull()),
block(
method(
field(names._this, fieldWriter(i)),
"writeEnum",
mwc.jsonWriter,
ident(enumVar)
)
),
defIf(
mwc.writeNulls,
block(
genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod("writeNull"))
)
)
)
);
return stmts;
}
private ListBuffer genWriteFieldValueDate(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
JCTree.JCVariableDecl dateVar = defVar("date" + i, qualIdent(type), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(dateVar);
stmts.append(
defIf(
ne(dateVar, defNull()),
block(
exec(method(
field(names._this, fieldWriter(i)),
"writeDate",
mwc.jsonWriter,
method(dateVar, "getTime")
))
),
defIf(
mwc.writeNulls,
block(
genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod("writeNull"))
)
)
)
);
return stmts;
}
private ListBuffer genWriteFieldValueList(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
JCTree.JCVariableDecl listStrVar = defVar("listStr" + i, ident("String"), defNull());
stmts.append(listStrVar);
JCTree.JCVariableDecl listVar = defVar("list" + i, qualIdent("java.util.List"), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
stmts.append(listVar);
JCTree.JCLabeledStatement label = label("listLabel" + i);
ListBuffer notNullStmts = new ListBuffer<>();
ListBuffer labelStmts = new ListBuffer<>();
ListBuffer notZeroStmts = new ListBuffer<>();
notZeroStmts.append(defIf(eq(mwc.object, listVar),
block(exec(mwc.jsonWriterMethod("writeReference", "..")),
defBreak(label))));
notZeroStmts.append(exec(assign(listStrVar, mwc.jsonWriterMethod("setPath", field(ident(names._this), fieldWriter(i)), listVar))));
notZeroStmts.append(defIf(ne(listStrVar, defNull()),
block(exec(mwc.jsonWriterMethod("writeReference", listStrVar)),
exec(mwc.jsonWriterMethod("popPath", listVar)),
defBreak(label))));
labelStmts.append(defIf(ne(bitAnd(mwc.contextFeatures, ReferenceDetection.mask), 0L), block(notZeroStmts.toList())));
JCTree.JCBinary binary = eq(bitAnd(mwc.contextFeatures, NotWriteEmptyArray), 0L);
JCTree.JCUnary unary = unary(JCTree.Tag.NOT, method(listVar, "isEmpty"));
ListBuffer notEmptyStmts = new ListBuffer<>();
notEmptyStmts.append(genWriteFieldName(mwc, attributeInfo, i));
String type = attributeInfo.type.toString();
if ("java.util.List".equals(type)) {
notEmptyStmts.append(exec(mwc.jsonWriterMethod("writeString", listVar)));
} else {
notEmptyStmts.append(
exec(method(
field(names._this, fieldWriter(i)),
"writeListValue",
mwc.jsonWriter,
listVar
))
);
}
notEmptyStmts.append(exec(mwc.jsonWriterMethod("popPath", listVar)));
labelStmts.append(defIf(or(binary, unary), block(notEmptyStmts.toList())));
JCTree.JCExpression writeAsStringBinary = literal(WriteNulls.mask | NullAsDefaultValue.mask | WriteNullListAsEmpty.mask);
JCTree.JCIf notNUllIf = defIf(ne(bitAnd(mwc.contextFeatures, writeAsStringBinary), 0L),
block(
genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod("writeArrayNull"))
)
);
label.body = block(labelStmts.toList());
notNullStmts.append(label);
stmts.append(defIf(ne(listVar, defNull()), block(notNullStmts.toList()), block(notNUllIf)));
return stmts;
}
private JCTree.JCExpression genWriteFieldValue(AttributeInfo attributeInfo,
JCTree.JCIdent objectIdent,
JCTree.JCExpression beanType) {
if (attributeInfo.getMethod != null) {
return method(cast(beanType, objectIdent), attributeInfo.getMethod.getSimpleName().toString());
} else {
String name = attributeInfo.name;
VariableElement field = attributeInfo.field;
if (field instanceof Symbol.VarSymbol) {
Name symbolName = ((Symbol.VarSymbol) field).name;
if (symbolName != null) {
String fieldName = symbolName.toString();
if (!name.equals(fieldName)) {
name = fieldName;
}
}
}
return field(cast(beanType, objectIdent), name);
}
}
private ListBuffer genWriteFieldValueObject(
MethodWriterContext mwc,
AttributeInfo attributeInfo,
int i
) {
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
if (type.contains("[")) {
JCTree.JCVariableDecl objectStrVar = defVar("objectStr" + i, ident("String"), defNull());
stmts.append(objectStrVar);
JCTree.JCVariableDecl objectIntVar = defVar("objectInt" + i, 0);
stmts.append(objectIntVar);
JCTree.JCLabeledStatement outerLabel = label("objectOuterLabel" + i);
ListBuffer outerLabelStmts = new ListBuffer<>();
String elemType = ((ArrayType) attributeInfo.type).getComponentType().toString();
JCTree.JCVariableDecl objectVar = defVar("object" + i, arrayIdentType(elemType), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
outerLabelStmts.append(objectVar);
JCTree.JCLabeledStatement innerLabel = label("objectInnerLabel" + i);
ListBuffer innerLabelStmts = new ListBuffer<>();
ListBuffer notNullStmts = new ListBuffer<>();
JCTree.JCVariableDecl objectLongVar = defVar("objectLong" + i, TypeTag.LONG, bitAnd(mwc.contextFeatures, ReferenceDetection.mask));
notNullStmts.append(objectLongVar);
notNullStmts.append(exec(
assign(
objectIntVar,
ternary(
eq(objectLongVar, 0),
literal(0),
ternary(lt(objectLongVar, 0), -1, 1)
)
)
));
notNullStmts.append(defIf(eq(objectIntVar, 0), defBreak(innerLabel)));
ListBuffer eqStmts = new ListBuffer<>();
eqStmts.append(genWriteFieldName(mwc, attributeInfo, i));
eqStmts.append(exec(mwc.jsonWriterMethod("writeReference", literal(".."))));
eqStmts.append(defBreak(outerLabel));
notNullStmts.append(defIf(eq(mwc.object, objectVar), block(eqStmts.toList())));
notNullStmts.append(exec(
assign(
objectStrVar,
method(
mwc.jsonWriter,
"setPath",
field(names._this, fieldWriter(i)),
objectVar
)
)
));
notNullStmts.append(defIf(eq(objectStrVar, defNull()), block(defBreak(innerLabel))));
notNullStmts.append(genWriteFieldName(mwc, attributeInfo, i));
notNullStmts.append(exec(mwc.jsonWriterMethod("writeReference", "..")));
innerLabelStmts.append(defIf(ne(ident(objectVar), defNull()), block(notNullStmts.toList())));
ListBuffer notZeroStmts = new ListBuffer<>();
notZeroStmts.append(genWriteFieldName(mwc, attributeInfo, i));
notZeroStmts.append(exec(mwc.jsonWriterMethod("writeArrayNull")));
JCTree.JCExpression writeAsStringBinary = literal(WriteNulls.mask | NullAsDefaultValue.mask | WriteNullListAsEmpty.mask);
innerLabelStmts.append(defIf(ne(bitAnd(mwc.contextFeatures, writeAsStringBinary), 0), block(notZeroStmts.toList())));
innerLabelStmts.append(defBreak(outerLabel));
innerLabel.body = block(innerLabelStmts.toList());
outerLabelStmts.append(innerLabel);
ListBuffer notEmptyArrayStmts = new ListBuffer<>();
notEmptyArrayStmts.append(genWriteFieldName(mwc, attributeInfo, i));
notEmptyArrayStmts.append(
exec(method(
method(field(names._this, fieldWriter(i)), "getObjectWriter", mwc.jsonWriter, field(arrayIdentType(type), names._class)),
"write",
mwc.jsonWriter,
ident(objectVar),
literal(attributeInfo),
method(objectVar, "getClass"),
literal(0L)
))
);
notEmptyArrayStmts.append(
defIf(
ne(objectIntVar, 0),
exec(mwc.jsonWriterMethod("popPath", objectVar))
)
);
JCTree.JCBinary binary1 = eq(bitAnd(mwc.contextFeatures, NotWriteEmptyArray.mask), 0);
JCTree.JCBinary binary2 = ne(field(objectVar, "length"), 0);
outerLabelStmts.append(defIf(and(binary1, binary2), block(notEmptyArrayStmts.toList())));
outerLabel.body = block(outerLabelStmts.toList());
stmts.append(outerLabel);
} else if (type.contains("java.util.Map<")) {
JCTree.JCLabeledStatement outerLabel = label("objectOuterLabel" + i);
ListBuffer outerLabelStmts = new ListBuffer<>();
JCTree.JCVariableDecl objectStrVar = defVar("objectStr" + i, ident("String"), defNull());
outerLabelStmts.append(objectStrVar);
JCTree.JCVariableDecl objectVar = defVar("object" + i, getFieldValueType(type), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
outerLabelStmts.append(objectVar);
JCTree.JCVariableDecl objectIntVar = defVar("objectInt" + i, TypeTag.INT, literal(0));
outerLabelStmts.append(objectIntVar);
JCTree.JCLabeledStatement innerLabel = label("objectInnerLabel" + i);
ListBuffer notNullStmts = new ListBuffer<>();
notNullStmts.append(defIf(mwc.jsonWriterMethod("isIgnoreNoneSerializable", objectVar), block(defBreak(outerLabel))));
JCTree.JCVariableDecl objectLongVar = defVar("objectLong" + i, TypeTag.LONG, bitAnd(mwc.contextFeatures, ReferenceDetection.mask));
notNullStmts.append(objectLongVar);
notNullStmts.append(exec(
assign(
objectIntVar,
ternary(
eq(objectLongVar, 0),
literal(0),
ternary(lt(objectLongVar, 0), -1, 1)
)
)
));
notNullStmts.append(defIf(eq(objectIntVar, 0), defBreak(innerLabel)));
notNullStmts.append(defIf(eq(mwc.object, objectVar),
block(genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod("writeReference", literal(".."))),
defBreak(outerLabel)), null));
notNullStmts.append(exec(assign(objectStrVar, mwc.jsonWriterMethod("setPath", field(ident(names._this), fieldWriter(i)), ident(objectVar)))));
notNullStmts.append(defIf(eq(objectStrVar, defNull()), defBreak(innerLabel)));
notNullStmts.append(genWriteFieldName(mwc, attributeInfo, i));
notNullStmts.append(exec(mwc.jsonWriterMethod("writeReference", objectStrVar)));
notNullStmts.append(exec(mwc.jsonWriterMethod("popPath", objectVar)));
ListBuffer innerLabelStmts = new ListBuffer<>();
innerLabelStmts.append(defIf(ne(ident(objectVar), defNull()), block(notNullStmts.toList())));
JCTree.JCBinary binary = ne(bitAnd(mwc.contextFeatures, WriteMapNullValue.mask), 0);
innerLabelStmts.append(
defIf(
binary,
block(
genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod("writeNull"))
)
)
);
innerLabelStmts.append(defBreak(outerLabel));
innerLabel.body = block(innerLabelStmts.toList());
outerLabelStmts.append(innerLabel);
outerLabelStmts.append(genWriteFieldName(mwc, attributeInfo, i));
outerLabelStmts.append(
exec(method(
method(
field(names._this, fieldWriter(i)),
"getObjectWriter",
mwc.jsonWriter,
method(objectVar, "getClass")
),
"write",
mwc.jsonWriter, ident(objectVar),
literal(attributeInfo.name),
field(field(names._this, fieldWriter(i)), "fieldType"),
literal(0L))
)
);
outerLabelStmts.append(
defIf(
ne(objectIntVar, 0),
exec(mwc.jsonWriterMethod("popPath", objectVar))
)
);
outerLabel.body = block(outerLabelStmts.toList());
stmts.append(outerLabel);
} else {
String WRITE_NULL_METHOD;
if ("AtomicLongArray".equals(type)
|| "AtomicIntegerArray".equals(type)
|| "Collection.class.isAssignableFrom".equals(type)
|| "isArray".equals(type)) {
WRITE_NULL_METHOD = "writeArrayNull";
} else if ("java.lang.Number".equals(type)) {
WRITE_NULL_METHOD = "writeNumberNull";
} else if ("Boolean".equals(type)) {
WRITE_NULL_METHOD = "writeBooleanNull";
} else if ("String".equals(type)
|| "Appendable".equals(type)
|| "StringBuffer".equals(type)
|| "StringBuilder".equals(type)) {
WRITE_NULL_METHOD = "writeStringNull";
} else {
WRITE_NULL_METHOD = "writeNull";
}
JCTree.JCLabeledStatement outerLabel = label("objectOuterLabel" + i);
ListBuffer outerLabelStmts = new ListBuffer<>();
JCTree.JCVariableDecl objectStrVar = defVar("objectStr" + i, ident("String"), defNull());
outerLabelStmts.append(objectStrVar);
JCTree.JCVariableDecl objectVar = defVar("object" + i, getFieldValueType(type), genWriteFieldValue(attributeInfo, mwc.object, mwc.beanType));
outerLabelStmts.append(objectVar);
JCTree.JCVariableDecl objectIntVar = defVar("objectInt" + i, TypeTag.INT, literal(0));
outerLabelStmts.append(objectIntVar);
JCTree.JCLabeledStatement innerLabel = label("objectInnerLabel" + i);
ListBuffer notNullStmts = new ListBuffer<>();
boolean noneSerializable = false;
if (attributeInfo.type instanceof com.sun.tools.javac.code.Type.ClassType) {
List interfacesField = ((com.sun.tools.javac.code.Type.ClassType) attributeInfo.type).interfaces_field;
if (interfacesField == null || interfacesField.stream().noneMatch(f -> "java.io.Serializable".equals(f.toString()))) {
noneSerializable = true;
}
}
if (noneSerializable) {
notNullStmts.append(defIf(mwc.jsonWriterMethod("isIgnoreNoneSerializable", objectVar), defBreak(outerLabel)));
}
JCTree.JCVariableDecl objectLongVar = defVar("objectLong" + i, TypeTag.LONG, bitAnd(mwc.contextFeatures, ReferenceDetection.mask));
notNullStmts.append(objectLongVar);
notNullStmts.append(exec(assign(objectIntVar, ternary(eq(objectLongVar, 0), literal(0), ternary(lt(objectLongVar, 0), -1, 1)))));
notNullStmts.append(defIf(eq(objectIntVar, 0), defBreak(innerLabel)));
notNullStmts.append(defIf(eq(mwc.object, ident(objectVar)),
block(genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod("writeReference", "..")),
defBreak(outerLabel))));
notNullStmts.append(
exec(
assign(
objectStrVar,
method(
mwc.jsonWriter,
"setPath",
field(names._this, fieldWriter(i)),
objectVar
)
)
)
);
notNullStmts.append(defIf(eq(objectStrVar, defNull()), defBreak(innerLabel)));
notNullStmts.append(genWriteFieldName(mwc, attributeInfo, i));
notNullStmts.append(exec(mwc.jsonWriterMethod("writeReference", objectStrVar)));
notNullStmts.append(exec(mwc.jsonWriterMethod("popPath", objectVar)));
ListBuffer innerLabelStmts = new ListBuffer<>();
innerLabelStmts.append(defIf(ne(objectVar, defNull()), block(notNullStmts.toList())));
JCTree.JCBinary binary = ne(bitAnd(mwc.contextFeatures, WriteMapNullValue.mask), 0);
innerLabelStmts.append(defIf(binary,
block(genWriteFieldName(mwc, attributeInfo, i),
exec(mwc.jsonWriterMethod(WRITE_NULL_METHOD))),
null));
innerLabelStmts.append(defBreak(outerLabel));
innerLabel.body = block(innerLabelStmts.toList());
outerLabelStmts.append(innerLabel);
outerLabelStmts.append(genWriteFieldName(mwc, attributeInfo, i));
outerLabelStmts.append(
exec(method(
method(
field(names._this, fieldWriter(i)),
"getObjectWriter",
mwc.jsonWriter,
method(objectVar, "getClass")
),
"write",
mwc.jsonWriter,
ident(objectVar),
literal(attributeInfo.name),
field(field(ident(names._this), fieldWriter(i)), "fieldType"),
literal(0L))
)
);
outerLabelStmts.append(
defIf(
ne(objectIntVar, 0),
exec(mwc.jsonWriterMethod("popPath", objectVar))
)
);
outerLabel.body = block(outerLabelStmts.toList());
stmts.append(outerLabel);
}
return stmts;
}
private JCTree.JCVariableDecl getHashCode32Var(JCTree.JCExpression hashCode64) {
JCTree.JCBinary usrBinary = binary(JCTree.Tag.USR, hashCode64, literal(32));
JCTree.JCPrimitiveTypeTree intType = type(TypeTag.INT);
JCTree.JCTypeCast hashCode32Cast = cast(intType, bitXor(hashCode64, parens(usrBinary)));
return defVar("hashCode32", intType, hashCode32Cast);
}
private List genReadFieldValue(
AttributeInfo attributeInfo,
JCTree.JCIdent jsonReaderIdent,
int i,
StructInfo structInfo,
JCTree.JCLabeledStatement loopLabel,
JCTree.JCIdent objectIdent,
JCTree.JCExpression beanType,
boolean isJsonb) {
JCTree.JCExpression valueExpr = null;
ListBuffer stmts = new ListBuffer<>();
String type = attributeInfo.type.toString();
boolean referenceDetect = structInfo.referenceDetect;
if (referenceDetect) {
referenceDetect = isReference(type);
}
JCTree.JCFieldAccess fieldReaderField = field(ident(names._this), fieldReader(i));
if (referenceDetect) {
ListBuffer thenStmts = new ListBuffer<>();
JCTree.JCMethodInvocation readReferenceMethod = method(jsonReaderIdent, "readReference");
JCTree.JCVariableDecl refVar = defVar("ref", ident("String"), readReferenceMethod);
thenStmts.append(refVar);
JCTree.JCMethodInvocation addResolveTaskMethod = method(fieldReaderField, "addResolveTask", jsonReaderIdent, objectIdent, ident(refVar));
thenStmts.append(exec(addResolveTaskMethod));
thenStmts.append(defContinue(loopLabel));
stmts.append(defIf(method(jsonReaderIdent, "isReference"), block(thenStmts.toList())));
}
String readDirectMethod = getReadDirectMethod(type);
if (readDirectMethod != null) {
valueExpr = method(jsonReaderIdent, readDirectMethod);
} else {
JCTree.JCExpression fieldValueType = getFieldValueType(type);
JCTree.JCVariableDecl fieldValueVar = defVar(attributeInfo.name, fieldValueType);
stmts.append(fieldValueVar);
if (type.startsWith("java.util.List<")) {
valueExpr = genFieldValueList(
type,
attributeInfo,
jsonReaderIdent,
fieldValueVar,
loopLabel,
stmts,
i,
referenceDetect,
fieldReaderField,
beanType,
isJsonb);
} else if (type.startsWith("java.util.Map genRead243(
java.util.List attributeInfos,
JCTree.JCIdent jsonReaderIdent,
StructInfo structInfo,
JCTree.JCLabeledStatement loopLabel,
JCTree.JCIdent objectIdent,
JCTree.JCExpression beanType,
boolean isJsonb) {
IdentityHashMap readerIndexMap = new IdentityHashMap<>();
Map> name0Map = new TreeMap<>();
for (int i = 0; i < attributeInfos.size(); ++i) {
AttributeInfo field = attributeInfos.get(i);
readerIndexMap.put(field, i);
byte[] fieldName = field.name.getBytes(StandardCharsets.UTF_8);
byte[] name0Bytes = new byte[4];
name0Bytes[0] = '"';
if (fieldName.length == 2) {
System.arraycopy(fieldName, 0, name0Bytes, 1, 2);
name0Bytes[3] = '"';
} else {
System.arraycopy(fieldName, 0, name0Bytes, 1, 3);
}
int name0 = UNSAFE.getInt(name0Bytes, ARRAY_BYTE_BASE_OFFSET);
java.util.List fieldReaders = name0Map.get(name0);
if (fieldReaders == null) {
fieldReaders = new ArrayList<>();
name0Map.put(name0, fieldReaders);
}
fieldReaders.add(field);
}
int[] switchKeys = new int[name0Map.size()];
Label[] labels = new Label[name0Map.size()];
{
Iterator it = name0Map.keySet().iterator();
for (int i = 0; i < labels.length; i++) {
labels[i] = new Label();
switchKeys[i] = it.next();
}
}
List stmts = List.nil();
ListBuffer cases = new ListBuffer<>();
JCTree.JCLabeledStatement switchLabel = label("_switch2");
for (int i = 0; i < labels.length; i++) {
int name0 = switchKeys[i];
java.util.List fieldReaders = name0Map.get(name0);
ListBuffer caseStmts = new ListBuffer<>();
for (int j = 0; j < fieldReaders.size(); j++) {
AttributeInfo fieldReader = fieldReaders.get(j);
int fieldReaderIndex = readerIndexMap.get(fieldReader);
byte[] fieldName = fieldReader.name.getBytes(StandardCharsets.UTF_8);
int fieldNameLength = fieldName.length;
JCTree.JCMethodInvocation nextIfMethod;
switch (fieldNameLength) {
case 2:
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match2");
break;
case 3:
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match3");
break;
case 4:
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match4", literal(fieldName[3]));
break;
case 5: {
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[3];
bytes4[1] = fieldName[4];
bytes4[2] = '"';
bytes4[3] = ':';
int name1 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match5", literal(name1));
break;
}
case 6: {
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[3];
bytes4[1] = fieldName[4];
bytes4[2] = fieldName[5];
bytes4[3] = '"';
int name1 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match6", literal(name1));
break;
}
case 7: {
int name1 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match7", literal(name1));
break;
}
case 8: {
int name1 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match8", literal(name1), literal(fieldName[7]));
break;
}
case 9: {
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 3, bytes8, 0, 6);
bytes8[6] = '"';
bytes8[7] = ':';
long name1 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match9", literal(name1));
break;
}
case 10: {
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 3, bytes8, 0, 7);
bytes8[7] = '"';
long name1 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match10", literal(name1));
break;
}
case 11: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match11", literal(name1));
break;
}
case 12: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match12", literal(name1), literal(fieldName[11]));
break;
}
case 13: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[11];
bytes4[1] = fieldName[12];
bytes4[2] = '"';
bytes4[3] = ':';
int name2 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match13", literal(name1), literal(name2));
break;
}
case 14: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[11];
bytes4[1] = fieldName[12];
bytes4[2] = fieldName[13];
bytes4[3] = '"';
int name2 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match14", name1, name2);
break;
}
case 15: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
int name2 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match15", name1, name2);
break;
}
case 16: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
int name2 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match16", name1, name2, fieldName[15]);
break;
}
case 17: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 11, bytes8, 0, 6);
bytes8[6] = '"';
bytes8[7] = ':';
long name2 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match17", name1, name2);
break;
}
case 18: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 11, bytes8, 0, 7);
bytes8[7] = '"';
long name2 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match18", name1, name2);
break;
}
case 19: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match19", name1, name2);
break;
}
case 20: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match20", name1, name2, fieldName[19]);
break;
}
case 21: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[19];
bytes4[1] = fieldName[20];
bytes4[2] = '"';
bytes4[3] = ':';
int name3 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match21", name1, name2, name3);
break;
}
case 22: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[19];
bytes4[1] = fieldName[20];
bytes4[2] = fieldName[21];
bytes4[3] = '"';
int name3 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match22", name1, name2, name3);
break;
}
case 23: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
int name3 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match23", name1, name2, name3);
break;
}
case 24: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
int name3 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match24", name1, name2, name3, fieldName[23]);
break;
}
case 25: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 19, bytes8, 0, 6);
bytes8[6] = '"';
bytes8[7] = ':';
long name3 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match25", name1, name2, name3);
break;
}
case 26: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 19, bytes8, 0, 7);
bytes8[7] = '"';
long name3 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match26", name1, name2, name3);
break;
}
case 27: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match27", name1, name2, name3);
break;
}
case 28: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match28", name1, name2, name3, fieldName[27]);
break;
}
case 29: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[27];
bytes4[1] = fieldName[28];
bytes4[2] = '"';
bytes4[3] = ':';
int name4 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match29", name1, name2, name3, name4);
break;
}
case 30: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[27];
bytes4[1] = fieldName[28];
bytes4[2] = fieldName[29];
bytes4[3] = '"';
int name4 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match30", name1, name2, name3, name4);
break;
}
case 31: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
int name4 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match31", name1, name2, name3, name4);
break;
}
case 32: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
int name4 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match32", name1, name2, name3, name4, fieldName[31]);
break;
}
case 33: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 27, bytes8, 0, 6);
bytes8[6] = '"';
bytes8[7] = ':';
long name4 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match33", name1, name2, name3, name4);
break;
}
case 34: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 27, bytes8, 0, 7);
bytes8[7] = '"';
long name4 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match34", name1, name2, name3, name4);
break;
}
case 35: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match35", name1, name2, name3, name4);
break;
}
case 36: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match36", name1, name2, name3, name4, fieldName[35]);
break;
}
case 37: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[35];
bytes4[1] = fieldName[36];
bytes4[2] = '"';
bytes4[3] = ':';
int name5 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match37", name1, name2, name3, name4, name5);
break;
}
case 38: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[35];
bytes4[1] = fieldName[36];
bytes4[2] = fieldName[37];
bytes4[3] = '"';
int name5 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match38", name1, name2, name3, name4, name5);
break;
}
case 39: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
int name5 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 35);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match39", name1, name2, name3, name4, name5);
break;
}
case 40: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
int name5 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 35);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match40", name1, name2, name3, name4, name5, fieldName[39]);
break;
}
case 41: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 35, bytes8, 0, 6);
bytes8[6] = '"';
bytes8[7] = ':';
long name5 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match41", name1, name2, name3, name4, name5);
break;
}
case 42: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 35, bytes8, 0, 7);
bytes8[7] = '"';
long name5 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match42", name1, name2, name3, name4, name5);
break;
}
case 43: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
long name5 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 35);
nextIfMethod = method(jsonReaderIdent, "nextIfName4Match43", name1, name2, name3, name4, name5);
break;
}
default:
throw new IllegalStateException("fieldNameLength " + fieldNameLength);
}
List readFieldValueStmts = genReadFieldValue(
fieldReader,
jsonReaderIdent,
fieldReaderIndex,
structInfo,
loopLabel,
objectIdent,
beanType,
isJsonb);
caseStmts.append(defIf(nextIfMethod, block(readFieldValueStmts)));
}
caseStmts.append(defBreak(switchLabel));
cases.append(defCase(literal(name0), caseStmts.toList()));
}
switchLabel.body = defSwitch(method(jsonReaderIdent, "getRawInt"), cases.toList());
stmts = stmts.append(switchLabel);
return stmts;
}
private JCTree.JCExpression genFieldValueList(
String type,
AttributeInfo attributeInfo,
JCTree.JCIdent jsonReaderIdent,
JCTree.JCVariableDecl fieldValueVar,
JCTree.JCLabeledStatement loopLabel,
ListBuffer stmts,
int i,
boolean referenceDetect,
JCTree.JCFieldAccess fieldReaderField,
JCTree.JCExpression beanType,
boolean isJsonb) {
String itemType = type.substring(15, type.length() - 1);
boolean itemTypeIsClass = itemType.indexOf('<') == -1;
if (itemTypeIsClass) {
JCTree.JCMethodInvocation nextIfNullMethod = method(jsonReaderIdent, "nextIfNull");
stmts.append(defIf(nextIfNullMethod,
block(exec(assign(fieldValueVar, defNull()))),
block(exec(assign(fieldValueVar, newClass(null, null, qualIdent("java.util.ArrayList"), null, null))))));
String readDirectMethod = getReadDirectMethod(itemType);
JCTree.JCIdent itemReaderIdent = ident(fieldItemObjectReader(i));
if (readDirectMethod == null) {
JCTree.JCFieldAccess getItemObjectReaderField = field(fieldReaderField, "getItemObjectReader");
JCTree.JCExpressionStatement getItemObjectReaderExec = exec(assign(itemReaderIdent, method(getItemObjectReaderField, jsonReaderIdent)));
stmts.append(defIf(eq(itemReaderIdent, defNull()), block(getItemObjectReaderExec)));
}
if (referenceDetect) {
referenceDetect = isReference(itemType);
}
JCTree.JCVariableDecl for_iVar;
if ("i".equals(attributeInfo.name)) {
for_iVar = defVar("j", TypeTag.INT, literal(0));
} else {
for_iVar = defVar("i", TypeTag.INT, literal(0));
}
JCTree.JCMethodInvocation nextIfArrayStartMethod = method(jsonReaderIdent, "nextIfArrayStart");
JCTree.JCMethodInvocation nextIfArrayEndMethod = method(jsonReaderIdent, "nextIfArrayEnd");
ListBuffer whileStmts = new ListBuffer<>();
JCTree.JCExpression item;
if (readDirectMethod != null) {
item = method(jsonReaderIdent, readDirectMethod);
} else {
item = cast(
qualIdent(itemType),
method(
itemReaderIdent,
isJsonb ? "readJSONBObject" : "readObject",
jsonReaderIdent, defNull(),
defNull(),
literal(0L)
)
);
}
if (referenceDetect) {
JCTree.JCVariableDecl listItemVar = defVar(attributeInfo.name + "_item", getFieldValueType(itemType), item);
ListBuffer isReferenceStmts = new ListBuffer<>();
JCTree.JCMethodInvocation readReferenceMethod = method(jsonReaderIdent, "readReference");
JCTree.JCVariableDecl refVar = defVar("ref", ident("String"), readReferenceMethod);
isReferenceStmts.append(refVar);
JCTree.JCMethodInvocation addResolveTaskMethod = method(
jsonReaderIdent,
"addResolveTask",
ident(fieldValueVar),
ident(for_iVar),
method(
qualIdent("com.alibaba.fastjson2.JSONPath"),
"of",
ident(refVar)
)
);
isReferenceStmts.append(exec(addResolveTaskMethod));
isReferenceStmts.append(exec(method(fieldValueVar, "add", defNull())));
isReferenceStmts.append(defContinue(loopLabel));
whileStmts.append(defIf(method(jsonReaderIdent, "isReference"), block(isReferenceStmts.toList())));
whileStmts.append(listItemVar);
item = ident(listItemVar);
}
whileStmts.append(exec(method(fieldValueVar, "add", item)));
ListBuffer condStmts = new ListBuffer<>();
if (referenceDetect) {
condStmts.append(forLoop(
List.of(for_iVar),
unary(JCTree.Tag.NOT, nextIfArrayEndMethod),
List.of(exec(unary(JCTree.Tag.PREINC, ident(for_iVar)))),
block(whileStmts.toList())));
} else {
condStmts.append(whileLoop(unary(JCTree.Tag.NOT, nextIfArrayEndMethod), block(whileStmts.toList())));
}
stmts.append(defIf(nextIfArrayStartMethod, block(condStmts.toList())));
return ident(fieldValueVar.name);
}
return null;
}
private JCTree.JCExpression genFieldValueMap(
String type,
AttributeInfo attributeInfo,
JCTree.JCIdent jsonReaderIdent,
JCTree.JCVariableDecl fieldValueVar,
JCTree.JCLabeledStatement loopLabel,
ListBuffer stmts,
int i,
boolean referenceDetect,
boolean isJsonb
) {
String itemType = type.substring(31, type.length() - 1);
JCTree.JCMethodInvocation nextIfNullMethod = method(jsonReaderIdent, "nextIfNull");
boolean readDirect = supportReadDirect(itemType);
ListBuffer elseStmts = new ListBuffer<>();
JCTree.JCIdent itemReaderIdent = ident(fieldItemObjectReader(i));
if (!readDirect) {
JCTree.JCFieldAccess getObjectReaderField = field(jsonReaderIdent, "getObjectReader");
JCTree.JCExpressionStatement getItemObjectReaderExec = exec(
assign(
itemReaderIdent,
method(getObjectReaderField, field(qualIdent(itemType), names._class))
)
);
elseStmts.append(defIf(eq(itemReaderIdent, defNull()), block(getItemObjectReaderExec)));
}
elseStmts.append(exec(assign(fieldValueVar, newClass(null, null, qualIdent("java.util.HashMap"), null, null))));
JCTree.JCMethodInvocation nextIfObjectStartMethod = method(jsonReaderIdent, "nextIfObjectStart");
elseStmts.append(exec(nextIfObjectStartMethod));
JCTree.JCMethodInvocation nextIfObjectEndMethod = method(jsonReaderIdent, "nextIfObjectEnd");
ListBuffer whileStmts = new ListBuffer<>();
if (referenceDetect) {
referenceDetect = isReference(itemType);
}
JCTree.JCExpression mapEntryValueExpr;
if (readDirect) {
mapEntryValueExpr = cast(qualIdent(itemType), method(jsonReaderIdent, getReadDirectMethod(itemType)));
} else {
mapEntryValueExpr = cast(
qualIdent(itemType),
method(
itemReaderIdent,
isJsonb ? "readJSONBObject" : "readObject",
jsonReaderIdent,
field(qualIdent(itemType), names._class),
literal(attributeInfo.name), ident("features")
)
);
}
JCTree.JCExpression mapEntryKeyExpr = method(jsonReaderIdent, "readFieldName");
if (referenceDetect) {
JCTree.JCVariableDecl mapKey = defVar(attributeInfo.name + "_key", ident("String"), mapEntryKeyExpr);
whileStmts.append(mapKey);
JCTree.JCVariableDecl mapValue = defVar(attributeInfo.name + "_value", ident("String"));
whileStmts.append(mapValue);
ListBuffer isReferenceStmts = new ListBuffer<>();
JCTree.JCMethodInvocation readReferenceMethod = method(jsonReaderIdent, "readReference");
JCTree.JCVariableDecl refVar = defVar("ref", ident("String"), readReferenceMethod);
isReferenceStmts.append(refVar);
JCTree.JCMethodInvocation addResolveTaskMethod = method(
jsonReaderIdent,
"addResolveTask",
ident(fieldValueVar),
ident(mapKey),
method(qualIdent("com.alibaba.fastjson2.JSONPath"), "of", ident(refVar))
);
isReferenceStmts.append(exec(addResolveTaskMethod));
whileStmts.append(
defIf(
method(jsonReaderIdent, "isReference"),
block(isReferenceStmts.toList()),
exec(method(fieldValueVar, "put", mapEntryKeyExpr, mapEntryValueExpr))
)
);
} else {
whileStmts.append(exec(method(fieldValueVar, "put", mapEntryKeyExpr, mapEntryValueExpr)));
}
elseStmts.append(whileLoop(unary(JCTree.Tag.NOT, nextIfObjectEndMethod), block(whileStmts.toList())));
elseStmts.append(exec(method(jsonReaderIdent, "nextIfComma")));
stmts.append(defIf(nextIfNullMethod,
block(exec(assign(fieldValueVar, defNull()))),
block(elseStmts.toList())));
return ident(fieldValueVar);
}
private void genSource(StructInfo structInfo, TreePath treePath) {
Filer filer = processingEnv.getFiler();
String fullQualifiedName = structInfo.binaryName;
JavaFileObject converterFile = null;
try {
if (treePath.getCompilationUnit() instanceof JCTree.JCCompilationUnit) {
JCTree.JCCompilationUnit compilationUnit = (JCTree.JCCompilationUnit) treePath.getCompilationUnit();
converterFile = filer.createSourceFile(fullQualifiedName, structInfo.element);
String fileName = converterFile.getName() + ".txt";
Path filePath = Paths.get(fileName);
String dirName = fileName.substring(0, fileName.lastIndexOf(File.separator));
Path dirPath = Paths.get(dirName);
if (!Files.exists(dirPath)) {
Files.createDirectories(dirPath);
}
if (!Files.exists(filePath)) {
Files.createFile(filePath);
}
try (Writer writer = new FileWriter(filePath.toString())) {
writer.write(compilationUnit.toString());
} catch (Exception e) {
messager.printMessage(Diagnostic.Kind.WARNING, "Failed to generate source file for "
+ fullQualifiedName + " caused by " + e.getMessage());
}
} else {
messager.printMessage(Diagnostic.Kind.WARNING, "Failed to generate source file for "
+ fullQualifiedName + " caused by invalid compilation unit");
}
} catch (Exception e) {
messager.printMessage(Diagnostic.Kind.WARNING, "Failed to generate source file for "
+ fullQualifiedName + " caused by " + e.getMessage());
} finally {
if (converterFile != null) {
converterFile.delete();
}
if (filer instanceof JavacFiler) {
((JavacFiler) filer).close();
}
}
}
private void genReflect(Set reflects) {
File file = null;
try {
file = new File("");
String absolutePath = file.getAbsolutePath() +
File.separator +
Arrays.stream("src/main/resources/META-INF/native-image/reflect-config.json".split("/"))
.sequential()
.collect(Collectors.joining(File.separator));
int idx = absolutePath.lastIndexOf(File.separator);
Path dirPath = Paths.get(absolutePath.substring(0, idx));
Path filePath = Paths.get(absolutePath);
if (!Files.exists(dirPath)) {
Files.createDirectories(dirPath);
}
if (!Files.exists(filePath)) {
Files.createFile(filePath);
}
try (BufferedReader reader = Files.newBufferedReader(filePath)) {
String content = reader.lines().collect(Collectors.joining());
java.util.List reflectionMetadata = JSON.parseArray(content, ReflectionMetadata.class);
if (reflectionMetadata != null) {
reflects.addAll(reflectionMetadata);
}
String jsonString = JSON.toJSONString(reflects, PrettyFormat);
try (BufferedWriter writer = Files.newBufferedWriter(filePath)) {
writer.write(jsonString);
}
}
} catch (Exception e) {
messager.printMessage(Diagnostic.Kind.WARNING, "Failed to generate reflect-config.json caused by " + e.getMessage());
} finally {
if (file != null && file.exists()) {
file.delete();
}
}
}
private boolean isDebug(JCTree.JCClassDecl beanClassDecl) {
JCTree.JCExpression jsonCompiledIdent = qualIdent(JSONCompiled.class.getName());
List annotations = beanClassDecl.mods.annotations;
Optional jsonCompiledAnnoOpt = annotations.stream()
.filter(a -> a.getAnnotationType().type.tsym.toString().equals(jsonCompiledIdent.type.tsym.toString()))
.findAny();
if (jsonCompiledAnnoOpt.isPresent()) {
JCTree.JCAnnotation jsonCompiledAnno = jsonCompiledAnnoOpt.get();
Optional jsonCompiledAsgOpt = jsonCompiledAnno.args.stream()
.map(a -> (JCTree.JCAssign) a)
.filter(a2 -> "debug".equals(a2.lhs.toString()))
.findAny();
if (jsonCompiledAsgOpt.isPresent()) {
JCTree.JCAssign jcAssign = jsonCompiledAsgOpt.get();
return "true".equals(jcAssign.rhs.toString());
}
}
return false;
}
private JCTree.JCExpression getFieldValueType(String type) {
if (type.contains("[")) {
return arrayIdentType(type);
}
if (type.contains("<")) {
return collectionIdent(type);
}
return qualIdent(type);
}
private String findConverterName(StructInfo structInfo, String suffix) {
int dotIndex;
dotIndex = structInfo.binaryName.lastIndexOf('$');
if (dotIndex != -1) {
dotIndex = structInfo.binaryName.lastIndexOf('.');
}
String className = structInfo.binaryName.substring(dotIndex + 1);
if (dotIndex == -1) {
return className + suffix;
}
String packageName = structInfo.binaryName.substring(0, dotIndex);
return packageName + '.' + className + suffix;
}
static final class MethodWriterContext {
final JCTree.JCExpression beanType;
final JCTree.JCIdent objectType;
final JCTree.JCIdent jsonWriter = ident("jsonWriter");
final JCTree.JCIdent object = ident("object");
final JCTree.JCIdent fieldName = ident("fieldName");
final JCTree.JCIdent fieldType = ident("fieldType");
final JCTree.JCIdent features = ident("features");
final JCTree.JCIdent contextFeatures = ident("contextFeatures");
final JCTree.JCIdent notWriteDefaultValue = ident("notWriteDefaultValue");
final JCTree.JCIdent nameDirect = ident("nameDirect");
final JCTree.JCIdent writeNulls = ident("writeNulls");
final boolean jsonb;
public MethodWriterContext(JCTree.JCExpression beanType, JCTree.JCIdent objectType, boolean jsonb) {
this.beanType = beanType;
this.objectType = objectType;
this.jsonb = jsonb;
}
void genVariantsMethodBefore(ListBuffer body) {
JCTree.JCVariableDecl contextFeaturesVar
= defVar("contextFeatures", TypeTag.LONG, jsonWriterMethod("getFeatures"));
body.append(contextFeaturesVar);
JCTree.JCVariableDecl nameDirect;
if (!jsonb) {
nameDirect = defVar("nameDirect", TypeTag.BOOLEAN,
and(
not(jsonWriterField("useSingleQuote")),
isDisable(contextFeatures, UnquoteFieldName, UseSingleQuotes)
)
);
} else {
nameDirect = defVar("nameDirect", TypeTag.BOOLEAN,
ternary(
notNull(jsonWriterField("symbolTable")),
literal(false),
isDisable(contextFeatures, WriteNameAsSymbol)
)
);
}
body.append(nameDirect);
body.append(
defVar("notWriteDefaultValue", TypeTag.BOOLEAN, isEnable(contextFeatures, NotWriteDefaultValue))
);
body.append(
defVar(
"writeNulls",
TypeTag.BOOLEAN,
ternary(this.notWriteDefaultValue, isEnable(contextFeatures, WriteNulls, NullAsDefaultValue), false)
)
);
}
JCTree.JCExpression jsonWriterField(String fieldName) {
return field(jsonWriter, fieldName);
}
JCTree.JCExpression jsonWriterMethod(String fieldName) {
return method(jsonWriter, fieldName);
}
JCTree.JCExpression jsonWriterMethod(String fieldName, List args) {
return method(jsonWriter, fieldName, args);
}
JCTree.JCExpression jsonWriterMethod(String fieldName, JCTree.JCExpression arg) {
return method(jsonWriter, fieldName, List.of(arg));
}
JCTree.JCExpression jsonWriterMethod(String fieldName, JCTree.JCVariableDecl arg) {
return method(jsonWriter, fieldName, List.of(ident(arg)));
}
JCTree.JCExpression jsonWriterMethod(String fieldName, String arg) {
return method(jsonWriter, fieldName, List.of(literal(arg)));
}
JCTree.JCExpression jsonWriterMethod(
String fieldName,
JCTree.JCExpression arg0,
JCTree.JCExpression arg1
) {
return method(jsonWriter, fieldName, List.of(arg0, arg1));
}
JCTree.JCExpression jsonWriterMethod(
String fieldName,
JCTree.JCExpression arg0,
JCTree.JCVariableDecl arg1
) {
return method(jsonWriter, fieldName, List.of(arg0, ident(arg1)));
}
}
}