From 05dec17ecf753541133f8a852f5e16b157efef87 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 9 Sep 2014 11:27:34 +0200 Subject: [PATCH] BUG-1745, BUG-1746: remove needless quotes 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 --- .../data/codec/gson/AbstractJSONCodec.java | 63 +++++++++++++++++++ .../yang/data/codec/gson/CodecFactory.java | 44 ++++++------- .../yang/data/codec/gson/JSONCodec.java | 14 +++++ .../data/codec/gson/JSONLeafrefCodec.java | 27 ++++++++ .../gson/JSONNormalizedNodeStreamWriter.java | 30 ++++----- .../gson/JSONStringIdentityrefCodec.java | 7 ++- .../JSONStringInstanceIdentifierCodec.java | 8 ++- .../yang/data/codec/gson/QuotedJSONCodec.java | 26 ++++++++ .../data/codec/gson/UnquotedJSONCodec.java | 26 ++++++++ 9 files changed, 200 insertions(+), 45 deletions(-) create mode 100644 yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/AbstractJSONCodec.java create mode 100644 yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java create mode 100644 yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONLeafrefCodec.java create mode 100644 yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java create mode 100644 yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnquotedJSONCodec.java 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 index 0000000000..94646531a8 --- /dev/null +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/AbstractJSONCodec.java @@ -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 Deserialized objec type + */ +abstract class AbstractJSONCodec implements JSONCodec { + private final Codec codec; + + protected AbstractJSONCodec(final Codec 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 JSONCodec create(final Codec 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); + } +} diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CodecFactory.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CodecFactory.java index dba5ed7d24..e755925af2 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CodecFactory.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CodecFactory.java @@ -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() { + private static final JSONCodec LEAFREF_DEFAULT_CODEC = new JSONLeafrefCodec(); + private static final JSONCodec NULL_CODEC = new JSONCodec() { @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() { - @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, Codec> codecs = - CacheBuilder.newBuilder().softValues().build(new CacheLoader, Codec>() { + private final LoadingCache, JSONCodec> codecs = + CacheBuilder.newBuilder().softValues().build(new CacheLoader, JSONCodec>() { + @SuppressWarnings("unchecked") @Override - public Codec load(final TypeDefinition key) throws Exception { + public JSONCodec load(final TypeDefinition key) throws Exception { final TypeDefinition type = resolveBaseTypeFrom(key); if (type instanceof InstanceIdentifierType) { - return iidCodec; + return (JSONCodec) iidCodec; } if (type instanceof IdentityrefType) { - return idrefCodec; + return (JSONCodec) 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 codecFor(final TypeDefinition typeDefinition) { - return (Codec) codecs.getUnchecked(typeDefinition); + public final JSONCodec 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 index 0000000000..aa52259c58 --- /dev/null +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java @@ -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 extends Codec { + 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 index 0000000000..5613433bbe --- /dev/null +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONLeafrefCodec.java @@ -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, LeafrefCodec { + @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 diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java index 9e0224220e..a0488ee6ae 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java @@ -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> NUMERIC_CLASSES = - ImmutableSet.>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 codec = codecs.codecFor(schema.getType()); + final JSONCodec 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 codec = codecs.codecFor(schema.getType()); + final JSONCodec 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('"'); diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringIdentityrefCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringIdentityrefCodec.java index 66d55237a5..fcbe473cca 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringIdentityrefCodec.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringIdentityrefCodec.java @@ -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 { 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; + } } diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringInstanceIdentifierCodec.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringInstanceIdentifierCodec.java index fc1322fba9..a1580dd5bb 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringInstanceIdentifierCodec.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONStringInstanceIdentifierCodec.java @@ -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 { 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 index 0000000000..e8606f8d95 --- /dev/null +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java @@ -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 Deserialized value type + */ +final class QuotedJSONCodec extends AbstractJSONCodec { + QuotedJSONCodec(final Codec 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 index 0000000000..f29db5d1ee --- /dev/null +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnquotedJSONCodec.java @@ -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 Deserialized value type + */ +final class UnquotedJSONCodec extends AbstractJSONCodec { + UnquotedJSONCodec(final Codec codec) { + super(codec); + } + + @Override + public boolean needQuotes() { + return false; + } +} \ No newline at end of file -- 2.36.6