BUG-1745, BUG-1746: remove needless quotes 36/10936/2
authorRobert Varga <rovarga@cisco.com>
Tue, 9 Sep 2014 09:27:34 +0000 (11:27 +0200)
committerRobert Varga <rovarga@cisco.com>
Tue, 9 Sep 2014 12:21:46 +0000 (14:21 +0200)
The class-based detection did not work because the encodec values are
always strings. Rework the codec factory to make that obvious. Add a
codec-type dispatch which will detect the need for quotes.

Change-Id: I9ca6b66d95522d2022db3f271f9fc40d213a8329
Signed-off-by: Robert Varga <rovarga@cisco.com>
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/AbstractJSONCodec.java [new file with mode: 0644]
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CodecFactory.java
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java [new file with mode: 0644]
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONLeafrefCodec.java [new file with mode: 0644]
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/JSONStringIdentityrefCodec.java
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringInstanceIdentifierCodec.java
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java [new file with mode: 0644]
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnquotedJSONCodec.java [new file with mode: 0644]

diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/AbstractJSONCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/AbstractJSONCodec.java
new file mode 100644 (file)
index 0000000..9464653
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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.common.base.Preconditions;
+
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.BooleanCodec;
+import org.opendaylight.yangtools.yang.data.api.codec.DecimalCodec;
+import org.opendaylight.yangtools.yang.data.api.codec.Int16Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Int32Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Int64Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Int8Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Uint16Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Uint32Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Uint64Codec;
+import org.opendaylight.yangtools.yang.data.api.codec.Uint8Codec;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+
+/**
+ * Abstract base implementation of {@link JSONCodec}, which wraps a {@link TypeDefinitionAwareCodec}.
+ *
+ * @param <T> Deserialized objec type
+ */
+abstract class AbstractJSONCodec<T> implements JSONCodec<T> {
+    private final Codec<String, T> codec;
+
+    protected AbstractJSONCodec(final Codec<String, T> codec) {
+        this.codec = Preconditions.checkNotNull(codec);
+    }
+
+    /**
+     * Create a proper JSONCodec based on the underlying codec type
+     * @param codec underlying codec
+     * @return A JSONCodec instance
+     */
+    public static <T> JSONCodec<T> create(final Codec<String, T> codec) {
+        if (codec instanceof BooleanCodec || codec instanceof DecimalCodec ||
+                codec instanceof Int8Codec || codec instanceof Int16Codec ||
+                codec instanceof Int32Codec || codec instanceof Int64Codec ||
+                codec instanceof Uint8Codec || codec instanceof Uint16Codec ||
+                codec instanceof Uint32Codec || codec instanceof Uint64Codec) {
+            return new UnquotedJSONCodec<>(codec);
+        }
+
+        return new QuotedJSONCodec<>(codec);
+    }
+
+    @Override
+    public final T deserialize(final String input) {
+        return codec.deserialize(input);
+    }
+
+    @Override
+    public final String serialize(final T input) {
+        return codec.serialize(input);
+    }
+}
index dba5ed7d24638c4f757622911725a75ff8d84ff9..e755925af22977394127a7e8122b0b00b29f3a7e 100644 (file)
@@ -12,8 +12,6 @@ import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 
-import org.opendaylight.yangtools.concepts.Codec;
-import org.opendaylight.yangtools.yang.data.api.codec.LeafrefCodec;
 import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
