You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by ni...@apache.org on 2015/06/10 01:58:05 UTC

[07/14] zest-qi4j git commit: Fix for ZEST-23.

Fix for ZEST-23.


Project: http://git-wip-us.apache.org/repos/asf/zest-qi4j/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-qi4j/commit/e6d2d6b5
Tree: http://git-wip-us.apache.org/repos/asf/zest-qi4j/tree/e6d2d6b5
Diff: http://git-wip-us.apache.org/repos/asf/zest-qi4j/diff/e6d2d6b5

Branch: refs/heads/develop
Commit: e6d2d6b59a60fe93597df338d0ad29ad22caadbe
Parents: 5915625
Author: Niclas Hedhman <ni...@hedhman.org>
Authored: Thu May 21 22:31:22 2015 +0800
Committer: Niclas Hedhman <ni...@hedhman.org>
Committed: Thu May 21 22:31:22 2015 +0800

----------------------------------------------------------------------
 .../main/java/org/qi4j/api/type/MapType.java    | 27 ++++++++++++++++
 .../entity/associations/AssociationTest.java    |  1 +
 .../spi/value/ValueDeserializerAdapter.java     | 34 +++++++++++++++++---
 .../qi4j/spi/value/ValueSerializerAdapter.java  |  4 +--
 .../orgjson/OrgJsonValueDeserializer.java       | 29 +++++++++++++++++
 .../AbstractCollectionSerializationTest.java    |  1 +
 .../jackson/JacksonValueDeserializer.java       | 26 +++++++++++++++
 .../stax/StaxValueDeserializer.java             | 23 +++++++++++++
 8 files changed, 138 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e6d2d6b5/core/api/src/main/java/org/qi4j/api/type/MapType.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/type/MapType.java b/core/api/src/main/java/org/qi4j/api/type/MapType.java
index ddf03c5..753500a 100644
--- a/core/api/src/main/java/org/qi4j/api/type/MapType.java
+++ b/core/api/src/main/java/org/qi4j/api/type/MapType.java
@@ -27,6 +27,17 @@ public final class MapType
 
     private ValueType keyType;
     private ValueType valueType;
+    private final Variant variant;
+
+    /** Two Variants are made distinct.
+     * <p>
+     * The {@code entry} type represents the explicit key=keyValue, value=valueValue.
+     * </p>
+     * <p>
+     * The {@code object} type represents the explicit keyValue=valueValue.
+     * </p>
+     */
+    public enum Variant { entry, object }
 
     public static boolean isMap( Type type )
     {
@@ -39,11 +50,22 @@ public final class MapType
         return new MapType( Map.class, ValueType.of( keyType ), ValueType.of( valueType ) );
     }
 
+    public static MapType of( Class<?> keyType, Class<?> valueType, Variant variant )
+    {
+        return new MapType( Map.class, ValueType.of( keyType ), ValueType.of( valueType ), variant );
+    }
+
     public MapType( Class<?> type, ValueType keyType, ValueType valueType )
     {
+        this( type, keyType, valueType, Variant.entry );
+    }
+
+    public MapType( Class<?> type, ValueType keyType, ValueType valueType, Variant variant )
+    {
         super( type );
         this.keyType = keyType;
         this.valueType = valueType;
+        this.variant = variant;
         if( !isMap( type ) )
         {
             throw new IllegalArgumentException( type + " is not a Map." );
@@ -60,6 +82,11 @@ public final class MapType
         return valueType;
     }
 
+    public Variant variant()
+    {
+        return variant;
+    }
+
     @Override
     public String toString()
     {

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e6d2d6b5/core/runtime/src/test/java/org/qi4j/runtime/entity/associations/AssociationTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/associations/AssociationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/associations/AssociationTest.java
index 7772245..ac321c9 100644
--- a/core/runtime/src/test/java/org/qi4j/runtime/entity/associations/AssociationTest.java
+++ b/core/runtime/src/test/java/org/qi4j/runtime/entity/associations/AssociationTest.java
@@ -101,6 +101,7 @@ public class AssociationTest
 
     public interface Friend<T>
     {
+        @Optional
         Association<T> friend();
     }
 

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e6d2d6b5/core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java b/core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java
index 6663150..b20bd79 100644
--- a/core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java
+++ b/core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java
@@ -32,7 +32,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Scanner;
 import java.util.Set;
-import java.util.logging.Logger;
 import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
 import org.joda.time.LocalDateTime;
@@ -687,7 +686,7 @@ public abstract class ValueDeserializerAdapter<InputType, InputNodeType>
                 Object value = getObjectFieldValue(
                     inputNode,
                     namedAssociationName,
-                    buildDeserializeInputNodeFunction( MapType.of( String.class, EntityReference.class ) ) );
+                    buildDeserializeInputNodeFunction( MapType.of( String.class, EntityReference.class, MapType.Variant.object ) ) );
                 stateMap.put( namedAssociationName, value );
             }
         }
