You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by rs...@apache.org on 2017/10/31 21:11:40 UTC

johnzon git commit: JOHNZON-77/JOHNZON-142 implemented ObjectConverter support for constructors

Repository: johnzon
Updated Branches:
  refs/heads/master 08905f99e -> 52f0aab8e


JOHNZON-77/JOHNZON-142 implemented ObjectConverter support for constructors


Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo
Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/52f0aab8
Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/52f0aab8
Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/52f0aab8

Branch: refs/heads/master
Commit: 52f0aab8ed32151b34528e1e48304682a4449f34
Parents: 08905f9
Author: Reinhard Sandtner <rs...@apache.org>
Authored: Tue Oct 31 22:08:53 2017 +0100
Committer: Reinhard Sandtner <rs...@apache.org>
Committed: Tue Oct 31 22:09:41 2017 +0100

----------------------------------------------------------------------
 .../apache/johnzon/jsonb/JsonbAccessMode.java   | 66 +++++++++++++++-----
 .../johnzon/mapper/MappingParserImpl.java       |  2 +-
 .../johnzon/mapper/access/AccessMode.java       |  1 +
 .../johnzon/mapper/access/BaseAccessMode.java   | 10 ++-
 .../johnzon/mapper/access/FieldAccessMode.java  |  9 +--
 .../ObjectConverterWithAnnotationTest.java      | 33 ++++++++++
 6 files changed, 98 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/johnzon/blob/52f0aab8/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
index 3b020d2..5852177 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
@@ -30,6 +30,7 @@ import org.apache.johnzon.jsonb.serializer.JohnzonSerializationContext;
 import org.apache.johnzon.jsonb.spi.JohnzonAdapterFactory;
 import org.apache.johnzon.mapper.Adapter;
 import org.apache.johnzon.mapper.JohnzonAny;
+import org.apache.johnzon.mapper.JohnzonConverter;
 import org.apache.johnzon.mapper.ObjectConverter;
 import org.apache.johnzon.mapper.TypeAwareAdapter;
 import org.apache.johnzon.mapper.access.AccessMode;
