Merge pull request #10 from TouchInstinct/json_model_features
Json model features
This commit is contained in:
commit
60b3a36ed3
|
|
@ -34,9 +34,10 @@ import javafx.util.Pair
|
|||
import org.yaml.snakeyaml.Yaml
|
||||
|
||||
import javax.lang.model.element.Modifier
|
||||
import java.util.Map.Entry
|
||||
|
||||
|
||||
//TODO: missable in future
|
||||
//TODO: optional in future
|
||||
//TODO: NUMBER/BOOLEAN enums in future
|
||||
//TODO: maybe save md5-hashes to check if files/scheme changed
|
||||
|
||||
|
|
@ -49,6 +50,10 @@ class Types {
|
|||
static final TypeName JSON_OBJECT = ClassName.bestGuess("com.bluelinelabs.logansquare.annotation.JsonObject")
|
||||
static final TypeName JSON_FIELD = ClassName.bestGuess("com.bluelinelabs.logansquare.annotation.JsonField")
|
||||
static final TypeName COLLECTIONS = ClassName.get(Collections.class)
|
||||
static final TypeName COLLECTION = ClassName.get(Collection.class)
|
||||
static final TypeName ARRAY_LIST = ClassName.get(ArrayList.class)
|
||||
static final TypeName MAP = ClassName.get(Map.class)
|
||||
static final TypeName HASH_MAP = ClassName.get(HashMap.class)
|
||||
static final TypeName API_MODEL = ClassName.bestGuess("ru.touchin.templates.ApiModel")
|
||||
static final TypeName LOGAN_SQUARE_JSON_MODEL = ClassName.bestGuess("ru.touchin.templates.logansquare.LoganSquareJsonModel")
|
||||
static final TypeName OBJECT_UTILS = ClassName.bestGuess("ru.touchin.roboswag.core.utils.ObjectUtils")
|
||||
|
|
@ -86,14 +91,24 @@ abstract class SchemeObject {
|
|||
*/
|
||||
class ImportObject extends SchemeObject {
|
||||
|
||||
enum Type {
|
||||
MODEL,
|
||||
ENUM,
|
||||
EXTERNAL
|
||||
}
|
||||
|
||||
static final String GROUP_NAME = "imports"
|
||||
|
||||
final String name
|
||||
final String fullName
|
||||
final Type type
|
||||
final ClassObject relatedModel
|
||||
|
||||
ImportObject(String value) {
|
||||
ImportObject(final String value, final Type type, final ClassObject relatedModel) {
|
||||
fullName = value.trim()
|
||||
name = fullName.substring(fullName.lastIndexOf('.') + 1)
|
||||
this.type = type
|
||||
this.relatedModel = relatedModel
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -154,7 +169,7 @@ class EnumObject extends SchemeObject {
|
|||
throw new Exception("Name of enum is empty")
|
||||
}
|
||||
|
||||
for (final Map.Entry<String, String> entry : jsonValues) {
|
||||
for (final Entry<String, String> entry : jsonValues) {
|
||||
final enumValue = entry.key.trim()
|
||||
final jsonValue = entry.value.trim()
|
||||
if (jsonValue.isEmpty() || enumValue.isEmpty()) {
|
||||
|
|
@ -202,7 +217,7 @@ class EnumObject extends SchemeObject {
|
|||
.build())
|
||||
.build())
|
||||
|
||||
for (final Map.Entry<String, Object> enumValue : values) {
|
||||
for (final Entry<String, Object> enumValue : values) {
|
||||
enumBuilder.addEnumConstant(enumValue.key, TypeSpec.anonymousClassBuilder(type.format, enumValue.value).build())
|
||||
}
|
||||
|
||||
|
|
@ -283,7 +298,14 @@ enum FieldType {
|
|||
default:
|
||||
final SchemeObject object = objects.get(typeString)
|
||||
if (object instanceof ImportObject) {
|
||||
return IMPORTED_CLASS
|
||||
switch (object.type) {
|
||||
case ImportObject.Type.MODEL:
|
||||
return MODEL
|
||||
case ImportObject.Type.ENUM:
|
||||
return ENUM
|
||||
case ImportObject.Type.EXTERNAL:
|
||||
return IMPORTED_CLASS
|
||||
}
|
||||
}
|
||||
if (object instanceof EnumObject) {
|
||||
return ENUM
|
||||
|
|
@ -420,7 +442,7 @@ class TypeNameUtils {
|
|||
* - jsonName - field name association with JSON parameter name. By default equals 'name' property;
|
||||
* - type - type of field;
|
||||
* - nullable - 'nullable' flag, true if field could contains null and associated JSON value could be null;
|
||||
* - missable - 'missable' flag, true if JSON parameter associated with field could be missed in JSON object;
|
||||
* - optional - 'optional' flag, true if JSON parameter associated with field could be missed in JSON object;
|
||||
* - nonEmptyCollection - 'non-empty' flag, true if JSON parameter could contains collection and that collection souldn't be empty;
|
||||
* - solidCollection - 'solid' flag, true if JSON parameter could contains collection and that collection can't contains any invalid element.
|
||||
*/
|
||||
|
|
@ -445,7 +467,7 @@ class FieldInfo {
|
|||
final String name
|
||||
final String jsonName
|
||||
boolean nullable
|
||||
boolean missable
|
||||
boolean optional
|
||||
boolean nonEmptyCollection
|
||||
boolean solidCollection
|
||||
final FieldType type
|
||||
|
|
@ -469,8 +491,8 @@ class FieldInfo {
|
|||
case "nullable":
|
||||
nullable = true
|
||||
break
|
||||
case "missable":
|
||||
missable = true
|
||||
case "optional":
|
||||
optional = true
|
||||
break
|
||||
case "non-empty":
|
||||
nonEmptyCollection = true
|
||||
|
|
@ -503,7 +525,7 @@ class FieldInfo {
|
|||
throw new Exception("Unsupported map type of field: " + fieldName + ". Supports only Map<String, *>")
|
||||
}
|
||||
} else {
|
||||
typeName = nullable ? type.nonPrimitiveTypeName : type.primitiveTypeName
|
||||
typeName = couldContainsNull() ? type.nonPrimitiveTypeName : type.primitiveTypeName
|
||||
}
|
||||
} else if (type != FieldType.TYPE_ARGUMENT) {
|
||||
typeName = TypeNameUtils.resolveTypeName(typeString, objects)
|
||||
|
|
@ -513,6 +535,10 @@ class FieldInfo {
|
|||
}
|
||||
}
|
||||
|
||||
boolean couldContainsNull() {
|
||||
return nullable || optional
|
||||
}
|
||||
|
||||
FieldSpec generateFieldCode() {
|
||||
return FieldSpec.builder(typeName, name, Modifier.PRIVATE)
|
||||
.addAnnotation(AnnotationSpec.builder(Types.JSON_FIELD)
|
||||
|
|
@ -544,13 +570,13 @@ class FieldInfo {
|
|||
.returns(typeName)
|
||||
|
||||
if (!typeName.isPrimitive()) {
|
||||
builder.addAnnotation(AnnotationSpec.builder(nullable ? Types.NULLABLE : Types.NON_NULL).build())
|
||||
builder.addAnnotation(AnnotationSpec.builder(couldContainsNull() ? Types.NULLABLE : Types.NON_NULL).build())
|
||||
}
|
||||
|
||||
if (type == FieldType.MAP) {
|
||||
builder.addStatement("return \$T.unmodifiableMap(\$L)", Types.COLLECTIONS, name)
|
||||
} else if (type == FieldType.LIST) {
|
||||
if (type == FieldType.LIST) {
|
||||
builder.addStatement("return \$T.unmodifiableList(\$L)", Types.COLLECTIONS, name)
|
||||
} else if (type == FieldType.MAP) {
|
||||
builder.addStatement("return \$T.unmodifiableMap(\$L)", Types.COLLECTIONS, name)
|
||||
} else {
|
||||
builder.addStatement("return \$L", name)
|
||||
}
|
||||
|
|
@ -561,17 +587,17 @@ class FieldInfo {
|
|||
MethodSpec generateSetterCode() {
|
||||
final ParameterSpec.Builder parameterBuilder = ParameterSpec.builder(typeName, name, Modifier.FINAL)
|
||||
if (!typeName.isPrimitive()) {
|
||||
parameterBuilder.addAnnotation(AnnotationSpec.builder(nullable ? Types.NULLABLE : Types.NON_NULL).build())
|
||||
parameterBuilder.addAnnotation(AnnotationSpec.builder(couldContainsNull() ? Types.NULLABLE : Types.NON_NULL).build())
|
||||
}
|
||||
|
||||
final MethodSpec.Builder builder = MethodSpec.methodBuilder("set" + upperStartName(name))
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.addParameter(parameterBuilder.build())
|
||||
|
||||
if (type == FieldType.MAP) {
|
||||
builder.addStatement("this.\$L = \$T.unmodifiableMap(\$L)", name, ClassName.get(Collections.class), name)
|
||||
} else if (type == FieldType.LIST) {
|
||||
builder.addStatement("this.\$L = \$T.unmodifiableList(\$L)", name, ClassName.get(Collections.class), name)
|
||||
if (type == FieldType.LIST) {
|
||||
builder.addStatement("this.\$L = new \$T<>(\$L)", name, Types.ARRAY_LIST, name)
|
||||
} else if (type == FieldType.MAP) {
|
||||
builder.addStatement("this.\$L = new \$T<>(\$L)", name, Types.HASH_MAP, name)
|
||||
} else {
|
||||
builder.addStatement("this.\$L = \$L", name, name)
|
||||
}
|
||||
|
|
@ -580,7 +606,7 @@ class FieldInfo {
|
|||
}
|
||||
|
||||
void generateValidationCode(MethodSpec.Builder validateMethod) {
|
||||
if (!nullable) {
|
||||
if (!couldContainsNull()) {
|
||||
validateMethod.addStatement("validateNotNull(\$L)", name)
|
||||
}
|
||||
if (!type.ableToInnerValidate) {
|
||||
|
|
@ -591,9 +617,17 @@ class FieldInfo {
|
|||
.beginControlFlow("if (\$L instanceof \$T)", name, Types.API_MODEL)
|
||||
.addStatement("((\$T) \$L).validate()", Types.API_MODEL, name)
|
||||
.endControlFlow()
|
||||
validateMethod
|
||||
.beginControlFlow("if (\$L instanceof \$T)", name, Types.COLLECTION)
|
||||
.addStatement("validateCollection((\$T) \$L, CollectionValidationRule.EXCEPTION_IF_ANY_INVALID)", Types.COLLECTION, name)
|
||||
.endControlFlow()
|
||||
validateMethod
|
||||
.beginControlFlow("if (\$L instanceof \$T)", name, Types.MAP)
|
||||
.addStatement("validateCollection(((\$T) \$L).values(), CollectionValidationRule.EXCEPTION_IF_ANY_INVALID)", Types.MAP, name)
|
||||
.endControlFlow()
|
||||
return
|
||||
}
|
||||
if (nullable) {
|
||||
if (couldContainsNull()) {
|
||||
validateMethod.beginControlFlow("if (\$L != null)", name)
|
||||
}
|
||||
if (type == FieldType.LIST) {
|
||||
|
|
@ -617,7 +651,7 @@ class FieldInfo {
|
|||
} else {
|
||||
throw new Exception("Unexpected able to validate field type '" + type + "' of field " + name)
|
||||
}
|
||||
if (nullable) {
|
||||
if (couldContainsNull()) {
|
||||
validateMethod.endControlFlow()
|
||||
}
|
||||
}
|
||||
|
|
@ -650,11 +684,24 @@ class ClassObject extends SchemeObject {
|
|||
|
||||
static final String PREFIX = "class "
|
||||
|
||||
private static ClassObject resolveBaseTypeModel(final String typeString, final Map<String, SchemeObject> objects) {
|
||||
final String baseTypeString = TypeNameUtils.extractBaseTypeString(typeString)
|
||||
final SchemeObject associatedObject = objects.get(baseTypeString)
|
||||
if (associatedObject instanceof ClassObject) {
|
||||
return associatedObject
|
||||
}
|
||||
if (associatedObject instanceof ImportObject && associatedObject.relatedModel != null) {
|
||||
return associatedObject.relatedModel
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
final String name
|
||||
final Map<String, String> fieldsInfo
|
||||
final List<FieldInfo> fields = new ArrayList<>()
|
||||
final List<String> typeVariables = new ArrayList<>()
|
||||
final List<String> typeArguments = new ArrayList<>()
|
||||
TypeName superclass
|
||||
ClassObject parentModel
|
||||
|
||||
ClassObject(final String name, final Map<String, String> fieldsInfo) {
|
||||
this.name = name.trim()
|
||||
|
|
@ -663,20 +710,21 @@ class ClassObject extends SchemeObject {
|
|||
|
||||
void resolveFieldsInfo(final Map<String, SchemeObject> objects) {
|
||||
final Set<String> fieldNames = new HashSet<>()
|
||||
for (final Map.Entry entry : fieldsInfo.entrySet()) {
|
||||
for (final Entry entry : fieldsInfo.entrySet()) {
|
||||
if (fieldNames.contains(entry.key)) {
|
||||
throw new Exception("Duplicate field name: " + name)
|
||||
}
|
||||
|
||||
if (entry.key.equals("typeVariables")) {
|
||||
if (entry.key.equals("typeArguments")) {
|
||||
for (String typeVariable : entry.value.replace(" ", "").split(",")) {
|
||||
typeVariables.add(typeVariable)
|
||||
typeArguments.add(typeVariable)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (entry.key.equals("extends")) {
|
||||
superclass = TypeNameUtils.resolveTypeName(entry.value, objects)
|
||||
parentModel = resolveBaseTypeModel(entry.value, objects)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -696,25 +744,84 @@ class ClassObject extends SchemeObject {
|
|||
}
|
||||
}
|
||||
|
||||
private MethodSpec.Builder createFullConstructorWithParent(final List<String> parameters, final List<String> childTypeArguments) {
|
||||
final MethodSpec.Builder result
|
||||
if (parentModel != null) {
|
||||
final List<String> resolvedTypeArguments = new ArrayList<>()
|
||||
if (superclass instanceof ParameterizedTypeName) {
|
||||
for (final TypeName typeName : superclass.typeArguments) {
|
||||
final int argIndex = typeArguments.indexOf(typeName.toString())
|
||||
if (argIndex >= 0) {
|
||||
resolvedTypeArguments.add(childTypeArguments.get(argIndex))
|
||||
} else {
|
||||
resolvedTypeArguments.add(typeName.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
result = parentModel.createFullConstructorWithParent(parameters, resolvedTypeArguments)
|
||||
} else {
|
||||
result = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC)
|
||||
}
|
||||
for (final FieldInfo field : fields) {
|
||||
final int argIndex = typeArguments.indexOf(field.typeName.toString())
|
||||
if (argIndex >= 0) {
|
||||
result.addParameter(ParameterSpec.builder(ClassName.bestGuess(childTypeArguments.get(argIndex)), field.name, Modifier.FINAL)
|
||||
.addAnnotation(field.couldContainsNull() ? Types.NULLABLE : Types.NON_NULL)
|
||||
.build())
|
||||
} else {
|
||||
result.addParameter(ParameterSpec.builder(field.typeName, field.name, Modifier.FINAL)
|
||||
.addAnnotation(field.couldContainsNull() ? Types.NULLABLE : Types.NON_NULL)
|
||||
.build())
|
||||
}
|
||||
parameters.add(field.name)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeToFile(final File directory, final Map<String, SchemeObject> objects, final String packageName) {
|
||||
final TypeSpec.Builder classBuilder = TypeSpec.classBuilder(name).addModifiers(Modifier.PUBLIC)
|
||||
.addAnnotation(AnnotationSpec.builder(Types.JSON_OBJECT).addMember("serializeNullObjects", "true").build())
|
||||
.superclass(superclass != null ? superclass : Types.LOGAN_SQUARE_JSON_MODEL)
|
||||
|
||||
final TypeName[] arguments = new TypeName[typeArguments.size()]
|
||||
int index = 0
|
||||
// adds type variables
|
||||
for (String typeVariable : typeVariables) {
|
||||
for (final String typeVariable : typeArguments) {
|
||||
classBuilder.addTypeVariable(TypeVariableName.get(typeVariable))
|
||||
arguments[index++] = TypeVariableName.get(typeVariable)
|
||||
}
|
||||
|
||||
final TypeName thisTypeName = arguments.length > 0 ? ParameterizedTypeName.get(ClassName.bestGuess(name), arguments) : ClassName.bestGuess(name)
|
||||
|
||||
// adds default constructor
|
||||
classBuilder.addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addStatement("super()").build())
|
||||
|
||||
// creates full constructor only if it is extends from LoganSquareJsonModel,
|
||||
// else we can't create constructor as parent constructor could also have parameters
|
||||
final MethodSpec.Builder fullConstructorBuilder = superclass == null ?
|
||||
MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addStatement("super()")
|
||||
: null
|
||||
final MethodSpec.Builder fullConstructorBuilder
|
||||
if (superclass == null) {
|
||||
fullConstructorBuilder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addStatement("super()")
|
||||
} else if (parentModel != null) {
|
||||
final List<String> parameters = new ArrayList<>()
|
||||
final List<String> typeArguments = new ArrayList<>()
|
||||
if (superclass instanceof ParameterizedTypeName) {
|
||||
for (final TypeName typeName : superclass.typeArguments) {
|
||||
typeArguments.add(typeName.toString())
|
||||
}
|
||||
}
|
||||
fullConstructorBuilder = parentModel.createFullConstructorWithParent(parameters, typeArguments)
|
||||
fullConstructorBuilder.addStatement("super(\$L)", parameters.join(", "))
|
||||
} else {
|
||||
fullConstructorBuilder = null
|
||||
}
|
||||
|
||||
// creates copy logic method
|
||||
final MethodSpec.Builder copyToMethod = MethodSpec.methodBuilder("copyTo").addModifiers(Modifier.PROTECTED)
|
||||
.addParameter(ParameterSpec.builder(thisTypeName, "destination", Modifier.FINAL).addAnnotation(Types.NON_NULL).build())
|
||||
if (parentModel != null) {
|
||||
copyToMethod.addStatement("super.copyTo(destination)")
|
||||
}
|
||||
|
||||
// creates validate() method
|
||||
final MethodSpec.Builder validateMethod = MethodSpec.methodBuilder("validate").addModifiers(Modifier.PUBLIC)
|
||||
|
|
@ -747,9 +854,9 @@ class ClassObject extends SchemeObject {
|
|||
classBuilder.addMethod(field.generateGetterCode())
|
||||
classBuilder.addMethod(field.generateSetterCode())
|
||||
field.generateValidationCode(validateMethod)
|
||||
final String serializeMethodName = (!field.nullable && field.type.serializationMethodName != null
|
||||
final String serializeMethodName = (!field.couldContainsNull() && field.type.serializationMethodName != null
|
||||
? field.type.serializationMethodName : "writeObject");
|
||||
final String deserializeMethodName = (!field.nullable && field.type.deserializationMethodName != null
|
||||
final String deserializeMethodName = (!field.couldContainsNull() && field.type.deserializationMethodName != null
|
||||
? field.type.deserializationMethodName : "readObject");
|
||||
serializeMethod.addStatement("outputStream.\$L(\$L)", serializeMethodName, field.name)
|
||||
if (deserializeMethodName.equals("readObject")) {
|
||||
|
|
@ -760,15 +867,24 @@ class ClassObject extends SchemeObject {
|
|||
|
||||
if (fullConstructorBuilder != null) {
|
||||
fullConstructorBuilder.addParameter(ParameterSpec.builder(field.typeName, field.name, Modifier.FINAL)
|
||||
.addAnnotation(field.nullable ? Types.NULLABLE : Types.NON_NULL)
|
||||
.addAnnotation(field.couldContainsNull() ? Types.NULLABLE : Types.NON_NULL)
|
||||
.build())
|
||||
if (field.type == FieldType.LIST) {
|
||||
fullConstructorBuilder.addStatement("this.\$L = \$T.unmodifiableList(\$L)", field.name, Types.COLLECTIONS, field.name)
|
||||
} else if (field.type == FieldType.MAP) {
|
||||
fullConstructorBuilder.addStatement("this.\$L = \$T.unmodifiableMap(\$L)", field.name, Types.COLLECTIONS, field.name)
|
||||
} else {
|
||||
}
|
||||
if (field.type == FieldType.LIST) {
|
||||
if (fullConstructorBuilder != null) {
|
||||
fullConstructorBuilder.addStatement("this.\$L = new \$T<>(\$L)", field.name, Types.ARRAY_LIST, field.name)
|
||||
}
|
||||
copyToMethod.addStatement("destination.\$L = new \$T<>(\$L)", field.name, Types.ARRAY_LIST, field.name)
|
||||
} else if (field.type == FieldType.MAP) {
|
||||
if (fullConstructorBuilder != null) {
|
||||
fullConstructorBuilder.addStatement("this.\$L = new \$T<>(\$L)", field.name, Types.HASH_MAP, field.name)
|
||||
}
|
||||
copyToMethod.addStatement("destination.\$L = new \$T<>(\$L)", field.name, Types.HASH_MAP, field.name)
|
||||
} else {
|
||||
if (fullConstructorBuilder != null) {
|
||||
fullConstructorBuilder.addStatement("this.\$L = \$L", field.name, field.name)
|
||||
}
|
||||
copyToMethod.addStatement("destination.\$L = \$L", field.name, field.name)
|
||||
}
|
||||
|
||||
if (first) {
|
||||
|
|
@ -799,6 +915,17 @@ class ClassObject extends SchemeObject {
|
|||
|
||||
// creates validate() method
|
||||
classBuilder.addMethod(validateMethod.build())
|
||||
// creates copyTo() method
|
||||
classBuilder.addMethod(copyToMethod.build())
|
||||
// creates copy() method
|
||||
classBuilder.addMethod(MethodSpec.methodBuilder("copy").addModifiers(Modifier.PUBLIC)
|
||||
.returns(thisTypeName)
|
||||
.addAnnotation(Types.NON_NULL)
|
||||
.addStatement("final \$T result = new \$T()", thisTypeName, thisTypeName)
|
||||
.addStatement("this.copyTo(result)")
|
||||
.addStatement("return result")
|
||||
.addJavadoc("Beware! It is not copying objects stored in fields.")
|
||||
.build())
|
||||
// adds equals() method
|
||||
classBuilder.addMethod(MethodSpec.methodBuilder("equals").addModifiers(Modifier.PUBLIC)
|
||||
.addAnnotation(Override.class)
|
||||
|
|
@ -840,8 +967,7 @@ class FileUtils {
|
|||
}
|
||||
}
|
||||
|
||||
static void generateJsonModelsCode(final File generatedModelsDirectory, final String schemeFilePath,
|
||||
final String modelsPackage, final String projectDir) {
|
||||
static Map<String, SchemeObject> getObjectsMap(final String schemeFilePath, final String projectDir) {
|
||||
if (schemeFilePath == null) {
|
||||
return
|
||||
}
|
||||
|
|
@ -856,26 +982,35 @@ class FileUtils {
|
|||
|
||||
final Yaml yaml = new Yaml()
|
||||
final Map<String, SchemeObject> schemeObjects = new HashMap<>()
|
||||
schemeObjects.put("Map", new ImportObject("java.util.Map"))
|
||||
schemeObjects.put("List", new ImportObject("java.util.List"))
|
||||
schemeObjects.put("DateTime", new ImportObject("org.joda.time.DateTime"))
|
||||
schemeObjects.put("Map", new ImportObject("java.util.Map", ImportObject.Type.EXTERNAL, null))
|
||||
schemeObjects.put("List", new ImportObject("java.util.List", ImportObject.Type.EXTERNAL, null))
|
||||
schemeObjects.put("DateTime", new ImportObject("org.joda.time.DateTime", ImportObject.Type.EXTERNAL, null))
|
||||
|
||||
for (final Object data : yaml.loadAll(new FileReader(schemeFile))) {
|
||||
if (!(data instanceof Map)) {
|
||||
throw new Exception("Yaml file '" + schemeFile + "' is invalid")
|
||||
}
|
||||
|
||||
for (final Map.Entry<String, Object> entry : data.entrySet()) {
|
||||
for (final Entry<String, Object> entry : data.entrySet()) {
|
||||
if (entry.key.equals(ImportObject.GROUP_NAME)) {
|
||||
for (String importString : (Iterable) entry.value) {
|
||||
final ImportObject importObject = new ImportObject(importString)
|
||||
final ImportObject importObject = new ImportObject(importString, ImportObject.Type.EXTERNAL, null)
|
||||
if (schemeObjects.containsKey(importObject.name)) {
|
||||
throw new Exception("Duplicate import object with name '" + importObject.name + "' in file " + schemeFile.getPath())
|
||||
}
|
||||
schemeObjects.put(importObject.name, importObject)
|
||||
}
|
||||
} else if (entry.key.startsWith(EnumObject.PREFIX)) {
|
||||
final EnumObject enumObject = new EnumObject(entry.key.substring(EnumObject.PREFIX.length()), entry.value)
|
||||
if (schemeObjects.containsKey(enumObject.name)) {
|
||||
throw new Exception("Duplicate enum object with name '" + enumObject.name + "' in file " + schemeFile.getPath())
|
||||
}
|
||||
schemeObjects.put(enumObject.name, enumObject)
|
||||
} else if (entry.key.startsWith(ClassObject.PREFIX)) {
|
||||
final ClassObject classObject = new ClassObject(entry.key.substring(ClassObject.PREFIX.length()), entry.value)
|
||||
if (schemeObjects.containsKey(classObject.name)) {
|
||||
throw new Exception("Duplicate class object with name '" + classObject.name + "' in file " + schemeFile.getPath())
|
||||
}
|
||||
schemeObjects.put(classObject.name, classObject)
|
||||
} else {
|
||||
throw new Exception("Unexpected scheme object: " + entry.key)
|
||||
|
|
@ -883,20 +1018,7 @@ class FileUtils {
|
|||
}
|
||||
}
|
||||
|
||||
for (final SchemeObject schemeObject : schemeObjects.values()) {
|
||||
if (schemeObject instanceof ClassObject) {
|
||||
try {
|
||||
schemeObject.resolveFieldsInfo(schemeObjects)
|
||||
} catch (final Exception exception) {
|
||||
throw new Exception("Error on parsing class '" + schemeObject.name + "' : " + exception.getMessage())
|
||||
}
|
||||
}
|
||||
try {
|
||||
schemeObject.writeToFile(generatedModelsDirectory, schemeObjects, modelsPackage)
|
||||
} catch (final Exception exception) {
|
||||
throw new Exception("Error on generating code for '" + schemeObject.name + "' : " + exception.getMessage())
|
||||
}
|
||||
}
|
||||
return schemeObjects
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -911,18 +1033,66 @@ android.applicationVariants.all {
|
|||
final List<String> jsonModelsMapping = android.extensions.findByName("jsonModelsMapping")
|
||||
|
||||
FileUtils.purgeDirectory(generatedModelsDirectory)
|
||||
final Map<String, Map<String, SchemeObject>> overallObjects = new HashMap<>()
|
||||
for (final String jsonMapping : jsonModelsMapping) {
|
||||
final int indexOfDivider = jsonMapping.indexOf('->')
|
||||
final String packageName
|
||||
final Map<String, SchemeObject> objects
|
||||
if (indexOfDivider == -1) {
|
||||
FileUtils.generateJsonModelsCode(generatedModelsDirectory,
|
||||
jsonMapping.trim(),
|
||||
android.defaultConfig.applicationId + '.logic.model',
|
||||
"${project.projectDir}")
|
||||
packageName = android.defaultConfig.applicationId + '.logic.model'
|
||||
objects = FileUtils.getObjectsMap(jsonMapping.trim(), "${project.projectDir}")
|
||||
} else {
|
||||
FileUtils.generateJsonModelsCode(generatedModelsDirectory,
|
||||
jsonMapping.substring(0, indexOfDivider).trim(),
|
||||
jsonMapping.substring(indexOfDivider + 2).trim(),
|
||||
"${project.projectDir}")
|
||||
packageName = jsonMapping.substring(indexOfDivider + 2).trim()
|
||||
objects = FileUtils.getObjectsMap(jsonMapping.substring(0, indexOfDivider).trim(), "${project.projectDir}")
|
||||
}
|
||||
if (overallObjects.containsKey(packageName)) {
|
||||
overallObjects.get(packageName).putAll(objects)
|
||||
} else {
|
||||
overallObjects.put(packageName, objects)
|
||||
}
|
||||
}
|
||||
|
||||
for (final Entry<String, Map<String, SchemeObject>> fileObjects : overallObjects.entrySet()) {
|
||||
final String packageName = fileObjects.key
|
||||
final Map<String, SchemeObject> schemeObjects = new HashMap<>(fileObjects.value)
|
||||
for (final Entry<String, Map<String, SchemeObject>> externalObjects : overallObjects.entrySet()) {
|
||||
if (externalObjects.key == packageName) {
|
||||
continue
|
||||
}
|
||||
for (final SchemeObject externalObject : externalObjects.value.values()) {
|
||||
if (schemeObjects.containsKey(externalObject.name)) {
|
||||
if (!(externalObject instanceof ImportObject) || externalObject.type != ImportObject.Type.EXTERNAL) {
|
||||
throw new Exception("Duplicate model name '" + externalObject.name + "' for package " + packageName)
|
||||
}
|
||||
}
|
||||
if (externalObject instanceof ImportObject) {
|
||||
schemeObjects.put(externalObject.name, externalObject)
|
||||
} else if (externalObject instanceof EnumObject) {
|
||||
schemeObjects.put(externalObject.name,
|
||||
new ImportObject(externalObjects.key + '.' + externalObject.name, ImportObject.Type.ENUM, null))
|
||||
} else if (externalObject instanceof ClassObject) {
|
||||
schemeObjects.put(externalObject.name,
|
||||
new ImportObject(externalObjects.key + '.' + externalObject.name, ImportObject.Type.MODEL, externalObject))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final SchemeObject schemeObject : schemeObjects.values()) {
|
||||
if (schemeObject instanceof ClassObject) {
|
||||
try {
|
||||
schemeObject.resolveFieldsInfo(schemeObjects)
|
||||
} catch (final Exception exception) {
|
||||
throw new Exception("Error on parsing class '" + schemeObject.name + "' : " + exception.getMessage())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final SchemeObject schemeObject : schemeObjects.values()) {
|
||||
try {
|
||||
schemeObject.writeToFile(generatedModelsDirectory, schemeObjects, packageName)
|
||||
} catch (final Exception exception) {
|
||||
throw new Exception("Error on generating code for '" + schemeObject.name + "' : " + exception.getMessage())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue