From 1e44a98074e393dcad5a9e78c4cea8938a46584c Mon Sep 17 00:00:00 2001 From: Fabien RECCO Date: Mon, 15 Apr 2019 15:19:38 +0200 Subject: [PATCH] Support of private fields in Resource --- .../vault/compiler/ModelInjection.java | 35 +++++++--- .../contentful/vault/compiler/Processor.java | 65 ++++++++++--------- .../vault/compiler/ContentTypeTest.java | 5 +- .../contentful/vault/compiler/FieldTest.java | 2 +- .../src/test/resources/ModelInjection.java | 12 +++- .../java/com/contentful/vault/FieldMeta.java | 13 ++++ 6 files changed, 90 insertions(+), 42 deletions(-) diff --git a/compiler/src/main/java/com/contentful/vault/compiler/ModelInjection.java b/compiler/src/main/java/com/contentful/vault/compiler/ModelInjection.java index f022a7b..bc4ac42 100644 --- a/compiler/src/main/java/com/contentful/vault/compiler/ModelInjection.java +++ b/compiler/src/main/java/com/contentful/vault/compiler/ModelInjection.java @@ -81,6 +81,10 @@ private void appendConstructor(TypeSpec.Builder builder) { .add(".setId($S)", f.id()) .add(".setName($S)", f.name()); + if (f.setter() != null) { + block.add(".setSetter($S)", f.setter()); + } + if (f.sqliteType() != null) { block.add(".setSqliteType($S)", f.sqliteType()); } @@ -122,7 +126,7 @@ private void appendSetField(TypeSpec.Builder builder) { } else { method.endControlFlow().beginControlFlow("else if ($S.equals(name))", field.name()); } - method.addStatement("resource.$L = ($T) value", field.name(), field.type()); + addStatement(method, field, "($T) value", "resource", field.type()); } method.endControlFlow() .beginControlFlow("else") @@ -154,22 +158,20 @@ private void appendFromCursor(TypeSpec.Builder builder) { FieldMeta field = nonLinkFields.get(i); int columnIndex = RESOURCE_COLUMNS.length + i; String fqClassName = field.type().toString(); - String name = field.name(); if (String.class.getName().equals(fqClassName)) { - method.addStatement("$N.$L = cursor.getString($L)", result, name, columnIndex); + addStatement(method, field,"cursor.getString($L)", result, columnIndex); } else if (Boolean.class.getName().equals(fqClassName)) { - method.addStatement("$N.$L = Integer.valueOf(1).equals(cursor.getInt($L))", result, - name, columnIndex); + addStatement(method, field, "Integer.valueOf(1).equals(cursor.getInt($L))", result, columnIndex); } else if (Integer.class.getName().equals(fqClassName)) { - method.addStatement("$N.$L = cursor.getInt($L)", result, name, columnIndex); + addStatement(method, field, "cursor.getInt($L)", result, columnIndex); } else if (Double.class.getName().equals(fqClassName)) { - method.addStatement("$N.$L = cursor.getDouble($L)", result, name, columnIndex); + addStatement(method, field, "cursor.getDouble($L)", result, columnIndex); } else if (Map.class.getName().equals(fqClassName)) { - method.addStatement("$N.$L = fieldFromBlob($T.class, cursor, $L)", result, name, + addStatement(method, field, "fieldFromBlob($T.class, cursor, $L)", result, ClassName.get(HashMap.class), columnIndex); } else if (field.isArrayOfSymbols()) { - method.addStatement("$N.$L = fieldFromBlob($T.class, cursor, $L)", result, name, + addStatement(method, field, "fieldFromBlob($T.class, cursor, $L)", result, ClassName.get(ArrayList.class), columnIndex); } } @@ -178,6 +180,21 @@ private void appendFromCursor(TypeSpec.Builder builder) { builder.addMethod(method.build()); } + private void addStatement(MethodSpec.Builder method, FieldMeta field, String operation, String resource, Object... args) { + Object[] newArgs = new Object[args.length + 2]; + System.arraycopy(args, 0, newArgs, 2, args.length); + newArgs[0] = resource; + + if(field.setter() != null) { + newArgs[1] = field.setter(); + method.addStatement("$N.$L(" + operation + ")", newArgs); + } + else { + newArgs[1] = field.name(); + method.addStatement("$N.$L = " + operation, newArgs); + } + } + private void appendCreateStatements(TypeSpec.Builder builder) { MethodSpec.Builder method = MethodSpec.methodBuilder("getCreateStatements") .returns(ParameterizedTypeName.get(List.class, String.class)) diff --git a/compiler/src/main/java/com/contentful/vault/compiler/Processor.java b/compiler/src/main/java/com/contentful/vault/compiler/Processor.java index a1f316d..28b115f 100644 --- a/compiler/src/main/java/com/contentful/vault/compiler/Processor.java +++ b/compiler/src/main/java/com/contentful/vault/compiler/Processor.java @@ -16,48 +16,32 @@ package com.contentful.vault.compiler; -import com.contentful.vault.ContentType; -import com.contentful.vault.Field; -import com.contentful.vault.FieldMeta; -import com.contentful.vault.Resource; -import com.contentful.vault.Space; +import com.contentful.vault.*; import com.google.common.base.Joiner; import com.squareup.javapoet.ClassName; import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Type; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import org.apache.commons.lang3.StringUtils; + import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.SourceVersion; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; +import javax.lang.model.element.*; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; -import org.apache.commons.lang3.StringUtils; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.annotation.Annotation; +import java.util.*; import static com.contentful.java.cda.CDAType.ASSET; import static com.contentful.java.cda.CDAType.ENTRY; -import static com.contentful.vault.Constants.SUFFIX_FIELDS; -import static com.contentful.vault.Constants.SUFFIX_MODEL; -import static com.contentful.vault.Constants.SUFFIX_SPACE; +import static com.contentful.vault.Constants.*; import static javax.tools.Diagnostic.Kind.ERROR; public class Processor extends AbstractProcessor { @@ -248,15 +232,21 @@ private void parseContentType(TypeElement element, Map modifiers = enclosedElement.getModifiers(); if (modifiers.contains(Modifier.STATIC)) { error(element, "@%s elements must not be static. (%s.%s)", Field.class.getSimpleName(), element.getQualifiedName(), enclosedElement.getSimpleName()); return; } - if (modifiers.contains(Modifier.PRIVATE)) { - error(element, "@%s elements must not be private. (%s.%s)", Field.class.getSimpleName(), - element.getQualifiedName(), enclosedElement.getSimpleName()); + + String setter = getSetter(element, enclosedElement); + if(setter != null) { + fieldBuilder.setSetter(setter); + } + else if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.PROTECTED)) { + error(element, "@%s private elements must have public setter methods. (%s.%s)", Field.class.getSimpleName(), + element.getQualifiedName(), enclosedElement.getSimpleName()); return; } @@ -267,7 +257,6 @@ private void parseContentType(TypeElement element, Map typeArguments = declaredType.getTypeArguments(); @@ -333,6 +322,22 @@ private void parseContentType(TypeElement element, Map methodsIn = ElementFilter.methodsIn(elementUtils.getAllMembers(element)); + for(ExecutableElement method : methodsIn) { + Name methodName = method.getSimpleName(); + String fluentSetterName = enclosedElement.getSimpleName().toString(); + String setterName = "set" + StringUtils.capitalize(fluentSetterName); + if((methodName.contentEquals(setterName) || methodName.contentEquals(fluentSetterName)) + && method.getParameters().size() == 1 + && method.getModifiers().contains(Modifier.PUBLIC) + && typeUtils.isSameType(method.getParameters().get(0).asType(), enclosedElement.asType())) { + return methodName.toString(); + } + } + return null; + } + private boolean isValidListType(TypeMirror typeMirror) { return isSubtypeOfType(typeMirror, String.class.getName()) || isSubtypeOfType(typeMirror, Resource.class.getName()); diff --git a/compiler/src/test/java/com/contentful/vault/compiler/ContentTypeTest.java b/compiler/src/test/java/com/contentful/vault/compiler/ContentTypeTest.java index 8cccaa9..38ccaad 100644 --- a/compiler/src/test/java/com/contentful/vault/compiler/ContentTypeTest.java +++ b/compiler/src/test/java/com/contentful/vault/compiler/ContentTypeTest.java @@ -35,7 +35,6 @@ public class ContentTypeTest { "import com.contentful.vault.ContentType;", "import com.contentful.vault.Field;", "import com.contentful.vault.Resource;", - "import com.contentful.vault.SpaceHelper;", "import java.util.List;", "import java.util.Map;", "class Test {", @@ -51,6 +50,10 @@ public class ContentTypeTest { " @Field List arrayOfAssets;", " @Field List arrayOfModels;", " @Field List arrayOfSymbols;", + " @Field private String privateField;", + " @Field private String privateFluentField;", + " public void setPrivateField(String privateField) { this.privateField = privateField; }", + " public void privateFluentField(String privateFluentField) { this.privateFluentField = privateFluentField; }", " }", "}" )); diff --git a/compiler/src/test/java/com/contentful/vault/compiler/FieldTest.java b/compiler/src/test/java/com/contentful/vault/compiler/FieldTest.java index 87a5eb1..7bb2294 100644 --- a/compiler/src/test/java/com/contentful/vault/compiler/FieldTest.java +++ b/compiler/src/test/java/com/contentful/vault/compiler/FieldTest.java @@ -132,7 +132,7 @@ public class FieldTest { assert_().about(javaSource()).that(source) .processedWith(processors()) .failsToCompile() - .withErrorContaining("@Field elements must not be private. (Test.foo)"); + .withErrorContaining("@Field private elements must have public setter methods. (Test.foo)"); } @Test public void testInvalidListType() throws Exception { diff --git a/compiler/src/test/resources/ModelInjection.java b/compiler/src/test/resources/ModelInjection.java index 60d9bb2..2d538cd 100644 --- a/compiler/src/test/resources/ModelInjection.java +++ b/compiler/src/test/resources/ModelInjection.java @@ -24,6 +24,8 @@ public final class Test$AwesomeModel$$ModelHelper extends ModelHelper getCreateStatements(SpaceHelper spaceHelper) { List list = new ArrayList(); for (String code : spaceHelper.getLocales()) { - list.add("CREATE TABLE `entry_y2lk$" + code + "` (`remote_id` STRING NOT NULL UNIQUE, `created_at` STRING NOT NULL, `updated_at` STRING, `textField` TEXT, `booleanField` BOOL, `integerField` INT, `doubleField` DOUBLE, `mapField` BLOB, `arrayOfSymbols` BLOB);"); + list.add("CREATE TABLE `entry_y2lk$" + code + "` (`remote_id` STRING NOT NULL UNIQUE, `created_at` STRING NOT NULL, `updated_at` STRING, `textField` TEXT, `booleanField` BOOL, `integerField` INT, `doubleField` DOUBLE, `mapField` BLOB, `arrayOfSymbols` BLOB, `privateField` TEXT, `privateFluentField` TEXT);"); } return list; } @@ -56,6 +58,8 @@ public Test.AwesomeModel fromCursor(Cursor cursor) { result.doubleField = cursor.getDouble(6); result.mapField = fieldFromBlob(HashMap.class, cursor, 7); result.arrayOfSymbols = fieldFromBlob(ArrayList.class, cursor, 8); + result.setPrivateField(cursor.getString(9)); + result.privateFluentField(cursor.getString(10)); return result; } @@ -92,6 +96,12 @@ else if ("arrayOfModels".equals(name)) { else if ("arrayOfSymbols".equals(name)) { resource.arrayOfSymbols = (List) value; } + else if ("privateField".equals(name)) { + resource.setPrivateField((String) value); + } + else if ("privateFluentField".equals(name)) { + resource.privateFluentField((String) value); + } else { return false; } diff --git a/core/src/main/java/com/contentful/vault/FieldMeta.java b/core/src/main/java/com/contentful/vault/FieldMeta.java index 773e545..7584520 100644 --- a/core/src/main/java/com/contentful/vault/FieldMeta.java +++ b/core/src/main/java/com/contentful/vault/FieldMeta.java @@ -23,6 +23,8 @@ public final class FieldMeta { private final String name; + private final String setter; + private final TypeMirror type; private final String sqliteType; @@ -34,6 +36,7 @@ public final class FieldMeta { FieldMeta(Builder builder) { this.id = builder.id; this.name = builder.name; + this.setter = builder.setter; this.type = builder.type; this.sqliteType = builder.sqliteType; this.linkType = builder.linkType; @@ -48,6 +51,10 @@ public String name() { return name; } + public String setter() { + return setter; + } + public TypeMirror type() { return type; } @@ -100,6 +107,7 @@ public static class Builder { String sqliteType; String linkType; String arrayType; + String setter; public Builder setId(String id) { this.id = id; @@ -111,6 +119,11 @@ public Builder setName(String name) { return this; } + public Builder setSetter(String setter) { + this.setter = setter; + return this; + } + public Builder setType(TypeMirror type) { this.type = type; return this;