From ba0ff8765767721ffe0938f25141ceb50dcc2866 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 2 Apr 2024 19:54:08 +0200 Subject: [PATCH] Add JSONValue and JSONCodec.unparseValue() RESTCONF use case requires serializing values using JSON encoding -- without having a document ready. Introduce JSONValue to encapsulate what sort of values we can have along with JSONCodec.unparseValue() -- which produces such values. JIRA: YANGTOOLS-1569 Change-Id: I398af058b5c017803a9dc4c61d3f7cfbc45cca5b Signed-off-by: Robert Varga --- .../data/codec/gson/BooleanJSONCodec.java | 5 ++ .../yang/data/codec/gson/EmptyJSONCodec.java | 5 ++ .../data/codec/gson/IdentityrefJSONCodec.java | 14 ++++- .../yang/data/codec/gson/JSONCodec.java | 10 +++ .../gson/JSONInstanceIdentifierCodec.java | 6 ++ .../yang/data/codec/gson/JSONValue.java | 61 +++++++++++++++++++ .../yang/data/codec/gson/NullJSONCodec.java | 5 ++ .../yang/data/codec/gson/NumberJSONCodec.java | 6 ++ .../yang/data/codec/gson/QuotedJSONCodec.java | 6 ++ .../yang/data/codec/gson/UnionJSONCodec.java | 40 +++++++++--- 10 files changed, 146 insertions(+), 12 deletions(-) create mode 100644 codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONValue.java diff --git a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/BooleanJSONCodec.java b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/BooleanJSONCodec.java index 401465b929..9730124cc3 100644 --- a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/BooleanJSONCodec.java +++ b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/BooleanJSONCodec.java @@ -22,4 +22,9 @@ final class BooleanJSONCodec extends AbstractJSONCodec { public void writeValue(final JSONValueWriter ctx, final Boolean value) throws IOException { ctx.writeBoolean(value); } + + @Override + public JSONValue unparseValue(final Boolean value) { + return value ? JSONValue.TRUE : JSONValue.FALSE; + } } diff --git a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/EmptyJSONCodec.java b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/EmptyJSONCodec.java index 46f33cb2d3..4a6d8b8109 100644 --- a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/EmptyJSONCodec.java +++ b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/EmptyJSONCodec.java @@ -27,6 +27,11 @@ final class EmptyJSONCodec implements JSONCodec { return Empty.value(); } + @Override + public JSONValue unparseValue(final Empty value) { + return JSONValue.EMPTY; + } + @Override public void writeValue(final JSONValueWriter ctx, final Empty value) throws IOException { ctx.writeEmpty(); diff --git a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/IdentityrefJSONCodec.java b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/IdentityrefJSONCodec.java index 3c3dad959c..c4d0de9947 100644 --- a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/IdentityrefJSONCodec.java +++ b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/IdentityrefJSONCodec.java @@ -14,6 +14,7 @@ import java.io.IOException; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.data.codec.gson.JSONValue.Kind; import org.opendaylight.yangtools.yang.data.util.codec.IdentityCodecUtil; import org.opendaylight.yangtools.yang.data.util.codec.QNameCodecUtil; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; @@ -45,10 +46,19 @@ final class IdentityrefJSONCodec implements JSONCodec { }).getQName(); } + @Override + public JSONValue unparseValue(final QName value) { + return new JSONValue(encode(value), Kind.STRING); + } + @Override public void writeValue(final JSONValueWriter ctx, final QName value) throws IOException { - ctx.writeString(QNameCodecUtil.encodeQName(value, uri -> context.findModuleStatement(uri) + ctx.writeString(encode(value)); + } + + private @NonNull String encode(final QName value) { + return QNameCodecUtil.encodeQName(value, uri -> context.findModuleStatement(uri) .map(module -> module.argument().getLocalName()) - .orElseThrow(() -> new IllegalArgumentException("Cannot find module for " + uri)))); + .orElseThrow(() -> new IllegalArgumentException("Cannot find module for " + uri))); } } diff --git a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java index 908709d88f..d872cced6e 100644 --- a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java +++ b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodec.java @@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.data.codec.gson; import com.google.gson.stream.JsonWriter; import java.io.IOException; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.yang.data.util.codec.TypeAwareCodec; /** @@ -60,4 +61,13 @@ public sealed interface JSONCodec extends TypeAwareCodec { // NOOP since codec is unknown. LOG.warn("Call of the serializeToWriter method on null codec. No operation performed."); } + + @Override + public JSONValue unparseValue(final Object value) { + throw new UnsupportedOperationException(); + } } diff --git a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/NumberJSONCodec.java b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/NumberJSONCodec.java index 6d4a4bf008..bc912b91dc 100644 --- a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/NumberJSONCodec.java +++ b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/NumberJSONCodec.java @@ -8,6 +8,7 @@ package org.opendaylight.yangtools.yang.data.codec.gson; import java.io.IOException; +import org.opendaylight.yangtools.yang.data.codec.gson.JSONValue.Kind; import org.opendaylight.yangtools.yang.data.impl.codec.DataStringCodec; /** @@ -20,6 +21,11 @@ final class NumberJSONCodec extends AbstractJSONCodec { super(codec); } + @Override + public JSONValue unparseValue(final T value) { + return new JSONValue(value.toString(), Kind.NUMBER); + } + @Override public void writeValue(final JSONValueWriter ctx, final T value) throws IOException { ctx.writeNumber(value); diff --git a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java index 9eec9d4038..5ce1e381d8 100644 --- a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java +++ b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/QuotedJSONCodec.java @@ -8,6 +8,7 @@ package org.opendaylight.yangtools.yang.data.codec.gson; import java.io.IOException; +import org.opendaylight.yangtools.yang.data.codec.gson.JSONValue.Kind; import org.opendaylight.yangtools.yang.data.impl.codec.DataStringCodec; /** @@ -20,6 +21,11 @@ final class QuotedJSONCodec extends AbstractJSONCodec { super(codec); } + @Override + public JSONValue unparseValue(final T value) { + return new JSONValue(serialize(value), Kind.STRING); + } + @Override public void writeValue(final JSONValueWriter ctx, final T value) throws IOException { ctx.writeString(serialize(value)); diff --git a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnionJSONCodec.java b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnionJSONCodec.java index 8f5b54132f..d39ac5ca96 100644 --- a/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnionJSONCodec.java +++ b/codec/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/UnionJSONCodec.java @@ -98,21 +98,41 @@ abstract sealed class UnionJSONCodec implements JSONCodec { @SuppressWarnings("checkstyle:illegalCatch") public final void writeValue(final JSONValueWriter ctx, final T value) throws IOException { for (var codec : codecs) { - if (!codec.getDataType().isInstance(value)) { + if (codec.getDataType().isInstance(value)) { + @SuppressWarnings("unchecked") + final var objCodec = (JSONCodec) codec; + try { + objCodec.writeValue(ctx, value); + return; + } catch (RuntimeException e) { + LOG.debug("Codec {} failed to serialize {}", codec, value, e); + } + } else { LOG.debug("Codec {} cannot accept input {}, skipping it", codec, value); - continue; } + } - @SuppressWarnings("unchecked") - final var objCodec = (JSONCodec) codec; - try { - objCodec.writeValue(ctx, value); - return; - } catch (RuntimeException e) { - LOG.debug("Codec {} failed to serialize {}", codec, value, e); + throw new IllegalArgumentException("No codecs could serialize" + value); + } + + + @Override + @SuppressWarnings("checkstyle:illegalCatch") + public JSONValue unparseValue(final Object value) { + for (var codec : codecs) { + if (codec.getDataType().isInstance(value)) { + @SuppressWarnings("unchecked") + final var objCodec = (JSONCodec) codec; + try { + return objCodec.unparseValue(value); + } catch (RuntimeException e) { + LOG.debug("Codec {} failed to unparse {}", codec, value, e); + } + } else { + LOG.debug("Codec {} cannot accept input {}, skipping it", codec, value); } } - throw new IllegalArgumentException("No codecs could serialize" + value); + throw new IllegalArgumentException("No codecs could unparse" + value); } } -- 2.36.6