@@ -166,11 +167,14 @@ public class JsonbAccessMode implements AccessMode, Closeable {
         final String[] params;
         final Adapter<?, ?>[] converters;
         final Adapter<?, ?>[] itemConverters;
+        final ObjectConverter.Codec<?>[] objectConverters;
         if (finalConstructor != null || finalFactory != null) {
             types = finalConstructor != null ? finalConstructor.getGenericParameterTypes() : finalFactory.getGenericParameterTypes();
             params = new String[types.length];
             converters = new Adapter<?, ?>[types.length];
             itemConverters = new Adapter<?, ?>[types.length];
+            objectConverters = new ObjectConverter.Codec<?>[types.length];
+
             int i = 0;
             for (final Parameter parameter : (finalConstructor == null ? finalFactory : finalConstructor).getParameters()) {
                 final JsonbProperty property = getAnnotation(parameter, JsonbProperty.class);
@@ -179,20 +183,25 @@ public class JsonbAccessMode implements AccessMode, Closeable {
                 final JsonbTypeAdapter adapter = getAnnotation(parameter, JsonbTypeAdapter.class);
                 final JsonbDateFormat dateFormat = getAnnotation(parameter, JsonbDateFormat.class);
                 final JsonbNumberFormat numberFormat = getAnnotation(parameter, JsonbNumberFormat.class);
-                if (adapter == null && dateFormat == null && numberFormat == null) {
+                final JohnzonConverter johnzonConverter = getAnnotation(parameter, JohnzonConverter.class);
+                if (adapter == null && dateFormat == null && numberFormat == null && johnzonConverter == null) {
                     converters[i] = defaultConverters.get(parameter.getType());
                     itemConverters[i] = null;
                 } else {
-                    validateAnnotations(parameter, adapter, dateFormat, numberFormat);
+                    validateAnnotations(parameter, adapter, dateFormat, numberFormat, johnzonConverter);
 
                     try {
-                        final Adapter converter = toConverter(parameter.getType(), adapter, dateFormat, numberFormat);
-                        if (matches(parameter.getParameterizedType(), converter)) {
-                            converters[i] = converter;
-                            itemConverters[i] = null;
-                        } else {
-                            converters[i] = null;
-                            itemConverters[i] = converter;
+                        if (adapter != null) {
+                            final Adapter converter = toConverter(parameter.getType(), adapter, dateFormat, numberFormat);
+                            if (matches(parameter.getParameterizedType(), converter)) {
+                                converters[i] = converter;
+                                itemConverters[i] = null;
+                            } else {
+                                converters[i] = null;
+                                itemConverters[i] = converter;
+                            }
+                        } else if (johnzonConverter != null) {
+                            objectConverters[i] = (ObjectConverter.Codec<?>) johnzonConverter.value().newInstance();
                         }
                     } catch (final InstantiationException | IllegalAccessException e) {
                         throw new IllegalArgumentException(e);
@@ -206,6 +215,7 @@ public class JsonbAccessMode implements AccessMode, Closeable {
             params = null;
             converters = null;
             itemConverters = null;
+            objectConverters = null;
         }
 
         return constructor == null && factory == null ? delegate.findFactory(clazz) : (
@@ -241,6 +251,11 @@ public class JsonbAccessMode implements AccessMode, Closeable {
                             public Adapter<?, ?>[] getParameterItemConverter() {
                                 return itemConverters;
                             }
+
+                            @Override
+                            public ObjectConverter.Codec<?>[] getObjectConverter() {
+                                return objectConverters;
+                            }
                         } :
                         new Factory() {
                             @Override
@@ -277,17 +292,24 @@ public class JsonbAccessMode implements AccessMode, Closeable {
                             public Adapter<?, ?>[] getParameterItemConverter() {
                                 return itemConverters;
                             }
+
+                            @Override
+                            public ObjectConverter.Codec<?>[] getObjectConverter() {
+                                return objectConverters;
+                            }
                         });
     }
 
     private void validateAnnotations(final Object parameter,
                                      final JsonbTypeAdapter adapter, final JsonbDateFormat dateFormat,
-                                     final JsonbNumberFormat numberFormat) {
+                                     final JsonbNumberFormat numberFormat,
+                                     final JohnzonConverter johnzonConverter) {
         int notNull = adapter != null ? 1 : 0;
         notNull += dateFormat != null ? 1 : 0;
         notNull += numberFormat != null ? 1 : 0;
+        notNull += johnzonConverter != null ? 1 : 0;
         if (notNull > 1) {
-            throw new IllegalArgumentException("Conflicting @JsonbXXX on " + parameter);
+            throw new IllegalArgumentException("Conflicting @JsonbXXX/@JohnzonConverter on " + parameter);
         }
     }
 
@@ -685,7 +707,8 @@ public class JsonbAccessMode implements AccessMode, Closeable {
             final JsonbTypeAdapter adapter = annotationHolder.getAnnotation(JsonbTypeAdapter.class);
             final JsonbDateFormat dateFormat = annotationHolder.getAnnotation(JsonbDateFormat.class);
             final JsonbNumberFormat numberFormat = annotationHolder.getAnnotation(JsonbNumberFormat.class);
-            validateAnnotations(annotationHolder, adapter, dateFormat, numberFormat);
+            final JohnzonConverter johnzonConverter = annotationHolder.getAnnotation(JohnzonConverter.class);
+            validateAnnotations(annotationHolder, adapter, dateFormat, numberFormat, johnzonConverter);
 
             try {
                 converter = adapter == null && dateFormat == null && numberFormat == null ?
@@ -705,8 +728,12 @@ public class JsonbAccessMode implements AccessMode, Closeable {
                 toRelease.add(instance);
                 reader = (jsonObject, targetType, parser) ->
                         instance.getValue().deserialize(parserFactory.get().createParser(jsonObject), new JohnzonDeserializationContext(parser), targetType);
-            } else {
-                reader = null;
+            } else if (johnzonConverter != null) {
+                try {
+                    reader = (ObjectConverter.Reader) johnzonConverter.value().newInstance();
+                } catch (final InstantiationException | IllegalAccessException e) {
+                    throw new IllegalArgumentException(e);
+                }
             }
         }
     }
@@ -720,7 +747,8 @@ public class JsonbAccessMode implements AccessMode, Closeable {
             final JsonbTypeAdapter adapter = initialReader.getAnnotation(JsonbTypeAdapter.class);
             final JsonbDateFormat dateFormat = initialReader.getAnnotation(JsonbDateFormat.class);
             final JsonbNumberFormat numberFormat = initialReader.getAnnotation(JsonbNumberFormat.class);
-            validateAnnotations(initialReader, adapter, dateFormat, numberFormat);
+            final JohnzonConverter johnzonConverter = initialReader.getAnnotation(JohnzonConverter.class);
+            validateAnnotations(initialReader, adapter, dateFormat, numberFormat, johnzonConverter);
 
             try {
                 converter = adapter == null && dateFormat == null && numberFormat == null ?
@@ -740,8 +768,12 @@ public class JsonbAccessMode implements AccessMode, Closeable {
                 toRelease.add(instance);
                 writer = (instance1, jsonbGenerator) ->
                         instance.getValue().serialize(instance1, jsonbGenerator.getJsonGenerator(), new JohnzonSerializationContext(jsonbGenerator));
-            } else {
-                writer = null;
+            } else if (johnzonConverter != null) {
+                try {
+                    writer = (ObjectConverter.Writer) johnzonConverter.value().newInstance();
+                } catch (final InstantiationException | IllegalAccessException e) {
+                    throw new IllegalArgumentException(e);
+                }
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/52f0aab8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
index 383b10c..41731d4 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
@@ -666,7 +666,7 @@ public class MappingParserImpl implements MappingParser {
                     mapping.factory.getParameterConverter()[i],
                     mapping.factory.getParameterItemConverter()[i],
                     mapping.factory.getParameterTypes()[i],
-                    null,
+                    mapping.factory.getObjectConverter()[i],
                     config.isDeduplicateObjects() ? new JsonPointerTracker(jsonPointer, paramName) : null); //X TODO ObjectConverter in @JOhnzonConverter with Constructors!
         }
 

http://git-wip-us.apache.org/repos/asf/johnzon/blob/52f0aab8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
index 8575aa3..4d590bf 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
@@ -52,6 +52,7 @@ public interface AccessMode {
         String[] getParameterNames();
         Adapter<?, ?>[] getParameterConverter();
         Adapter<?, ?>[] getParameterItemConverter();
+        ObjectConverter.Codec<?>[] getObjectConverter();
     }
 
     Factory findFactory(Class<?> clazz);

http://git-wip-us.apache.org/repos/asf/johnzon/blob/52f0aab8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
index e1bba2e..36200ad 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
@@ -134,6 +134,7 @@ public abstract class BaseAccessMode implements AccessMode {
         final String[] constructorParameters;
         final Adapter<?, ?>[] constructorParameterConverters;
         final Adapter<?, ?>[] constructorItemParameterConverters;
+        final ObjectConverter.Codec<?>[] objectConverters;
         if (constructorHasArguments) {
             factoryParameterTypes = constructor.getGenericParameterTypes();
 
@@ -143,6 +144,7 @@ public abstract class BaseAccessMode implements AccessMode {
 
             constructorParameterConverters = new Adapter<?, ?>[constructor.getGenericParameterTypes().length];
             constructorItemParameterConverters = new Adapter<?, ?>[constructorParameterConverters.length];
+            objectConverters = new ObjectConverter.Codec[constructorParameterConverters.length];
             for (int i = 0; i < constructorParameters.length; i++) {
                 for (final Annotation a : constructor.getParameterAnnotations()[i]) {
                     if (a.annotationType() == JohnzonConverter.class) {
@@ -158,7 +160,7 @@ public abstract class BaseAccessMode implements AccessMode {
                                     constructorItemParameterConverters[i] = converter;
                                 }
                             } else {
-                                throw new UnsupportedOperationException("TODO implement");
+                                objectConverters[i] = (ObjectConverter.Codec<?>) mapperConverter;
                             }
                         } catch (final Exception e) {
                             throw new IllegalArgumentException(e);
@@ -171,6 +173,7 @@ public abstract class BaseAccessMode implements AccessMode {
             constructorParameters = null;
             constructorParameterConverters = null;
             constructorItemParameterConverters = null;
+            objectConverters = null;
         }
 
         final Constructor<?> cons = constructor;
@@ -213,6 +216,11 @@ public abstract class BaseAccessMode implements AccessMode {
             public Adapter<?, ?>[] getParameterItemConverter() {
                 return constructorItemParameterConverters;
             }
+
+            @Override
+            public ObjectConverter.Codec<?>[] getObjectConverter() {
+                return objectConverters;
+            }
         };
     }
 

http://git-wip-us.apache.org/repos/asf/johnzon/blob/52f0aab8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
index cff4358..f2cec48 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
@@ -39,7 +39,7 @@ public class FieldAccessMode extends BaseAccessMode {
     @Override
     public Map<String, Reader> doFindReaders(final Class<?> clazz) {
         final Map<String, Reader> readers = new HashMap<String, Reader>();
-        for (final Map.Entry<String, Field> f : fields(clazz).entrySet()) {
+        for (final Map.Entry<String, Field> f : fields(clazz, true).entrySet()) {
             final String key = f.getKey();
             if (isIgnored(key) || Meta.getAnnotation(f.getValue(), JohnzonAny.class) != null) {
                 continue;
@@ -54,7 +54,7 @@ public class FieldAccessMode extends BaseAccessMode {
     @Override
     public Map<String, Writer> doFindWriters(final Class<?> clazz) {
         final Map<String, Writer> writers = new HashMap<String, Writer>();
-        for (final Map.Entry<String, Field> f : fields(clazz).entrySet()) {
+        for (final Map.Entry<String, Field> f : fields(clazz, false).entrySet()) {
             final String key = f.getKey();
             if (isIgnored(key)) {
                 continue;
@@ -75,7 +75,7 @@ public class FieldAccessMode extends BaseAccessMode {
         return key.contains("$");
     }
 
-    protected Map<String, Field> fields(final Class<?> clazz) {
+    protected Map<String, Field> fields(final Class<?> clazz, boolean includeFinalFields) {
         final Map<String, Field> fields = new HashMap<String, Field>();
         Class<?> current = clazz;
         while (current != null && current != Object.class) {
@@ -84,7 +84,8 @@ public class FieldAccessMode extends BaseAccessMode {
                 final int modifiers = f.getModifiers();
                 if (fields.containsKey(name)
                         || Modifier.isStatic(modifiers)
-                        || Modifier.isTransient(modifiers)) {
+                        || Modifier.isTransient(modifiers)
+                        || (!includeFinalFields && Modifier.isFinal(modifiers))) {
                     continue;
                 }
                 fields.put(name, f);

http://git-wip-us.apache.org/repos/asf/johnzon/blob/52f0aab8/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java
index 510672d..c465f8b 100644
--- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java
@@ -24,6 +24,7 @@ import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
 import javax.json.JsonObject;
+import java.beans.ConstructorProperties;
 import java.lang.reflect.Type;
 import java.util.Arrays;
 import java.util.List;
@@ -159,6 +160,38 @@ public class ObjectConverterWithAnnotationTest {
         Assert.assertEquals(expected, tourDeFlanderen);
     }
 
+    @Test
+    public void testDeserializeObjectWithAnnotatedConsturctorParameter() {
+
+        String json = "{" +
+                        "\"bike\": {" +
+                          "\"" + MANUFACTURER_ID + "\":1," +
+                          "\"" + TYPE_INDEX + "\":0" +
+                        "}" +
+                      "}";
+
+        Mapper mapper = new MapperBuilder().setAccessModeName(accessMode)
+                                           .setReadAttributeBeforeWrite(true)
+                                           .build();
+
+        BikeWrapper bikeWrapper = mapper.readObject(json, BikeWrapper.class);
+        Assert.assertNotNull(bikeWrapper);
+        Assert.assertEquals(bikeWrapper.getBike(), new Bike("Canyon", BikeType.ROAD));
+    }
+
+    public static class BikeWrapper {
+        private final Bike bike;
+
+        @ConstructorProperties(value = "bike")
+        BikeWrapper(@JohnzonConverter(value = BikeConverter.class) Bike bike) {
+            this.bike = bike;
+        }
+
+        Bike getBike() {
+            return bike;
+        }
+    }
+
 
     public static class CycleRace {
         private boolean monument;