@@ -755,7 +754,15 @@ public abstract class ValueDeserializerAdapter<InputType, InputNodeType>
         else // Explicit Map
         if( MapType.class.isAssignableFrom( valueType.getClass() ) )
         {
-            return (T) deserializeNodeMap( (MapType) valueType, inputNode );
+            MapType mapType = (MapType) valueType;
+            if( mapType.variant().equals( MapType.Variant.entry ) )
+            {
+                return (T) deserializeNodeEntryMap( (MapType) valueType, inputNode );
+            }
+            else
+            {
+                return (T) deserializeNodeObjectMap( (MapType) valueType, inputNode );
+            }
         }
         else // Enum
         if( EnumType.class.isAssignableFrom( valueType.getClass() ) || type.isEnum() )
@@ -857,7 +864,7 @@ public abstract class ValueDeserializerAdapter<InputType, InputNodeType>
         return collection;
     }
 
-    private <K, V> Map<K, V> deserializeNodeMap( MapType mapType, InputNodeType inputNode )
+    private <K, V> Map<K, V> deserializeNodeEntryMap( MapType mapType, InputNodeType inputNode )
         throws Exception
     {
         Map<K, V> map = new HashMap<>();
@@ -868,6 +875,16 @@ public abstract class ValueDeserializerAdapter<InputType, InputNodeType>
         return map;
     }
 
+    private <V> Map<String, V> deserializeNodeObjectMap( MapType mapType, InputNodeType inputNode )
+        throws Exception
+    {
+        Map<String, V> map = new HashMap<>();
+        putObjectNodeInMap( inputNode,
+                            this.<V>buildDeserializeInputNodeFunction( mapType.valueType() ),
+                            map );
+        return map;
+    }
+
     @SuppressWarnings( "unchecked" )
     private <T> T deserializeNodeGuessed( ValueType valueType, InputNodeType inputNode )
         throws Exception
@@ -1070,6 +1087,13 @@ public abstract class ValueDeserializerAdapter<InputType, InputNodeType>
     protected abstract <K, V> void putArrayNodeInMap( InputNodeType inputNode,
                                                       Function<InputNodeType, K> keyDeserializer,
                                                       Function<InputNodeType, V> valueDeserializer,
-                                                      Map<K, V> map )
+                                                      Map<K, V> map
+    )
+        throws Exception;
+
+    protected abstract <V> void putObjectNodeInMap( InputNodeType inputNode,
+                                                    Function<InputNodeType, V> valueDeserializer,
+                                                    Map<String, V> map
+    )
         throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e6d2d6b5/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java b/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
index c392214..8b6246f 100644
--- a/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
+++ b/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
@@ -473,7 +473,7 @@ public abstract class ValueSerializerAdapter<OutputType>
             NamedAssociation<?> namedAssociation = state.namedAssociationFor( associationDescriptor.accessor() );
             onFieldStart( output, associationDescriptor.qualifiedName().name() );
             onValueStart( output );
-            onArrayStart( output );
+            onObjectStart( output );
             for( String name : namedAssociation )
             {
                 onFieldStart( output, name );
@@ -482,7 +482,7 @@ public abstract class ValueSerializerAdapter<OutputType>
                 onValueEnd( output );
                 onFieldEnd( output );
             }
-            onArrayEnd( output );
+            onObjectEnd( output );
             onValueEnd( output );
             onFieldEnd( output );
         }

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e6d2d6b5/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueDeserializer.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueDeserializer.java b/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueDeserializer.java
index 452f75e..223bc99 100644
--- a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueDeserializer.java
+++ b/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueDeserializer.java
@@ -20,6 +20,7 @@ package org.qi4j.valueserialization.orgjson;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.Map;
 import org.json.JSONArray;
 import org.json.JSONObject;
@@ -449,4 +450,32 @@ public class OrgJsonValueDeserializer
             }
         }
     }
