You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by rm...@apache.org on 2016/03/23 14:18:57 UTC

incubator-johnzon git commit: JOHNZON-70 ReadAttributeBeforeWrite option for mapper

Repository: incubator-johnzon
Updated Branches:
  refs/heads/master 01bae73bf -> c4c6f2900


JOHNZON-70 ReadAttributeBeforeWrite option for mapper


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

Branch: refs/heads/master
Commit: c4c6f2900bc6b2a9a4c4f5e2e796108509f03cd4
Parents: 01bae73
Author: Romain manni-Bucau <rm...@gmail.com>
Authored: Wed Mar 23 14:18:16 2016 +0100
Committer: Romain manni-Bucau <rm...@gmail.com>
Committed: Wed Mar 23 14:18:44 2016 +0100

----------------------------------------------------------------------
 .../jaxrs/ConfigurableJohnzonProvider.java      |  4 +++
 .../WildcardConfigurableJohnzonProvider.java    |  4 +++
 .../apache/johnzon/jsonb/JohnzonBuilder.java    |  5 ++-
 .../org/apache/johnzon/jsonb/AdapterTest.java   | 22 +++++++++---
 .../java/org/apache/johnzon/mapper/Mapper.java  | 37 ++++++++++++++------
 .../apache/johnzon/mapper/MapperBuilder.java    |  9 ++++-
 6 files changed, 65 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/c4c6f290/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
index e942385..ce783ab 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
@@ -195,4 +195,8 @@ public class ConfigurableJohnzonProvider<T> implements MessageBodyWriter<T>, Mes
     public void setEncoding(final String encoding) {
         builder.setEncoding(encoding);
     }
+
+    public void setReadAttributeBeforeWrite(final boolean rabw) {
+        builder.setReadAttributeBeforeWrite(rabw);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/c4c6f290/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
index 23f51e0..f404167 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
@@ -200,6 +200,10 @@ public class WildcardConfigurableJohnzonProvider<T> implements MessageBodyWriter
         builder.setTreatByteArrayAsBase64(treatByteArrayAsBase64);
     }
 
