Merge "Bug 2864: Fixed (de)serialization of leafrefs"
authorRobert Varga <nite@hq.sk>
Wed, 18 Mar 2015 11:10:43 +0000 (11:10 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 18 Mar 2015 11:10:43 +0000 (11:10 +0000)
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodecFactory.java
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONLeafrefCodec.java [deleted file]
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonParserStream.java

index c99d46404885c0b6c9b9e04dc24a64e0dbe0106f..c5840cff986b359c5f4271a29c8a5fa6829e0eb6 100644 (file)
@@ -15,11 +15,15 @@ import com.google.common.cache.LoadingCache;
 import com.google.gson.stream.JsonWriter;
 import java.io.IOException;
 import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.IdentityrefType;
 import org.opendaylight.yangtools.yang.model.util.InstanceIdentifierType;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -30,7 +34,6 @@ import org.slf4j.LoggerFactory;
 @Beta
 public final class JSONCodecFactory {
     private static final Logger LOG = LoggerFactory.getLogger(JSONCodecFactory.class);
-    private static final JSONCodec<Object> LEAFREF_DEFAULT_CODEC = new JSONLeafrefCodec();
     private static final JSONCodec<Object> NULL_CODEC = new JSONCodec<Object>() {
         @Override
         public Object deserialize(final String input) {
@@ -54,38 +57,19 @@ public final class JSONCodecFactory {
         }
     };
 
-    private static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
-        TypeDefinition<?> superType = type;
-        while (superType.getBaseType() != null) {
-            superType = superType.getBaseType();
-        }
-        return superType;
-    }
-
-    private final LoadingCache<TypeDefinition<?>, JSONCodec<Object>> codecs =
-            CacheBuilder.newBuilder().softValues().build(new CacheLoader<TypeDefinition<?>, JSONCodec<Object>>() {
-        @SuppressWarnings("unchecked")
+    private final LoadingCache<DataSchemaNode, JSONCodec<Object>> codecs =
+            CacheBuilder.newBuilder().softValues().build(new CacheLoader<DataSchemaNode, JSONCodec<Object>>() {
         @Override
-        public JSONCodec<Object> load(final TypeDefinition<?> key) throws Exception {
-            final TypeDefinition<?> type = resolveBaseTypeFrom(key);
-
-            if (type instanceof InstanceIdentifierType) {
-                return (JSONCodec<Object>) iidCodec;
+        public JSONCodec<Object> load(final DataSchemaNode key) throws Exception {
+            final TypeDefinition<?> type;
+            if (key instanceof LeafSchemaNode) {
+                type = ((LeafSchemaNode) key).getType();
+            } else if (key instanceof LeafListSchemaNode) {
+                type = ((LeafListSchemaNode) key).getType();
+            } else {
+                throw new IllegalArgumentException("Not supported node type " + key.getClass().getName());
             }
-            if (type instanceof IdentityrefType) {
-                return (JSONCodec<Object>) idrefCodec;
-            }
-            if (type instanceof LeafrefTypeDefinition) {
-                return LEAFREF_DEFAULT_CODEC;
-            }
-
-            final TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codec = TypeDefinitionAwareCodec.from(type);
-            if (codec == null) {
-                LOG.debug("Codec for type \"{}\" is not implemented yet.", type.getQName().getLocalName());
-                return NULL_CODEC;
-            }
-
-            return (JSONCodec<Object>) AbstractJSONCodec.create(codec);
+            return createCodec(key,type);
         }
     });
 
@@ -109,11 +93,55 @@ public final class JSONCodecFactory {
         return new JSONCodecFactory(context);
     }
 
+    private static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
+        TypeDefinition<?> superType = type;
+        while (superType.getBaseType() != null) {
+            superType = superType.getBaseType();
+        }
+        return superType;
+    }
+
+    private JSONCodec<Object> createCodec(DataSchemaNode key, TypeDefinition<?> type) {
+        TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
+        if (baseType instanceof LeafrefTypeDefinition) {
+            return createReferencedTypeCodec(key, (LeafrefTypeDefinition) baseType);
+        }
+        return createFromSimpleType(type);
+    }
+
+    private JSONCodec<Object> createReferencedTypeCodec(DataSchemaNode schema,
+            LeafrefTypeDefinition type) {
+        // FIXME: Verify if this does indeed support leafref of leafref
+        TypeDefinition<?> referencedType =
+                SchemaContextUtil.getBaseTypeForLeafRef(type, getSchemaContext(), schema);
+        return createFromSimpleType(referencedType);
+    }
+
+    @SuppressWarnings("unchecked")
+    private JSONCodec<Object> createFromSimpleType(TypeDefinition<?> type) {
+        final TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
+        if (baseType instanceof InstanceIdentifierType) {
+            return (JSONCodec<Object>) iidCodec;
+        }
+        if (baseType instanceof IdentityrefType) {
+            return (JSONCodec<Object>) idrefCodec;
+        }
+
+        final TypeDefinitionAwareCodec<Object, ?> codec = TypeDefinitionAwareCodec.from(type);
+        if (codec == null) {
+            LOG.debug("Codec for type \"{}\" is not implemented yet.", type.getQName()
+                    .getLocalName());
+            return NULL_CODEC;
+        }
+        return (JSONCodec<Object>) AbstractJSONCodec.create(codec);
+    }
+
     SchemaContext getSchemaContext() {
         return schemaContext;
     }
 
-    JSONCodec<Object> codecFor(final TypeDefinition<?> typeDefinition) {
-        return codecs.getUnchecked(typeDefinition);
+    JSONCodec<Object> codecFor(DataSchemaNode schema) {
+        return codecs.getUnchecked(schema);
     }
+
 }
diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONLeafrefCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONLeafrefCodec.java
deleted file mode 100644 (file)
index 51fc686..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.yangtools.yang.data.codec.gson;
-
-import com.google.gson.stream.JsonWriter;
-import java.io.IOException;
-import org.opendaylight.yangtools.yang.data.api.codec.LeafrefCodec;
-
-final class JSONLeafrefCodec implements JSONCodec<Object>, LeafrefCodec<String> {
-    @Override
-    public Object deserialize(final String input) {
-        return input;
-    }
-
-    @Override
-    public String serialize(final Object input) {
-        return String.valueOf(input);
-    }
-
-    @Override
-    public boolean needQuotes() {
-        return true;
-    }
-
-    /**
-     * Serialize specified value with specified JsonWriter.
-     *
-     * @param writer JsonWriter
-     * @param value
-     */
-    @Override
-    public void serializeToWriter(JsonWriter writer, Object value) throws IOException {
-        writer.value(serialize(value));
-    }
-}
\ No newline at end of file
index 57204c838aba86eee96f3f675090c8b9bb03d5bd..6b412d583d3c7675b81bc4ae89563b5d8809828d 100644 (file)
@@ -187,11 +187,9 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite
     @Override
     public void leafNode(final NodeIdentifier name, final Object value) throws IOException {
         final LeafSchemaNode schema = tracker.leafNode(name);
-        final JSONCodec<Object> codec = codecs.codecFor(schema.getType());
-
+        final JSONCodec<Object> codec = codecs.codecFor(schema);
         context.emittingChild(codecs.getSchemaContext(), writer);
         context.writeChildJsonIdentifier(codecs.getSchemaContext(), writer, name.getNodeType());
-
         writeValue(value, codec);
     }
 
@@ -204,10 +202,8 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite
     @Override
     public void leafSetEntryNode(final Object value) throws IOException {
         final LeafListSchemaNode schema = tracker.leafSetEntryNode();
-        final JSONCodec<Object> codec = codecs.codecFor(schema.getType());
-
+        final JSONCodec<Object> codec = codecs.codecFor(schema);
         context.emittingChild(codecs.getSchemaContext(), writer);
-
         writeValue(value, codec);
     }
 
index 4934161bd2757fcc1d0b9ab2d98b793c7721f15c..f0b4de3b03a90546f17c957ffcf1bc01625b9938 100644 (file)
@@ -21,7 +21,6 @@ import java.io.IOException;
 import java.net.URI;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.Deque;
 import java.util.HashSet;
@@ -34,13 +33,10 @@ import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 
 /**
  * This class parses JSON elements from a GSON JsonReader. It disallows multiple elements of the same name unlike the
@@ -206,32 +202,15 @@ public final class JsonParserStream implements Closeable, Flushable {
     }
 
     private Object translateValueByType(final String value, final DataSchemaNode node) {
-        final TypeDefinition<? extends Object> typeDefinition = typeDefinition(node);
-        if (typeDefinition == null) {
+        if (node instanceof AnyXmlSchemaNode) {
+            /*
+             *  FIXME: Figure out some YANG extension dispatch, which will
+             *  reuse JSON parsing or XML parsing - anyxml is not well-defined in
+             * JSON.
+             */
             return value;
         }
-
-        return codecs.codecFor(typeDefinition).deserialize(value);
-    }
-
-    private static TypeDefinition<? extends Object> typeDefinition(final DataSchemaNode node) {
-        TypeDefinition<?> baseType = null;
-        if (node instanceof LeafListSchemaNode) {
-            baseType = ((LeafListSchemaNode) node).getType();
-        } else if (node instanceof LeafSchemaNode) {
-            baseType = ((LeafSchemaNode) node).getType();
-        } else if (node instanceof AnyXmlSchemaNode) {
-            return null;
-        } else {
-            throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.<Object> asList(node).toString());
-        }
-
-        if (baseType != null) {
-            while (baseType.getBaseType() != null) {
-                baseType = baseType.getBaseType();
-            }
-        }
-        return baseType;
+        return codecs.codecFor(node).deserialize(value);
     }
 
     private void removeNamespace() {