+
+    @Override
+    protected <V> void putObjectNodeInMap( Object inputNode, Function<Object, V> valueDeserializer, Map<String, V> map )
+        throws Exception
+    {
+        if( JSONObject.NULL.equals( inputNode ) )
+        {
+            return;
+        }
+        if( !( inputNode instanceof JSONObject ) )
+        {
+            throw new ValueSerializationException( "Expected an object but got " + inputNode );
+        }
+        JSONObject object = (JSONObject) inputNode;
+
+        @SuppressWarnings( "unchecked" )
+        Iterator<String> it = object.keys();
+        while( it.hasNext() )
+        {
+            String key = it.next();
+            Object item = object.get( key );
+            V valueValue = valueDeserializer.map( item );
+            if( key != null )
+            {
+                map.put( key, valueValue );
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e6d2d6b5/core/testsupport/src/main/java/org/qi4j/test/value/AbstractCollectionSerializationTest.java
----------------------------------------------------------------------
diff --git a/core/testsupport/src/main/java/org/qi4j/test/value/AbstractCollectionSerializationTest.java b/core/testsupport/src/main/java/org/qi4j/test/value/AbstractCollectionSerializationTest.java
index 5c58c2a..3a04ee5 100644
--- a/core/testsupport/src/main/java/org/qi4j/test/value/AbstractCollectionSerializationTest.java
+++ b/core/testsupport/src/main/java/org/qi4j/test/value/AbstractCollectionSerializationTest.java
@@ -69,6 +69,7 @@ public class AbstractCollectionSerializationTest
     {
         module.injectTo( this );
     }
+
     @Service
     @SuppressWarnings( "ProtectedField" )
     protected ValueSerialization valueSerialization;

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e6d2d6b5/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueDeserializer.java
----------------------------------------------------------------------
diff --git a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueDeserializer.java b/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueDeserializer.java
index 5c6774b..3d82f43 100644
--- a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueDeserializer.java
+++ b/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueDeserializer.java
@@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import java.io.InputStream;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.Map;
 import org.qi4j.api.injection.scope.Service;
 import org.qi4j.api.injection.scope.Structure;
@@ -341,6 +342,31 @@ public class JacksonValueDeserializer
         }
     }
 
+    @Override
+    protected <V> void putObjectNodeInMap( JsonNode inputNode,
+                                           Function<JsonNode, V> valueDeserializer,
+                                           Map<String, V> map
+    )
+        throws Exception
+    {
+        if( isNullOrMissing( inputNode ) )
+        {
+            return;
+        }
+        if( !inputNode.isObject() )
+        {
+            throw new ValueSerializationException( "Expected an object but got " + inputNode );
+        }
+        ObjectNode object = (ObjectNode) inputNode;
+        Iterator<Map.Entry<String, JsonNode>> fields = object.fields();
+        while( fields.hasNext() )
+        {
+            Map.Entry<String, JsonNode> entry = fields.next();
+            V value = valueDeserializer.map( entry.getValue() );
+            map.put( entry.getKey(), value );
+        }
+    }
+
     private static boolean isNullOrMissing( JsonNode inputNode )
     {
         return inputNode == null || inputNode.isNull() || inputNode.isMissingNode();

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/e6d2d6b5/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueDeserializer.java
----------------------------------------------------------------------
diff --git a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueDeserializer.java b/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueDeserializer.java
index 9bdc34a..f162a62 100644
--- a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueDeserializer.java
+++ b/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueDeserializer.java
@@ -404,6 +404,29 @@ public class StaxValueDeserializer
         }
     }
 
+    @Override
+    protected <V> void putObjectNodeInMap( Node inputNode,
+                                           Function<Node, V> valueDeserializer,
+                                           Map<String, V> map )
+        throws Exception
+    {
+        if( inputNode == null )
+        {
+            return;
+        }
+        NodeList entriesNodes = inputNode.getChildNodes();
+        for( int idx = 0; idx < entriesNodes.getLength(); idx++ )
+        {
+            Node entryNode = entriesNodes.item( idx );
+            String key  = ((Element) entryNode).getTagName();
+            V value = getObjectFieldValue( entryNode, "value", valueDeserializer );
+            if( key != null )
+            {
+                map.put( key, value );
+            }
+        }
+    }
+
     @SuppressWarnings( "AssignmentToMethodParameter" )
     private Object detectAndConvertStringValue( String stringValue )
     {