+    public void setReadAttributeBeforeWrite(final boolean rabw) {
+        builder.setReadAttributeBeforeWrite(rabw);
+    }
+
     public void setEncoding(final String encoding) {
         builder.setEncoding(encoding);
     }

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/c4c6f290/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
index b66d90e..d987230 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
@@ -202,7 +202,7 @@ public class JohnzonBuilder implements JsonbBuilder {
         }));
 
         config.getProperty(JsonbConfig.STRICT_IJSON).map(Boolean.class::cast).ifPresent(ijson -> {
-            // no-op: https://tools.ietf.org/html/rfc7493 the only MUST of the spec sould be fine by default
+            // no-op: https://tools.ietf.org/html/rfc7493 the only MUST of the spec should be fine by default
         });
 
         config.getProperty(JsonbConfig.BINARY_DATA_STRATEGY).map(String.class::cast).ifPresent(bin -> {
@@ -233,6 +233,9 @@ public class JohnzonBuilder implements JsonbBuilder {
 
         getBeanManager(); // force detection
 
+        builder.setReadAttributeBeforeWrite(
+                config.getProperty("johnzon.readAttributeBeforeWrite").map(Boolean.class::cast).orElse(false));
+
         final boolean useCdi = cdiIntegration != null && cdiIntegration.isCanWrite();
         final Mapper mapper = builder.addCloseable(accessMode).build();
 

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/c4c6f290/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java
index 538399c..05b80da 100644
--- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java
@@ -63,7 +63,10 @@ public class AdapterTest {
         final Polymorphism foo = new Polymorphism();
         foo.bars = new ArrayList<>(asList(bar, bar2));
 
-        final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withPropertyOrderStrategy(PropertyOrderStrategy.LEXICOGRAPHICAL));
+        final Jsonb jsonb = JsonbBuilder.create(
+                new JsonbConfig()
+                        .setProperty("johnzon.readAttributeBeforeWrite", true)
+                        .withPropertyOrderStrategy(PropertyOrderStrategy.LEXICOGRAPHICAL) /* assertEquals() order */);
 
         final String toString = jsonb.toJson(foo);
         assertEquals("{\"bars\":[" +
@@ -75,10 +78,8 @@ public class AdapterTest {
         assertEquals(11, read.bars.get(0).value);
         assertTrue(Bar.class == read.bars.get(0).getClass());
         assertEquals(21, read.bars.get(1).value);
-        /* not yet working since model is statically typed
         assertTrue(Bar2.class == read.bars.get(1).getClass());
         assertEquals(22, Bar2.class.cast(read.bars.get(1)).value2);
-        */
     }
 
     public static class Polymorphism {
@@ -88,9 +89,22 @@ public class AdapterTest {
 
 
     public static class TypeInstance {
-        public String type;
+        private String type;
         private Bar value;
 
+        public String getType() {
+            return type;
+        }
+
+        public void setType(final String type) {
+            this.type = type;
+            try {
+                this.value = Bar.class.cast(Thread.currentThread().getContextClassLoader().loadClass(type).newInstance());
+            } catch (final InstantiationException | IllegalAccessException | ClassNotFoundException e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+
         public Bar getValue() {
             return value;
         }

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/c4c6f290/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
index d24e44c..f3bbcd9 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
@@ -99,6 +99,7 @@ public class Mapper implements Closeable {
     protected final boolean skipEmptyArray;
     protected final boolean treatByteArrayAsBase64;
     protected final boolean treatByteArrayAsBase64URL;
+    protected final boolean readAttributeBeforeWrite;
     protected final Charset encoding;
     protected final ReaderHandler readerHandler;
     protected final Collection<Closeable> closeables;
@@ -108,7 +109,7 @@ public class Mapper implements Closeable {
                   final boolean doClose, final Map<AdapterKey, Adapter<?, ?>> adapters,
                   final int version, final Comparator<String> attributeOrder, final boolean skipNull, final boolean skipEmptyArray,
                   final AccessMode accessMode, final boolean treatByteArrayAsBase64, final boolean treatByteArrayAsBase64URL, final Charset encoding,
-                  final Collection<Closeable> closeables) {
+                  final Collection<Closeable> closeables, final boolean readAttributeBeforeWrite) {
     // CHECKSTYLE:ON
         this.readerFactory = readerFactory;
         this.generatorFactory = generatorFactory;
@@ -123,6 +124,7 @@ public class Mapper implements Closeable {
         this.encoding = encoding;
         this.readerHandler = ReaderHandler.create(readerFactory);
         this.closeables = closeables;
+        this.readAttributeBeforeWrite = readAttributeBeforeWrite;
     }
 
     private static JsonGenerator writePrimitives(final JsonGenerator generator, final Object value) {
@@ -749,7 +751,7 @@ public class Mapper implements Closeable {
                             } else if (JsonString.class.isInstance(jsonValue) && any) {
                                 map.put(value.getKey(), JsonString.class.cast(jsonValue).getString());
                             } else {
-                                map.put(convertTo(keyType, value.getKey()), toObject(jsonValue, fieldArgTypes[1], null));
+                                map.put(convertTo(keyType, value.getKey()), toObject(null, jsonValue, fieldArgTypes[1], null));
                             }
                         }
                         return map;
@@ -758,7 +760,7 @@ public class Mapper implements Closeable {
             } else if (Map.class == type || HashMap.class == type || LinkedHashMap.class == type) {
                 final LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
                 for (final Map.Entry<String, JsonValue> value : object.entrySet()) {
-                    map.put(value.getKey(), toObject(value.getValue(), Object.class, null));
+                    map.put(value.getKey(), toObject(null, value.getValue(), Object.class, null));
                 }
                 return map;
             }
@@ -788,7 +790,18 @@ public class Mapper implements Closeable {
             if (jsonValue == JsonValue.NULL) { // forced
                 setterMethod.write(t, null);
             } else {
-                final Object convertedValue = toValue(jsonValue, value.converter, value.itemConverter, value.paramType);
+                Object existingInstance = null;
+                if (readAttributeBeforeWrite) {
+                    final Mappings.Getter getter = classMapping.getters.get(setter.getKey());
+                    if (getter != null) {
+                        try {
+                            existingInstance = getter.reader.read(t);
+                        } catch (final RuntimeException re) {
+                            // backward compatibility
+                        }
+                    }
+                }
+                final Object convertedValue = toValue(existingInstance, jsonValue, value.converter, value.itemConverter, value.paramType);
                 if (convertedValue != null) {
                     setterMethod.write(t, convertedValue);
                 }
@@ -798,9 +811,10 @@ public class Mapper implements Closeable {
         return t;
     }
 
-    private Object toValue(final JsonValue jsonValue, final Adapter converter, final Adapter itemConverter, final Type type) throws Exception {
+    private Object toValue(final Object baseInstance, final JsonValue jsonValue, final Adapter converter,
+                           final Adapter itemConverter, final Type type) throws Exception {
         return converter == null ?
-                toObject(jsonValue, type, itemConverter) : jsonValue.getValueType() == ValueType.STRING ?
+                toObject(baseInstance, jsonValue, type, itemConverter) : jsonValue.getValueType() == ValueType.STRING ?
                 converter.to(JsonString.class.cast(jsonValue).getString()) :
                 convertTo(converter, jsonValue);
     }
@@ -833,13 +847,15 @@ public class Mapper implements Closeable {
         final Object[] objects = new Object[length];
         for (int i = 0; i < length; i++) {
             objects[i] = toValue(
+                null,
                 object.get(mapping.factory.getParameterNames()[i]), mapping.factory.getParameterConverter()[i],
                 mapping.factory.getParameterItemConverter()[i], mapping.factory.getParameterTypes()[i]);
         }
         return objects;
     }
 
-    private Object toObject(final JsonValue jsonValue, final Type type, final Adapter itemConverter) throws Exception {
+    private Object toObject(final Object baseInstance, final JsonValue jsonValue,
+                            final Type type, final Adapter itemConverter) throws Exception {
         if (jsonValue == null || JsonValue.NULL == jsonValue) {
             return null;
         }
@@ -884,7 +900,8 @@ public class Mapper implements Closeable {
             }
             final boolean typedAdapter = TypeAwareAdapter.class.isInstance(itemConverter);
             final Object object = buildObject(
-                    typedAdapter ? TypeAwareAdapter.class.cast(itemConverter).getTo() : type,
+                    baseInstance != null ? baseInstance.getClass() : (
+                    typedAdapter ? TypeAwareAdapter.class.cast(itemConverter).getTo() : type),
                     JsonObject.class.cast(jsonValue));
             return typedAdapter ? itemConverter.to(object) : object;
         } else if (JsonArray.class.isInstance(jsonValue)) {
@@ -992,7 +1009,7 @@ public class Mapper implements Closeable {
         }
 
         for (final JsonValue value : jsonArray) {
-            collection.add(value == JsonValue.NULL ? null : toObject(value, mapping.arg, itemConverter));
+            collection.add(value == JsonValue.NULL ? null : toObject(null, value, mapping.arg, itemConverter));
         }
 
         if (EnumSet.class == mapping.raw) {
@@ -1013,7 +1030,7 @@ public class Mapper implements Closeable {
         final Object array = Array.newInstance(componentType, jsonArray.size());
         int i = 0;
         for (final JsonValue value : jsonArray) {
-            Array.set(array, i++, toObject(value, componentType, itemConverter));
+            Array.set(array, i++, toObject(null, value, componentType, itemConverter));
         }
         return array;
     }

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/c4c6f290/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
index 443903b..e78f2f2 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
@@ -114,6 +114,7 @@ public class MapperBuilder {
     private boolean supportConstructors;
     private Charset encoding = Charset.forName(System.getProperty("johnzon.mapper.encoding", "UTF-8"));
     private boolean useGetterForCollections;
+    private boolean readAttributeBeforeWrite;
     private String accessModeName;
     private final Collection<Closeable> closeables = new ArrayList<Closeable>();
 
@@ -171,7 +172,8 @@ public class MapperBuilder {
             accessMode,
             treatByteArrayAsBase64, treatByteArrayAsBase64URL,
             encoding,
-            closeables);
+            closeables,
+            readAttributeBeforeWrite);
     }
 
     public MapperBuilder addCloseable(final Closeable closeable) {
@@ -323,4 +325,9 @@ public class MapperBuilder {
         this.encoding = Charset.forName(encoding);
         return this;
     }
+
+    public MapperBuilder setReadAttributeBeforeWrite(final boolean readAttributeBeforeWrite) {
+        this.readAttributeBeforeWrite = readAttributeBeforeWrite;
+        return this;
+    }
 }