diff --git a/src/main/java/io/vertx/codegen/type/EnumTypeInfo.java b/src/main/java/io/vertx/codegen/type/EnumTypeInfo.java index 816d3fec3..be1b91b99 100644 --- a/src/main/java/io/vertx/codegen/type/EnumTypeInfo.java +++ b/src/main/java/io/vertx/codegen/type/EnumTypeInfo.java @@ -13,8 +13,9 @@ public class EnumTypeInfo extends ClassTypeInfo { final List values; final boolean gen; - public EnumTypeInfo(String fqcn, boolean gen, List values, ModuleInfo module, boolean nullable) { - super(ClassKind.ENUM, fqcn, module, nullable, Collections.emptyList(), null); + public EnumTypeInfo(String fqcn, boolean gen, List values, + ModuleInfo module, boolean nullable, DataObjectInfo dataObject) { + super(ClassKind.ENUM, fqcn, module, nullable, Collections.emptyList(), dataObject); this.gen = gen; this.values = values; diff --git a/src/main/java/io/vertx/codegen/type/TypeMirrorFactory.java b/src/main/java/io/vertx/codegen/type/TypeMirrorFactory.java index c54ac451a..4eb7cd942 100644 --- a/src/main/java/io/vertx/codegen/type/TypeMirrorFactory.java +++ b/src/main/java/io/vertx/codegen/type/TypeMirrorFactory.java @@ -10,7 +10,6 @@ import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -25,7 +24,6 @@ public class TypeMirrorFactory { private static final ModuleInfo VERTX_CORE_MOD = new ModuleInfo("io.vertx.core", "vertx", "io.vertx"); private static final ClassTypeInfo JSON_OBJECT = new ClassTypeInfo(ClassKind.JSON_OBJECT, "io.vertx.core.json.JsonObject", VERTX_CORE_MOD, false, Collections.emptyList(), null); - private static final ClassTypeInfo JSON_ARRAY = new ClassTypeInfo(ClassKind.JSON_ARRAY, "io.vertx.core.json.JsonArray", VERTX_CORE_MOD, false, Collections.emptyList(), null); private static final ClassTypeInfo STRING = new ClassTypeInfo(ClassKind.STRING, "java.lang.String", null, false, Collections.emptyList(), null); final Elements elementUtils; @@ -100,7 +98,6 @@ public TypeInfo create(TypeUse use, DeclaredType type, boolean checkTypeArgs) { PackageElement pkgElt = elementUtils.getPackageOf(elt); ModuleInfo module = ModuleInfo.resolve(elementUtils, pkgElt); String fqcn = elt.getQualifiedName().toString(); - String simpleName = elt.getSimpleName().toString(); boolean proxyGen = elt.getAnnotation(ProxyGen.class) != null; if (elt.getKind() == ElementKind.ENUM) { ArrayList values = new ArrayList<>(); @@ -110,7 +107,13 @@ public TypeInfo create(TypeUse use, DeclaredType type, boolean checkTypeArgs) { } } boolean gen = elt.getAnnotation(VertxGen.class) != null; - return new EnumTypeInfo(fqcn, gen, values, module, nullable); + MapperInfo serializer = serializers.get(type.toString()); + MapperInfo deserializer = deserializers.get(type.toString()); + DataObjectInfo dataObject = null; + if (serializer != null || deserializer != null) { + dataObject = new DataObjectInfo(false, serializer, deserializer); + } + return new EnumTypeInfo(fqcn, gen, values, module, nullable, dataObject); } else { ClassKind kind = ClassKind.getKind(fqcn, elt.getAnnotation(VertxGen.class) != null); List typeArgs = type.getTypeArguments(); diff --git a/src/main/java/io/vertx/codegen/type/TypeReflectionFactory.java b/src/main/java/io/vertx/codegen/type/TypeReflectionFactory.java index d69559140..a08733210 100644 --- a/src/main/java/io/vertx/codegen/type/TypeReflectionFactory.java +++ b/src/main/java/io/vertx/codegen/type/TypeReflectionFactory.java @@ -61,7 +61,8 @@ public static TypeInfo create(Type type) { classType.getDeclaredAnnotation(VertxGen.class) != null, Stream.of(classType.getEnumConstants()).map(Object::toString).collect(Collectors.toList()), module, - false + false, + null ); } else { ClassKind kind = ClassKind.getKind(fqcn, classType.getAnnotation(VertxGen.class) != null); diff --git a/src/tck/java/io/vertx/codegen/testmodel/JsonMapperTCK.java b/src/tck/java/io/vertx/codegen/testmodel/JsonMapperTCK.java index 7198bf30b..02109daff 100644 --- a/src/tck/java/io/vertx/codegen/testmodel/JsonMapperTCK.java +++ b/src/tck/java/io/vertx/codegen/testmodel/JsonMapperTCK.java @@ -36,6 +36,7 @@ static MyPojoToJsonObject deserializeMyPojoToJsonObject(JsonObject value) { return new MyPojoToJsonObject(value.getInteger("v")); } + @SuppressWarnings({ "unchecked", "rawtypes" }) @GenIgnore static JsonArray serializeMyPojoToJsonArray(MyPojoToJsonArray value) { return new JsonArray((List)value.stuff); @@ -56,6 +57,16 @@ static ZonedDateTime deserializeZonedDateTime(String value) { return ZonedDateTime.parse(value); } + @GenIgnore + static String serializeCustomEnum(TestCustomEnum value) { + return (value != null) ? value.getShortName() : null; + } + + @GenIgnore + static TestCustomEnum deserializeCustomEnum(String value) { + return (value != null) ? TestCustomEnum.of(value) : null; + } + // Java Type <-> Integer void methodWithTypeToIntegerParam(MyPojoToInteger myPojoToInteger); @@ -144,4 +155,26 @@ static ZonedDateTime deserializeZonedDateTime(String value) { void methodWithHandlerAsyncResultSetOfTypeToJsonObjectParam(Handler>> myPojoToJsonObjectSetHandler); void methodWithHandlerAsyncResultMapOfTypeToJsonObjectParam(Handler>> myPojoToJsonObjectMapHandler); + // CustomEnum <-> String + + void methodWithCustomEnumToStringParam(TestCustomEnum customEnum); + void methodWithListOfCustomEnumToStringParam(List customEnumList); + void methodWithSetOfCustomEnumToStringParam(Set customEnumSet); + void methodWithMapOfCustomEnumToStringParam(Map customEnumMap); + + TestCustomEnum methodWithCustomEnumToStringReturn(); + List methodWithListOfCustomEnumToStringReturn(); + Set methodWithSetOfCustomEnumToStringReturn(); + Map methodWithMapOfCustomEnumToStringReturn(); + + void methodWithHandlerCustomEnumToStringParam(Handler customEnumHandler); + void methodWithHandlerListOfCustomEnumToStringParam(Handler> customEnumListHandler); + void methodWithHandlerSetOfCustomEnumToStringParam(Handler> customEnumSetHandler); + void methodWithHandlerMapOfCustomEnumToStringParam(Handler> customEnumMapHandler); + + void methodWithHandlerAsyncResultCustomEnumToStringParam(Handler> customEnumHandler); + void methodWithHandlerAsyncResultListOfCustomEnumToStringParam(Handler>> customEnumListHandler); + void methodWithHandlerAsyncResultSetOfCustomEnumToStringParam(Handler>> customEnumSetHandler); + void methodWithHandlerAsyncResultMapOfCustomEnumToStringParam(Handler>> customEnumMapHandler); + } diff --git a/src/tck/java/io/vertx/codegen/testmodel/JsonMapperTCKImpl.java b/src/tck/java/io/vertx/codegen/testmodel/JsonMapperTCKImpl.java index 73278bb93..d190f5a36 100644 --- a/src/tck/java/io/vertx/codegen/testmodel/JsonMapperTCKImpl.java +++ b/src/tck/java/io/vertx/codegen/testmodel/JsonMapperTCKImpl.java @@ -366,4 +366,101 @@ public void methodWithHandlerAsyncResultSetOfTypeToJsonObjectParam(Handler>> myPojoToJsonObjectMapHandler) { myPojoToJsonObjectMapHandler.handle(Future.succeededFuture(methodWithMapOfTypeToJsonObjectReturn())); } + + @Override + public void methodWithCustomEnumToStringParam(TestCustomEnum customEnum) { + assertEquals(TestCustomEnum.of("development"), customEnum); + } + + @Override + public void methodWithListOfCustomEnumToStringParam(List customEnumList) { + assertEquals(2, customEnumList.size()); + assertEquals(TestCustomEnum.of("development"), customEnumList.get(0)); + assertEquals(TestCustomEnum.of("integration-test"), customEnumList.get(1)); + + } + + @Override + public void methodWithSetOfCustomEnumToStringParam(Set customEnumSet) { + assertEquals(2, customEnumSet.size()); + assertTrue(customEnumSet.contains(TestCustomEnum.of("development"))); + assertTrue(customEnumSet.contains(TestCustomEnum.of("integration-test"))); + + } + + @Override + public void methodWithMapOfCustomEnumToStringParam(Map customEnumMap) { + assertEquals(2, customEnumMap.size()); + assertEquals(TestCustomEnum.of("development"), customEnumMap.get("dev")); + assertEquals(TestCustomEnum.of("integration-test"), customEnumMap.get("itest")); + } + + @Override + public TestCustomEnum methodWithCustomEnumToStringReturn() { + return TestCustomEnum.of("development"); + } + + @Override + public List methodWithListOfCustomEnumToStringReturn() { + return Arrays.asList(TestCustomEnum.of("development"), TestCustomEnum.of("integration-test")); + } + + @Override + public Set methodWithSetOfCustomEnumToStringReturn() { + return new HashSet<>(methodWithListOfCustomEnumToStringReturn()); + } + + @Override + public Map methodWithMapOfCustomEnumToStringReturn() { + Map map = new HashMap<>(); + map.put("dev", TestCustomEnum.DEV); + map.put("itest", TestCustomEnum.ITEST); + return map; + } + + @Override + public void methodWithHandlerCustomEnumToStringParam(Handler customEnumHandler) { + customEnumHandler.handle(methodWithCustomEnumToStringReturn()); + } + + @Override + public void methodWithHandlerListOfCustomEnumToStringParam(Handler> customEnumListHandler) { + customEnumListHandler.handle(methodWithListOfCustomEnumToStringReturn()); + } + + @Override + public void methodWithHandlerSetOfCustomEnumToStringParam(Handler> customEnumSetHandler) { + customEnumSetHandler.handle(methodWithSetOfCustomEnumToStringReturn()); + } + + @Override + public void methodWithHandlerMapOfCustomEnumToStringParam( + Handler> customEnumMapHandler) { + customEnumMapHandler.handle(methodWithMapOfCustomEnumToStringReturn()); + } + + @Override + public void methodWithHandlerAsyncResultCustomEnumToStringParam( + Handler> customEnumHandler) { + customEnumHandler.handle(Future.succeededFuture(methodWithCustomEnumToStringReturn())); + } + + @Override + public void methodWithHandlerAsyncResultListOfCustomEnumToStringParam( + Handler>> customEnumListHandler) { + customEnumListHandler.handle(Future.succeededFuture(methodWithListOfCustomEnumToStringReturn())); + } + + @Override + public void methodWithHandlerAsyncResultSetOfCustomEnumToStringParam( + Handler>> customEnumSetHandler) { + customEnumSetHandler.handle(Future.succeededFuture(methodWithSetOfCustomEnumToStringReturn())); + } + + @Override + public void methodWithHandlerAsyncResultMapOfCustomEnumToStringParam( + Handler>> customEnumMapHandler) { + customEnumMapHandler.handle(Future.succeededFuture(methodWithMapOfCustomEnumToStringReturn())); + } + } diff --git a/src/tck/java/io/vertx/codegen/testmodel/TestCustomEnum.java b/src/tck/java/io/vertx/codegen/testmodel/TestCustomEnum.java new file mode 100644 index 000000000..892f771c7 --- /dev/null +++ b/src/tck/java/io/vertx/codegen/testmodel/TestCustomEnum.java @@ -0,0 +1,34 @@ +package io.vertx.codegen.testmodel; + +public enum TestCustomEnum { + + DEV("dev", "development"), + + ITEST("itest", "integration-test"); + + public static TestCustomEnum of(String pName) { + for (TestCustomEnum item : TestCustomEnum.values()) { + if (item.names[0].equalsIgnoreCase(pName) || item.names[1].equalsIgnoreCase(pName) + || pName.equalsIgnoreCase(item.name())) { + return item; + } + } + return DEV; + } + + private String[] names = new String[2]; + + TestCustomEnum(String pShortName, String pLongName) { + names[0] = pShortName; + names[1] = pLongName; + } + + public String getLongName() { + return names[1]; + } + + public String getShortName() { + return names[0]; + } + +} diff --git a/src/tck/resources/META-INF/vertx/json-mappers.properties b/src/tck/resources/META-INF/vertx/json-mappers.properties index 56d6979a4..a2c58db66 100644 --- a/src/tck/resources/META-INF/vertx/json-mappers.properties +++ b/src/tck/resources/META-INF/vertx/json-mappers.properties @@ -6,3 +6,5 @@ io.vertx.codegen.testmodel.MyPojoToJsonArray.serializer=io.vertx.codegen.testmod io.vertx.codegen.testmodel.MyPojoToJsonArray.deserializer=io.vertx.codegen.testmodel.JsonMapperTCK#deserializeMyPojoToJsonArray java.time.ZonedDateTime.serializer=io.vertx.codegen.testmodel.JsonMapperTCK#serializeZonedDateTime java.time.ZonedDateTime.deserializer=io.vertx.codegen.testmodel.JsonMapperTCK#deserializeZonedDateTime +io.vertx.codegen.testmodel.TestCustomEnum.serializer=io.vertx.codegen.testmodel.JsonMapperTCK#serializeCustomEnum +io.vertx.codegen.testmodel.TestCustomEnum.deserializer=io.vertx.codegen.testmodel.JsonMapperTCK#deserializeCustomEnum diff --git a/src/test/java/io/vertx/test/codegen/DataObjectTest.java b/src/test/java/io/vertx/test/codegen/DataObjectTest.java index bafc45061..8acd3f2ea 100644 --- a/src/test/java/io/vertx/test/codegen/DataObjectTest.java +++ b/src/test/java/io/vertx/test/codegen/DataObjectTest.java @@ -15,7 +15,10 @@ import io.vertx.test.codegen.testdataobject.*; import io.vertx.test.codegen.testdataobject.imported.Imported; import io.vertx.test.codegen.testdataobject.jsonmapper.DataObjectWithPojoWithMapper; +import io.vertx.test.codegen.testdataobject.jsonmapper.MyEnumWithCustomFactory; import io.vertx.test.codegen.testdataobject.jsonmapper.MyPojo; +import io.vertx.test.codegen.testdataobject.jsonmapper.DataObjectWithMappedEnum; + import org.junit.Test; import java.time.Instant; @@ -892,6 +895,23 @@ public void testDataObjectWithJsonMapper() throws Exception { assertTrue(myPojoProperty.getType().getDataObject().isSerializable()); } + @Test + public void testCustomEnumWithJsonMapper() throws Exception { + DataObjectModel model = new GeneratorHelper() + .registerConverter(MyEnumWithCustomFactory.class, DataObjectWithMappedEnum.class.getName(), "serializeMyEnumWithCustomFactory") + .registerConverter(MyEnumWithCustomFactory.class, DataObjectWithMappedEnum.class.getName(), "deserializeMyEnumWithCustomFactory") + .generateDataObject(DataObjectWithMappedEnum.class); + assertNotNull(model); + assertTrue(model.isClass()); + assertTrue(model.getGenerateConverter()); + assertTrue(model.isPublicConverter()); + + PropertyInfo myPojoProperty = model.getPropertyMap().get("customEnum"); + assertEquals(ClassKind.ENUM, myPojoProperty.getType().getKind()); + assertTrue(myPojoProperty.getType().getDataObject().isDeserializable()); + assertTrue(myPojoProperty.getType().getDataObject().isSerializable()); + } + private void assertInvalidDataObject(Class dataObjectClass) throws Exception { try { new GeneratorHelper().generateDataObject(dataObjectClass); diff --git a/src/test/java/io/vertx/test/codegen/EnumTest.java b/src/test/java/io/vertx/test/codegen/EnumTest.java index 63add4158..553dab6c8 100644 --- a/src/test/java/io/vertx/test/codegen/EnumTest.java +++ b/src/test/java/io/vertx/test/codegen/EnumTest.java @@ -1,8 +1,12 @@ package io.vertx.test.codegen; import io.vertx.codegen.*; +import io.vertx.codegen.annotations.VertxGen; +import io.vertx.codegen.type.ClassKind; import io.vertx.codegen.type.EnumTypeInfo; import io.vertx.codegen.type.TypeInfo; +import io.vertx.test.codegen.testapi.jsonmapper.MyEnumWithCustomFactory; +import io.vertx.test.codegen.testapi.jsonmapper.WithMyCustomEnumWithMapper; import io.vertx.test.codegen.testenum.EnumAsParam; import io.vertx.test.codegen.testenum.InvalidEmptyEnum; import io.vertx.test.codegen.testenum.ValidEnum; @@ -16,7 +20,7 @@ /** * @author Julien Viet */ -public class EnumTest { +public class EnumTest extends ClassTestBase { @Test public void testEnum() throws Exception { @@ -34,6 +38,29 @@ public void testEnum() throws Exception { assertTrue(model.getType().isGen()); } + @Test + public void testJsonMapper() throws Exception { + ClassModel model = new GeneratorHelper() + .registerConverter(MyEnumWithCustomFactory.class, WithMyCustomEnumWithMapper.class.getName(), "serializeMyEnumWithCustomFactory") + .registerConverter(MyEnumWithCustomFactory.class, WithMyCustomEnumWithMapper.class.getName(), "deserializeMyEnumWithCustomFactory") + .generateClass(WithMyCustomEnumWithMapper.class); + assertFalse(model.getAnnotations().isEmpty()); + assertEquals(1, model.getAnnotations().size()); + assertEquals(VertxGen.class.getName(), model.getAnnotations().get(0).getName()); + + assertEquals(1, model.getReferencedDataObjectTypes().size()); + assertEquals("MyEnumWithCustomFactory", model.getReferencedDataObjectTypes().iterator().next().getSimpleName()); + + checkMethod(model.getMethodMap().get("returnMyEnumWithCustomFactory").get(0), + "returnMyEnumWithCustomFactory", 0, new TypeLiteral() {}, MethodKind.OTHER); + + MethodInfo myPojoParam = model.getMethodMap().get("setMyEnumWithCustomFactory").get(0); + checkMethod(myPojoParam, "setMyEnumWithCustomFactory", 1, "void", MethodKind.OTHER); + checkParam(myPojoParam.getParam(0), "myEnum", MyEnumWithCustomFactory.class.getName(), ClassKind.ENUM); + + + } + @Test public void testInvalidEmptyEnum() throws Exception { try { diff --git a/src/test/java/io/vertx/test/codegen/testapi/jsonmapper/MyEnumWithCustomFactory.java b/src/test/java/io/vertx/test/codegen/testapi/jsonmapper/MyEnumWithCustomFactory.java new file mode 100644 index 000000000..96d2b454d --- /dev/null +++ b/src/test/java/io/vertx/test/codegen/testapi/jsonmapper/MyEnumWithCustomFactory.java @@ -0,0 +1,40 @@ +package io.vertx.test.codegen.testapi.jsonmapper; + +import io.vertx.codegen.annotations.VertxGen; + +/**MyEnumWithCustomFactory doc*/ +@VertxGen +public enum MyEnumWithCustomFactory { + + /**DEV doc*/ + DEV("dev", "development"), + + /**ITEST doc*/ + ITEST("itest", "integration-test"); + + public static MyEnumWithCustomFactory of(String pName) { + for (MyEnumWithCustomFactory item : MyEnumWithCustomFactory.values()) { + if (item.names[0].equalsIgnoreCase(pName) || item.names[1].equalsIgnoreCase(pName) + || pName.equalsIgnoreCase(item.name())) { + return item; + } + } + return DEV; + } + + private String[] names = new String[2]; + + MyEnumWithCustomFactory(String pShortName, String pLongName) { + names[0] = pShortName; + names[1] = pLongName; + } + + public String getLongName() { + return names[1]; + } + + public String getShortName() { + return names[0]; + } + +} diff --git a/src/test/java/io/vertx/test/codegen/testapi/jsonmapper/WithMyCustomEnumWithMapper.java b/src/test/java/io/vertx/test/codegen/testapi/jsonmapper/WithMyCustomEnumWithMapper.java new file mode 100644 index 000000000..3a1dcf877 --- /dev/null +++ b/src/test/java/io/vertx/test/codegen/testapi/jsonmapper/WithMyCustomEnumWithMapper.java @@ -0,0 +1,21 @@ +package io.vertx.test.codegen.testapi.jsonmapper; + +import io.vertx.codegen.annotations.GenIgnore; +import io.vertx.codegen.annotations.VertxGen; + +@VertxGen +public interface WithMyCustomEnumWithMapper { + + @GenIgnore + public static MyEnumWithCustomFactory deserializeMyEnumWithCustomFactory(String value) { + return (value != null) ? MyEnumWithCustomFactory.of(value) : null; + } + + @GenIgnore + public static String serializeMyEnumWithCustomFactory(MyEnumWithCustomFactory value) { + return (value != null) ? value.getLongName() : null; + } + + MyEnumWithCustomFactory returnMyEnumWithCustomFactory(); + void setMyEnumWithCustomFactory(MyEnumWithCustomFactory myEnum); +} diff --git a/src/test/java/io/vertx/test/codegen/testdataobject/jsonmapper/DataObjectWithMappedEnum.java b/src/test/java/io/vertx/test/codegen/testdataobject/jsonmapper/DataObjectWithMappedEnum.java new file mode 100644 index 000000000..201dfaf24 --- /dev/null +++ b/src/test/java/io/vertx/test/codegen/testdataobject/jsonmapper/DataObjectWithMappedEnum.java @@ -0,0 +1,44 @@ +package io.vertx.test.codegen.testdataobject.jsonmapper; + +import io.vertx.codegen.annotations.DataObject; +import io.vertx.codegen.annotations.GenIgnore; +import io.vertx.core.json.JsonObject; + +@DataObject(generateConverter = true, publicConverter = true) +public class DataObjectWithMappedEnum { + + @GenIgnore + public static MyEnumWithCustomFactory deserializeMyEnumWithCustomFactory(String value) { + return (value != null) ? MyEnumWithCustomFactory.of(value) : null; + } + + @GenIgnore + public static String serializeMyEnumWithCustomFactory(MyEnumWithCustomFactory value) { + return (value != null) ? value.getLongName() : null; + } + + MyEnumWithCustomFactory customEnum; + + public DataObjectWithMappedEnum(JsonObject customEnum) { + + } + + public DataObjectWithMappedEnum(MyEnumWithCustomFactory customEnum) { + super(); + this.customEnum = customEnum; + } + + public MyEnumWithCustomFactory getCustomEnum() { + return customEnum; + } + + public DataObjectWithMappedEnum setCustomEnum(MyEnumWithCustomFactory a) { + this.customEnum = a; + return this; + } + + public JsonObject toJson() { + return null; + } + +} diff --git a/src/test/java/io/vertx/test/codegen/testdataobject/jsonmapper/MyEnumWithCustomFactory.java b/src/test/java/io/vertx/test/codegen/testdataobject/jsonmapper/MyEnumWithCustomFactory.java new file mode 100644 index 000000000..214f19dd6 --- /dev/null +++ b/src/test/java/io/vertx/test/codegen/testdataobject/jsonmapper/MyEnumWithCustomFactory.java @@ -0,0 +1,31 @@ +package io.vertx.test.codegen.testdataobject.jsonmapper; + +public enum MyEnumWithCustomFactory { + DEV("dev", "development"), ITEST("itest", "integration-test"); + + public static MyEnumWithCustomFactory of(String pName) { + for (MyEnumWithCustomFactory item : MyEnumWithCustomFactory.values()) { + if (item.names[0].equalsIgnoreCase(pName) || item.names[1].equalsIgnoreCase(pName) + || pName.equalsIgnoreCase(item.name())) { + return item; + } + } + return DEV; + } + + private String[] names = new String[2]; + + MyEnumWithCustomFactory(String pShortName, String pLongName) { + names[0] = pShortName; + names[1] = pLongName; + } + + public String getLongName() { + return names[1]; + } + + public String getShortName() { + return names[0]; + } + +}