From 41cbfae077c5bcbad84bd3277003a7476fea2acd Mon Sep 17 00:00:00 2001
From: Bogdan Kobylynskyi <92bogdan@gmail.com>
Date: Thu, 5 Dec 2019 10:39:03 -0600
Subject: [PATCH] Introduce model annotations (for Lombok) #10
---
README.md | 1 +
.../InputDefinitionToDataModelMapper.java | 2 +-
.../TypeDefinitionToDataModelMapper.java | 10 +--
.../codegen/model/DataModelFields.java | 1 +
.../graphql/codegen/model/MappingConfig.java | 13 ++-
.../templates/javaClassGraphqlType.ftl | 3 +
.../graphql/codegen/GraphqlCodegenTest.java | 13 +++
.../Event_with_lombok_annotations.java.txt | 88 +++++++++++++++++++
8 files changed, 124 insertions(+), 7 deletions(-)
create mode 100644 src/test/resources/expected-classes/Event_with_lombok_annotations.java.txt
diff --git a/README.md b/README.md
index d893318b8..37db4cff1 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,7 @@ Please refer to:
| modelValidationAnnotation | String | @javax.validation.
constraints.NotNull | Annotation for mandatory (NonNull) fields. Can be null/empty. |
| modelNamePrefix | String | Empty | Sets the prefix for GraphQL model classes (type, input, interface, enum, union). |
| modelNameSuffix | String | Empty | Sets the suffix for GraphQL model classes (type, input, interface, enum, union). |
+| modelAnnotations | String | Empty | Annotations that will be added to model classes (type, input). |
| generateEqualsAndHashCode | Boolean | False | Specifies whether generated model classes should have equals and hashCode methods defined. |
| generateToString | Boolean | False | Specifies whether generated model classes should have toString method defined. |
diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java
index b8d715858..6d9c7bddb 100644
--- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java
+++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/InputDefinitionToDataModelMapper.java
@@ -28,11 +28,11 @@ public static Map map(MappingConfig mappingConfig, InputObjectTy
dataModel.put(PACKAGE, packageName);
dataModel.put(IMPORTS, MapperUtils.getImports(mappingConfig, packageName));
dataModel.put(CLASS_NAME, MapperUtils.getClassNameWithPrefixAndSuffix(mappingConfig, typeDefinition));
+ dataModel.put(ANNOTATIONS, mappingConfig.getModelAnnotations());
dataModel.put(NAME, typeDefinition.getName());
dataModel.put(FIELDS, InputValueDefinitionToParameterMapper.map(mappingConfig, typeDefinition.getInputValueDefinitions(), typeDefinition.getName()));
dataModel.put(EQUALS_AND_HASH_CODE, mappingConfig.getGenerateEqualsAndHashCode());
dataModel.put(TO_STRING, mappingConfig.getGenerateToString());
-
return dataModel;
}
diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java
index f5734bd6c..d65c9571b 100644
--- a/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java
+++ b/src/main/java/com/kobylynskyi/graphql/codegen/mapper/TypeDefinitionToDataModelMapper.java
@@ -33,16 +33,17 @@ public static Map map(MappingConfig mappingConfig, ObjectTypeDef
dataModel.put(PACKAGE, packageName);
dataModel.put(IMPORTS, MapperUtils.getImports(mappingConfig, packageName));
dataModel.put(CLASS_NAME, MapperUtils.getClassNameWithPrefixAndSuffix(mappingConfig, typeDefinition));
- Set allInterfaces = new LinkedHashSet<>();
- allInterfaces.addAll(MapperUtils.getUnionsHavingType(mappingConfig, typeDefinition, document));
+ dataModel.put(ANNOTATIONS, mappingConfig.getModelAnnotations());
+ Set allInterfaces = new LinkedHashSet<>(
+ MapperUtils.getUnionsHavingType(mappingConfig, typeDefinition, document));
typeDefinition.getImplements().stream()
.map(anImplement -> GraphqlTypeToJavaTypeMapper.getJavaType(mappingConfig, anImplement))
.forEach(allInterfaces::add);
dataModel.put(IMPLEMENTS, allInterfaces);
- Set allParameters = new LinkedHashSet<>();
// Merge attributes from the type and attributes from the interface
- allParameters.addAll(FieldDefinitionToParameterMapper.map(mappingConfig, typeDefinition.getFieldDefinitions(), typeDefinition.getName()));
+ Set allParameters = new LinkedHashSet<>(FieldDefinitionToParameterMapper
+ .map(mappingConfig, typeDefinition.getFieldDefinitions(), typeDefinition.getName()));
List interfaces = getInterfacesOfType(mappingConfig, typeDefinition, document);
interfaces.stream()
.map(i -> FieldDefinitionToParameterMapper.map(mappingConfig, i.getFieldDefinitions(), i.getName()))
@@ -51,7 +52,6 @@ public static Map map(MappingConfig mappingConfig, ObjectTypeDef
dataModel.put(EQUALS_AND_HASH_CODE, mappingConfig.getGenerateEqualsAndHashCode());
dataModel.put(TO_STRING, mappingConfig.getGenerateToString());
-
return dataModel;
}
diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java
index 08b8d733e..d748b8eea 100644
--- a/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java
+++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/DataModelFields.java
@@ -13,6 +13,7 @@ public final class DataModelFields {
public static final String NAME = "name";
public static final String FIELDS = "fields";
public static final String IMPLEMENTS = "implements";
+ public static final String ANNOTATIONS = "annotations";
public static final String OPERATIONS = "operations";
public static final String EQUALS_AND_HASH_CODE = "equalsAndHashCode";
public static final String TO_STRING = "toString";
diff --git a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java
index 1d787d1c2..83c910a4e 100644
--- a/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java
+++ b/src/main/java/com/kobylynskyi/graphql/codegen/model/MappingConfig.java
@@ -1,7 +1,9 @@
package com.kobylynskyi.graphql.codegen.model;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import lombok.Data;
@@ -27,6 +29,11 @@ public class MappingConfig implements Combinable {
*/
private Map customAnnotationsMapping = new HashMap<>();
+ /**
+ * Custom annotations for model classes.
+ */
+ private Set modelAnnotations = new HashSet<>();
+
private Boolean generateApis;
private String packageName;
private String apiPackageName;
@@ -67,6 +74,11 @@ public void combine(MappingConfig source) {
} else if (this.customAnnotationsMapping == null && source.customAnnotationsMapping != null) {
this.customAnnotationsMapping = source.customAnnotationsMapping;
}
+ if (this.modelAnnotations != null && source.modelAnnotations != null) {
+ this.modelAnnotations.addAll(source.modelAnnotations);
+ } else if (this.modelAnnotations == null && source.modelAnnotations != null) {
+ this.modelAnnotations = source.modelAnnotations;
+ }
this.generateApis = source.generateApis != null ? source.generateApis : this.generateApis;
this.packageName = source.packageName != null ? source.packageName : this.packageName;
this.apiPackageName = source.apiPackageName != null ? source.apiPackageName : this.apiPackageName;
@@ -76,7 +88,6 @@ public void combine(MappingConfig source) {
this.modelValidationAnnotation = source.modelValidationAnnotation != null ? source.modelValidationAnnotation : this.modelValidationAnnotation;
this.generateEqualsAndHashCode = source.generateEqualsAndHashCode != null ? source.generateEqualsAndHashCode : this.generateEqualsAndHashCode;
this.generateToString = source.generateToString != null ? source.generateToString : this.generateToString;
-
}
}
}
diff --git a/src/main/resources/templates/javaClassGraphqlType.ftl b/src/main/resources/templates/javaClassGraphqlType.ftl
index 3ec9dfc67..769edbf17 100644
--- a/src/main/resources/templates/javaClassGraphqlType.ftl
+++ b/src/main/resources/templates/javaClassGraphqlType.ftl
@@ -6,6 +6,9 @@ package ${package};
import ${import}.*;
#list>
+<#list annotations as annotation>
+@${annotation}
+#list>
public class ${className} <#if implements?has_content>implements <#list implements as interface>${interface}<#if interface_has_next>, #if>#list>#if>{
<#list fields as field>
diff --git a/src/test/java/com/kobylynskyi/graphql/codegen/GraphqlCodegenTest.java b/src/test/java/com/kobylynskyi/graphql/codegen/GraphqlCodegenTest.java
index 8d2b74fa0..0f278f017 100644
--- a/src/test/java/com/kobylynskyi/graphql/codegen/GraphqlCodegenTest.java
+++ b/src/test/java/com/kobylynskyi/graphql/codegen/GraphqlCodegenTest.java
@@ -143,6 +143,19 @@ void generate_CustomAnnotationMappings() throws Exception {
System.lineSeparator() + " private org.joda.time.DateTime createdDateTime;"));
}
+ @Test
+ void generate_ModelAnnotations() throws Exception {
+ mappingConfig.setModelAnnotations(new HashSet<>(Arrays.asList("lombok.Builder", "lombok.Builder", "lombok.Data")));
+
+ generator.generate();
+
+ File eventFile = Arrays.stream(Objects.requireNonNull(outputJavaClassesDir.listFiles()))
+ .filter(file -> file.getName().equalsIgnoreCase("Event.java"))
+ .findFirst().orElseThrow(FileNotFoundException::new);
+ assertEquals(Utils.getFileContent(new File("src/test/resources/expected-classes/Event_with_lombok_annotations.java.txt").getPath()),
+ Utils.getFileContent(eventFile.getPath()));
+ }
+
@Test
void generate_CustomAnnotationMappings_FieldType() throws Exception {
mappingConfig.setCustomTypesMapping(new HashMap<>(Collections.singletonMap(
diff --git a/src/test/resources/expected-classes/Event_with_lombok_annotations.java.txt b/src/test/resources/expected-classes/Event_with_lombok_annotations.java.txt
new file mode 100644
index 000000000..7b0502e46
--- /dev/null
+++ b/src/test/resources/expected-classes/Event_with_lombok_annotations.java.txt
@@ -0,0 +1,88 @@
+package com.kobylynskyi.graphql.test1;
+
+import java.util.*;
+
+@lombok.Builder
+@lombok.Data
+public class Event {
+
+ private String id;
+ private String categoryId;
+ private Collection properties;
+ private EventStatus status;
+ private String createdBy;
+ private String createdDateTime;
+ private Boolean active;
+ private Integer rating;
+
+ public Event() {
+ }
+
+ public Event(String id, String categoryId, Collection properties, EventStatus status, String createdBy, String createdDateTime, Boolean active, Integer rating) {
+ this.id = id;
+ this.categoryId = categoryId;
+ this.properties = properties;
+ this.status = status;
+ this.createdBy = createdBy;
+ this.createdDateTime = createdDateTime;
+ this.active = active;
+ this.rating = rating;
+ }
+
+ public String getId() {
+ return id;
+ }
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getCategoryId() {
+ return categoryId;
+ }
+ public void setCategoryId(String categoryId) {
+ this.categoryId = categoryId;
+ }
+
+ public Collection getProperties() {
+ return properties;
+ }
+ public void setProperties(Collection properties) {
+ this.properties = properties;
+ }
+
+ public EventStatus getStatus() {
+ return status;
+ }
+ public void setStatus(EventStatus status) {
+ this.status = status;
+ }
+
+ public String getCreatedBy() {
+ return createdBy;
+ }
+ public void setCreatedBy(String createdBy) {
+ this.createdBy = createdBy;
+ }
+
+ public String getCreatedDateTime() {
+ return createdDateTime;
+ }
+ public void setCreatedDateTime(String createdDateTime) {
+ this.createdDateTime = createdDateTime;
+ }
+
+ public Boolean getActive() {
+ return active;
+ }
+ public void setActive(Boolean active) {
+ this.active = active;
+ }
+
+ public Integer getRating() {
+ return rating;
+ }
+ public void setRating(Integer rating) {
+ this.rating = rating;
+ }
+
+}
\ No newline at end of file