diff --git a/CHANGELOG.md b/CHANGELOG.md index b2f8ea0..751b99d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Changed +- Added integer enum support. +- Upgraded common bom to version 1.28.0 +- Upgraded utilities to version 1.15.0 +- Upgraded generator maven plugin to version 2.6.1 +- Upgraded json schema catalog to version 1.4.0 + ## [1.4.2] - 2018-07-11 ### Changed - Upgraded framework api to version 2.2.0 diff --git a/integration-test/src/test/java/uk/gov/justice/generation/pojo/integration/examples/EnumsIT.java b/integration-test/src/test/java/uk/gov/justice/generation/pojo/integration/examples/EnumsIT.java index f8580c8..de31194 100644 --- a/integration-test/src/test/java/uk/gov/justice/generation/pojo/integration/examples/EnumsIT.java +++ b/integration-test/src/test/java/uk/gov/justice/generation/pojo/integration/examples/EnumsIT.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; public class EnumsIT { @@ -28,29 +29,72 @@ public class EnumsIT { private final GeneratorUtil generatorUtil = new GeneratorUtil(); private final ClassInstantiator classInstantiator = new ClassInstantiator(); - private final OutputDirectories outputDirectories = new OutputDirectories(); - - private static final File JSON_SCHEMA_FILE = new ClasspathFileResource().getFileFromClasspath("/schemas/examples/enum.json"); + private OutputDirectories outputDirectories; + private static final File JSON_SCHEMA_STRING_FILE = new ClasspathFileResource().getFileFromClasspath("/schemas/examples/enum-string.json"); + private static final File JSON_SCHEMA_INTEGER_FILE = new ClasspathFileResource().getFileFromClasspath("/schemas/examples/enum-integer.json"); @Before public void setup() throws Exception { + outputDirectories = new OutputDirectories(); outputDirectories.makeDirectories("./target/test-generation/examples/enums"); } @SuppressWarnings("unchecked") @Test - public void shouldGenerateJavaClassSourceCode() throws Exception { + public void shouldGenerateJavaClassWithIntegerEnum() throws Exception { final String packageName = "uk.gov.justice.pojo.enums"; final PojoGeneratorProperties generatorProperties = pojoGeneratorPropertiesBuilder() - .withRootClassName("PersonWithEnum") + .withRootClassName("PersonWithIntegerEnum") .build(); final List> classes = generatorUtil .withGeneratorProperties(generatorProperties) .generateAndCompileJavaSource( - JSON_SCHEMA_FILE, + JSON_SCHEMA_INTEGER_FILE, + packageName, + outputDirectories); + + final Class personWithEnumClass = classes.get(1); + final Class enumClass = (Class) classes.get(0); + + final Optional valueForMethod = ReflectionUtil.methodOf(enumClass, "valueFor"); + assertThat(valueForMethod.isPresent(), is(true)); + + final Optional favouriteNumber = (Optional) valueForMethod.get().invoke(null, 42); + assertThat(favouriteNumber.isPresent(), is(true)); + + final String name = "Fred"; + final Integer age = 21; + final Object personWithEnum = classInstantiator.newInstance(personWithEnumClass, age, favouriteNumber.get(), name); + + final String studentJson = objectMapper.writeValueAsString(personWithEnum); + + with(studentJson) + .assertThat("$.name", is(name)) + .assertThat("$.age", is(age)) + .assertThat("$.favouriteNumber", is(42)) + ; + + generatorUtil.validate(JSON_SCHEMA_INTEGER_FILE, studentJson); + } + + + @SuppressWarnings("unchecked") + @Test + public void shouldGenerateJavaClassWithStringEnum() throws Exception { + + final String packageName = "uk.gov.justice.pojo.enums"; + + final PojoGeneratorProperties generatorProperties = pojoGeneratorPropertiesBuilder() + .withRootClassName("PersonWithStringEnum") + .build(); + + final List> classes = generatorUtil + .withGeneratorProperties(generatorProperties) + .generateAndCompileJavaSource( + JSON_SCHEMA_STRING_FILE, packageName, outputDirectories); @@ -72,9 +116,9 @@ public void shouldGenerateJavaClassSourceCode() throws Exception { with(studentJson) .assertThat("$.name", is(name)) .assertThat("$.age", is(age)) - .assertThat("$.favouriteColour", is("Red")) - ; + .assertThat("$.favouriteColour", is("Red")); - generatorUtil.validate(JSON_SCHEMA_FILE, studentJson); + generatorUtil.validate(JSON_SCHEMA_STRING_FILE, studentJson); } + } diff --git a/integration-test/src/test/resources/schemas/examples/enum-integer.json b/integration-test/src/test/resources/schemas/examples/enum-integer.json new file mode 100644 index 0000000..c0efe55 --- /dev/null +++ b/integration-test/src/test/resources/schemas/examples/enum-integer.json @@ -0,0 +1,26 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "id": "http://justice.gov.uk/events/pojo/enums/person-with-integer-enum.json", + "properties": { + "name": { + "type": "string" + }, + "age": { + "type": "integer" + }, + "favouriteNumber": { + "type": "integer", + "enum": [ + 21, + 42 + ] + } + }, + "additionalProperties": false, + "required": [ + "name", + "age", + "favouriteNumber" + ] + } diff --git a/integration-test/src/test/resources/schemas/examples/enum.json b/integration-test/src/test/resources/schemas/examples/enum-string.json similarity index 83% rename from integration-test/src/test/resources/schemas/examples/enum.json rename to integration-test/src/test/resources/schemas/examples/enum-string.json index 4285122..db06ef3 100644 --- a/integration-test/src/test/resources/schemas/examples/enum.json +++ b/integration-test/src/test/resources/schemas/examples/enum-string.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", - "id": "http://justice.gov.uk/events/pojo/enums/person-with-enum.json", + "id": "http://justice.gov.uk/events/pojo/enums/person-with-string-enum.json", "properties": { "name": { "type": "string" diff --git a/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/dom/EnumDefinition.java b/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/dom/EnumDefinition.java index 3bfabe6..6520914 100644 --- a/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/dom/EnumDefinition.java +++ b/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/dom/EnumDefinition.java @@ -43,9 +43,9 @@ */ public class EnumDefinition extends ClassDefinition { - private final List enumValues; + private final List enumValues; - public EnumDefinition(final String fieldName, final List enumValues, final String id) { + public EnumDefinition(final String fieldName, final List enumValues, final String id) { super(ENUM, fieldName, id); this.enumValues = enumValues; } @@ -55,7 +55,7 @@ public EnumDefinition(final String fieldName, final List enumValues, fin * * @return The list of enumerated values */ - public List getEnumValues() { + public List getEnumValues() { return enumValues; } } diff --git a/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/generators/EnumGenerator.java b/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/generators/EnumGenerator.java index b956302..72e4b52 100644 --- a/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/generators/EnumGenerator.java +++ b/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/generators/EnumGenerator.java @@ -15,6 +15,7 @@ import java.util.Optional; import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; @@ -30,11 +31,14 @@ public class EnumGenerator implements ClassGeneratable { private static final String BLANK_ENUM_NAME = "BLANK"; private static final String SPACE = " "; private static final String UNDERSCORE = "_"; + private static final String NUMBER = "NUMBER"; private final EnumDefinition enumDefinition; private final ClassNameFactory classNameFactory; private final PluginContext pluginContext; + private boolean isNumericEnum; + public EnumGenerator(final EnumDefinition definition, final ClassNameFactory classNameFactory, final PluginContext pluginContext) { @@ -49,16 +53,19 @@ public TypeSpec generate() { final Builder enumBuilder = enumBuilder(getClassName()).addModifiers(PUBLIC); enumDefinition.getEnumValues().forEach(enumValue -> { + + isNumericEnum = enumValue instanceof Integer; + final String enumName = constructEnumNameFrom(enumValue); - enumBuilder.addEnumConstant(enumName, anonymousClassBuilder("$S", enumValue) + enumBuilder.addEnumConstant(enumName, anonymousClassBuilder(isNumericEnum ? "$L" : "$S", enumValue) .build()); }); return enumBuilder - .addField(String.class, VALUE_VARIABLE_NAME, PRIVATE, FINAL) + .addField(getClassType(), VALUE_VARIABLE_NAME, PRIVATE, FINAL) .addMethod(constructorBuilder() - .addParameter(String.class, VALUE_VARIABLE_NAME) + .addParameter(getClassType(), VALUE_VARIABLE_NAME) .addStatement("this.$L = $L", VALUE_VARIABLE_NAME, VALUE_VARIABLE_NAME) .build()) .addMethod(buildToStringMethod()) @@ -71,7 +78,7 @@ private MethodSpec buildToStringMethod() { .addAnnotation(Override.class) .addModifiers(PUBLIC) .returns(String.class) - .addStatement("return $L", VALUE_VARIABLE_NAME) + .addCode(addToStringReturnStatement()) .build(); } @@ -82,7 +89,7 @@ private MethodSpec buildValueForMethod() { final MethodSpec.Builder methodBuilder = methodBuilder("valueFor") .addModifiers(PUBLIC, STATIC) - .addParameter(String.class, VALUE_VARIABLE_NAME, FINAL) + .addParameter(getClassType(), VALUE_VARIABLE_NAME, FINAL) .returns(optionalEnumTypeName); enumDefinition.getEnumValues().forEach(enumValue -> { @@ -99,6 +106,17 @@ private MethodSpec buildValueForMethod() { return methodBuilder.build(); } + private CodeBlock addToStringReturnStatement() { + return CodeBlock + .builder() + .addStatement("return $L", isNumericEnum ? generateStringFromNumber() : VALUE_VARIABLE_NAME) + .build(); + } + + private String generateStringFromNumber() { + return "String.valueOf(".concat(VALUE_VARIABLE_NAME).concat(")"); + } + @Override public String getSimpleClassName() { return getClassName().simpleName(); @@ -109,11 +127,19 @@ public String getPackageName() { return getClassName().packageName(); } - private String constructEnumNameFrom(final String enumValue) { - return enumValue.isEmpty() ? BLANK_ENUM_NAME : enumValue.toUpperCase().replace(SPACE, UNDERSCORE); + + private String constructEnumNameFrom(final Object enumValue) { + if (isNumericEnum) { + return NUMBER.concat(UNDERSCORE).concat(enumValue.toString()); + } + return enumValue.toString().isEmpty() ? BLANK_ENUM_NAME : enumValue.toString().toUpperCase().replace(SPACE, UNDERSCORE); } private ClassName getClassName() { return classNameFactory.createClassNameFrom(enumDefinition); } + + private Class getClassType() { + return isNumericEnum ? Integer.class : String.class; + } } diff --git a/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/visitor/DefaultDefinitionFactory.java b/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/visitor/DefaultDefinitionFactory.java index 13b5b55..deb26d4 100644 --- a/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/visitor/DefaultDefinitionFactory.java +++ b/pojo-generation-core/src/main/java/uk/gov/justice/generation/pojo/visitor/DefaultDefinitionFactory.java @@ -1,7 +1,7 @@ package uk.gov.justice.generation.pojo.visitor; +import static com.google.common.collect.Lists.newArrayList; import static java.lang.String.format; -import static java.util.stream.Collectors.toList; import static uk.gov.justice.generation.pojo.dom.DefinitionType.ARRAY; import static uk.gov.justice.generation.pojo.dom.DefinitionType.BOOLEAN; import static uk.gov.justice.generation.pojo.dom.DefinitionType.CLASS; @@ -19,7 +19,6 @@ import uk.gov.justice.generation.pojo.dom.StringDefinition; import java.io.StringReader; -import java.util.List; import java.util.Optional; import java.util.Set; @@ -89,9 +88,8 @@ public Definition constructDefinitionFor(final String fieldName, final Schema sc if (schema instanceof EnumSchema) { final Set possibleValues = ((EnumSchema) schema).getPossibleValues(); - final List enumValues = possibleValues.stream().map(Object::toString).collect(toList()); - return new EnumDefinition(fieldName, enumValues, schema.getId()); + return new EnumDefinition(fieldName, newArrayList(possibleValues), schema.getId()); } if (schema instanceof StringSchema) { diff --git a/pojo-generation-core/src/test/java/uk/gov/justice/generation/pojo/dom/EnumDefinitionTest.java b/pojo-generation-core/src/test/java/uk/gov/justice/generation/pojo/dom/EnumDefinitionTest.java index 326b9e2..40ceee1 100644 --- a/pojo-generation-core/src/test/java/uk/gov/justice/generation/pojo/dom/EnumDefinitionTest.java +++ b/pojo-generation-core/src/test/java/uk/gov/justice/generation/pojo/dom/EnumDefinitionTest.java @@ -15,7 +15,7 @@ public class EnumDefinitionTest { @Test public void shouldConstructEnumDefinition() throws Exception { final String fieldName = "fieldName"; - final List enumValues = emptyList(); + final List enumValues = emptyList(); final String id = "id"; final EnumDefinition enumDefinition = new EnumDefinition(fieldName, enumValues, id); diff --git a/pojo-generation-core/src/test/java/uk/gov/justice/generation/pojo/generators/EnumGeneratorTest.java b/pojo-generation-core/src/test/java/uk/gov/justice/generation/pojo/generators/EnumGeneratorTest.java index 6521bab..c2d73dd 100644 --- a/pojo-generation-core/src/test/java/uk/gov/justice/generation/pojo/generators/EnumGeneratorTest.java +++ b/pojo-generation-core/src/test/java/uk/gov/justice/generation/pojo/generators/EnumGeneratorTest.java @@ -57,6 +57,24 @@ public void shouldGenerateTypeSpecForSingleWordEnumValue() { assertThat(typeSpec.methodSpecs.size(), is(3)); } + @Test + public void shouldGenerateTypeSpecForIntegerEnumValue() { + final ClassName className = get(Pojo.class); + + when(enumDefinition.getEnumValues()).thenReturn(singletonList(1)); + when(classNameFactory.createTypeNameFrom(enumDefinition, pluginContext)).thenReturn(className); + when(classNameFactory.createClassNameFrom(enumDefinition)).thenReturn(className); + + final TypeSpec typeSpec = enumGenerator.generate(); + + assertThat(typeSpec.name, is("Pojo")); + assertThat(typeSpec.enumConstants.keySet(), hasItem("NUMBER_1")); + assertThat(typeSpec.modifiers.size(), is(1)); + assertThat(typeSpec.modifiers, hasItem(PUBLIC)); + assertThat(typeSpec.fieldSpecs.size(), is(1)); + assertThat(typeSpec.methodSpecs.size(), is(3)); + } + @Test public void shouldGenerateTypeSpecForMultiWordEnumValue() { final ClassName className = get(Pojo.class); diff --git a/pom.xml b/pom.xml index 9c42fcd..b094632 100644 --- a/pom.xml +++ b/pom.xml @@ -28,12 +28,12 @@ - 1.27.0 + 1.28.0 2.2.0 - 1.13.2 + 1.15.0 1.17.3 - 2.6.0 - 1.3.2 + 2.6.1 + 1.4.0 jsonschema-pojo-generator