@@ -29,30 +27,24 @@ import org.slf4j.LoggerFactory;
 @Beta
 final class CodecFactory {
     private static final Logger LOG = LoggerFactory.getLogger(CodecFactory.class);
-    private static final Codec<?, ?> LEAFREF_DEFAULT_CODEC = new LeafrefCodec<String>() {
+    private static final JSONCodec<Object> LEAFREF_DEFAULT_CODEC = new JSONLeafrefCodec();
+    private static final JSONCodec<Object> NULL_CODEC = new JSONCodec<Object>() {
         @Override
-        public String serialize(final Object data) {
-            return String.valueOf(data);
+        public Object deserialize(final String input) {
+            return null;
         }
 
         @Override
-        public Object deserialize(final String data) {
-            return data;
-        }
-    };
-    private static final Codec<?, ?> NULL_CODEC = new Codec<Object, Object>() {
-        @Override
-        public Object deserialize(final Object input) {
+        public String serialize(final Object input) {
             return null;
         }
 
         @Override
-        public Object serialize(final Object input) {
-            return null;
+        public boolean needQuotes() {
+            return false;
         }
     };
 
-
     private static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
         TypeDefinition<?> superType = type;
         while (superType.getBaseType() != null) {
@@ -61,17 +53,18 @@ final class CodecFactory {
         return superType;
     }
 
-    private final LoadingCache<TypeDefinition<?>, Codec<?, ?>> codecs =
-            CacheBuilder.newBuilder().softValues().build(new CacheLoader<TypeDefinition<?>, Codec<?, ?>>() {
+    private final LoadingCache<TypeDefinition<?>, JSONCodec<Object>> codecs =
+            CacheBuilder.newBuilder().softValues().build(new CacheLoader<TypeDefinition<?>, JSONCodec<Object>>() {
+        @SuppressWarnings("unchecked")
         @Override
-        public Codec<?, ?> load(final TypeDefinition<?> key) throws Exception {
+        public JSONCodec<Object> load(final TypeDefinition<?> key) throws Exception {
             final TypeDefinition<?> type = resolveBaseTypeFrom(key);
 
             if (type instanceof InstanceIdentifierType) {
-                return iidCodec;
+                return (JSONCodec<Object>) iidCodec;
             }
             if (type instanceof IdentityrefType) {
-                return idrefCodec;
+                return (JSONCodec<Object>) idrefCodec;
             }
             if (type instanceof LeafrefTypeDefinition) {
                 return LEAFREF_DEFAULT_CODEC;
@@ -83,12 +76,12 @@ final class CodecFactory {
                 return NULL_CODEC;
             }
 
-            return codec;
+            return AbstractJSONCodec.create(codec);
         }
     });
 
-    private final Codec<?, ?> iidCodec;
-    private final Codec<?, ?> idrefCodec;
+    private final JSONCodec<?> iidCodec;
+    private final JSONCodec<?> idrefCodec;
 
     private CodecFactory(final SchemaContext context) {
         iidCodec = new JSONStringInstanceIdentifierCodec(context);
@@ -99,8 +92,7 @@ final class CodecFactory {
         return new CodecFactory(context);
     }
 
-    @SuppressWarnings("unchecked")
-    public final Codec<Object, Object> codecFor(final TypeDefinition<?> typeDefinition) {
-        return (Codec<Object, Object>) codecs.getUnchecked(typeDefinition);
+    public final JSONCodec<Object> codecFor(final TypeDefinition<?> typeDefinition) {
+        return codecs.getUnchecked(typeDefinition);
     }
 }
diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java
new file mode 100644 (file)
index 0000000..aa52259
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * 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 org.opendaylight.yangtools.concepts.Codec;
+
+interface JSONCodec<T> extends Codec<String, T> {
+    boolean needQuotes();
+}
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
new file mode 100644 (file)
index 0000000..5613433
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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 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;
+    }
+}
\ No newline at end of file
index 9e0224220ecaad4d0422dfb2e20b54d95f01e2f4..a0488ee6ae8f75e3d0441e714e9d1d5dfb533d9f 100644 (file)
@@ -9,17 +9,12 @@ package org.opendaylight.yangtools.yang.data.codec.gson;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableSet;
 import com.google.gson.stream.JsonWriter;
 
 import java.io.IOException;
 import java.io.Writer;
-import java.math.BigDecimal;
-import java.math.BigInteger;
 import java.net.URI;
-import java.util.Collection;
 
-import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
@@ -45,8 +40,6 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite
      * are marked as 'presence'.
      */
     private static final boolean DEFAULT_EMIT_EMPTY_CONTAINERS = true;
-    private static final Collection<Class<?>> NUMERIC_CLASSES =
-            ImmutableSet.<Class<?>>of(Byte.class, Short.class, Integer.class, Long.class, BigInteger.class, BigDecimal.class);
 
     private final SchemaContext schemaContext;
     private final SchemaTracker tracker;
@@ -128,11 +121,11 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite
     @Override
     public void leafNode(final NodeIdentifier name, final Object value) throws IOException {
         final LeafSchemaNode schema = tracker.leafNode(name);
-        final Codec<Object, Object> codec = codecs.codecFor(schema.getType());
+        final JSONCodec<Object> codec = codecs.codecFor(schema.getType());
 
         context.emittingChild(schemaContext, writer, indent);
         context.writeJsonIdentifier(schemaContext, writer, name.getNodeType());
-        writeValue(codec.serialize(value));
+        writeValue(codec.serialize(value), codec.needQuotes());
     }
 
     @Override
@@ -144,16 +137,21 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite
     @Override
     public void leafSetEntryNode(final Object value) throws IOException {
         final LeafListSchemaNode schema = tracker.leafSetEntryNode();
-        final Codec<Object, Object> codec = codecs.codecFor(schema.getType());
+        final JSONCodec<Object> codec = codecs.codecFor(schema.getType());
 
         context.emittingChild(schemaContext, writer, indent);
-        writeValue(codec.serialize(value));
+        writeValue(codec.serialize(value), codec.needQuotes());
     }
 
+    /*
+     * Warning suppressed due to static final constant which triggers a warning
+     * for the call to schema.isPresenceContainer().
+     */
+    @SuppressWarnings("unused")
     @Override
     public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
         final ContainerSchemaNode schema = tracker.startContainerNode(name);
-        context = new JSONStreamWriterNamedObjectContext(context, name, schema.isPresenceContainer() || DEFAULT_EMIT_EMPTY_CONTAINERS);
+        context = new JSONStreamWriterNamedObjectContext(context, name, DEFAULT_EMIT_EMPTY_CONTAINERS || schema.isPresenceContainer());
     }
 
     @Override
@@ -206,7 +204,7 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite
 
         context.emittingChild(schemaContext, writer, indent);
         context.writeJsonIdentifier(schemaContext, writer, name.getNodeType());
-        writeValue(value);
+        writeValue(String.valueOf(value), true);
     }
 
     @Override
@@ -215,10 +213,8 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite
         context = context.endNode(schemaContext, writer, indent);
     }
 
-    private void writeValue(final Object value) throws IOException {
-        final String str = String.valueOf(value);
-
-        if (!NUMERIC_CLASSES.contains(value.getClass())) {
+    private void writeValue(final String str, final boolean needQuotes) throws IOException {
+        if (needQuotes) {
             writer.append('"');
             writer.append(str);
             writer.append('"');
index 66d55237a567c813d31b1d77d7e3505731ac17b8..fcbe473cca8dc6b414814a2e05ed3f92d9e3673e 100644 (file)
@@ -11,11 +11,12 @@ import com.google.common.base.Preconditions;
 
 import java.net.URI;
 
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringIdentityrefCodec;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-final class JSONStringIdentityrefCodec extends AbstractModuleStringIdentityrefCodec {
+final class JSONStringIdentityrefCodec extends AbstractModuleStringIdentityrefCodec implements JSONCodec<QName> {
     private final SchemaContext context;
 
     JSONStringIdentityrefCodec(final SchemaContext context) {
@@ -33,4 +34,8 @@ final class JSONStringIdentityrefCodec extends AbstractModuleStringIdentityrefCo
         return module == null ? null : module.getName();
     }
 
+    @Override
+    public boolean needQuotes() {
+        return true;
+    }
 }
index fc1322fba9096bc3a3e906855a630e748ae71514..a1580dd5bb2c3f5681569c1c3541e68d38f51cbf 100644 (file)
@@ -11,11 +11,12 @@ import com.google.common.base.Preconditions;
 
 import java.net.URI;
 
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-final class JSONStringInstanceIdentifierCodec extends AbstractModuleStringInstanceIdentifierCodec {
+final class JSONStringInstanceIdentifierCodec extends AbstractModuleStringInstanceIdentifierCodec implements JSONCodec<YangInstanceIdentifier> {
     private final SchemaContext context;
 
     JSONStringInstanceIdentifierCodec(final SchemaContext context) {
@@ -32,4 +33,9 @@ final class JSONStringInstanceIdentifierCodec extends AbstractModuleStringInstan
         final Module module = context.findModuleByNamespaceAndRevision(namespace, null);
         return module == null ? null : module.getName();
     }
+
+    @Override
+    public boolean needQuotes() {
+        return true;
+    }
 }
diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java
new file mode 100644 (file)
index 0000000..e8606f8
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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 org.opendaylight.yangtools.concepts.Codec;
+
+/**
+ * A {@link JSONCodec} which needs double quotes in output representation.
+ *
+ * @param <T> Deserialized value type
+ */
+final class QuotedJSONCodec<T> extends AbstractJSONCodec<T> {
+    QuotedJSONCodec(final Codec<String, T> codec) {
+        super(codec);
+    }
+
+    @Override
+    public boolean needQuotes() {
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnquotedJSONCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnquotedJSONCodec.java
new file mode 100644 (file)
index 0000000..f29db5d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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 org.opendaylight.yangtools.concepts.Codec;
+
+/**
+ * A {@link JSONCodec} which does not need double quotes in output representation.
+ *
+ * @param <T> Deserialized value type
+ */
+final class UnquotedJSONCodec<T> extends AbstractJSONCodec<T> {
+    UnquotedJSONCodec(final Codec<String, T> codec) {
+        super(codec);
+    }
+
+    @Override
+    public boolean needQuotes() {
+        return false;
+    }
+}
\ No newline at end of file