Remove OperationOutputBody 09/111709/4
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 16 May 2024 16:36:54 +0000 (18:36 +0200)
committerRobert Varga <nite@hq.sk>
Fri, 17 May 2024 12:24:39 +0000 (12:24 +0000)
We have a fix for YANGTOOLS-1570 integrated, hence we do not need
to special-case anything -- a plain ContainerNode can we used with an
inference pointing to the operation.

JIRA: NETCONF-773
Change-Id: I0a70e067a796a7197a80d0312fdce90f793f08df
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/transactions/RestconfStrategy.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/api/DatabindPathFormattableBody.java [deleted file]
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/spi/NormalizedFormattableBody.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/spi/OperationOutputBody.java [deleted file]
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/jaxrs/AbstractRestconfTest.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/jaxrs/RestconfOperationsPostTest.java

index 86c00c7efae27b9c190fab9af5e99b8f2f15a850..752847b9c600596640581a0e13dd56bb8f012c37 100644 (file)
@@ -91,7 +91,6 @@ import org.opendaylight.restconf.server.spi.HttpGetResource;
 import org.opendaylight.restconf.server.spi.NormalizedFormattableBody;
 import org.opendaylight.restconf.server.spi.NormalizedNodeWriterFactory;
 import org.opendaylight.restconf.server.spi.OperationInput;
-import org.opendaylight.restconf.server.spi.OperationOutputBody;
 import org.opendaylight.restconf.server.spi.OperationsResource;
 import org.opendaylight.restconf.server.spi.RpcImplementation;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.with.defaults.rev110601.WithDefaultsMode;
@@ -1319,7 +1318,7 @@ public abstract class RestconfStrategy implements DatabindAware {
     private static @NonNull InvokeResult outputToInvokeResult(final @NonNull OperationPath path,
             final @Nullable ContainerNode value) {
         return value == null || value.isEmpty() ? InvokeResult.EMPTY
-            : new InvokeResult(new OperationOutputBody(path, value));
+            : new InvokeResult(NormalizedFormattableBody.of(path, value));
     }
 
     public @NonNull RestconfFuture<CharSource> resolveSource(final SourceIdentifier source,
diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/api/DatabindPathFormattableBody.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/api/DatabindPathFormattableBody.java
deleted file mode 100644 (file)
index 4b11350..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2024 PANTHEON.tech, s.r.o. 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.restconf.server.api;
-
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.base.MoreObjects.ToStringHelper;
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.restconf.api.FormattableBody;
-
-/**
- * A {@link FormattableBody} which has an attached {@link DatabindPath}.
- */
-@NonNullByDefault
-public abstract class DatabindPathFormattableBody<P extends DatabindPath> extends FormattableBody {
-    private final @NonNull P path;
-
-    protected DatabindPathFormattableBody(final P path) {
-        this.path = requireNonNull(path);
-    }
-
-    public final P path() {
-        return path;
-    }
-
-    @Override
-    protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
-        return helper.add("path", path).add("body", bodyAttribute());
-    }
-
-    protected abstract @Nullable Object bodyAttribute();
-}
index 19063bd6b8706893aa5aa8597a0b426b509df858..63556bae6cbe1a4034a1c5402b68160662245653 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.restconf.api.query.PrettyPrintParam;
 import org.opendaylight.restconf.server.api.DatabindContext;
 import org.opendaylight.restconf.server.api.DatabindFormattableBody;
 import org.opendaylight.restconf.server.api.DatabindPath.Data;
+import org.opendaylight.restconf.server.api.DatabindPath.OperationPath;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
@@ -84,6 +85,17 @@ public abstract sealed class NormalizedFormattableBody<N extends NormalizedNode>
             : data, writerFactory);
     }
 
+    /**
+     * Return a {@link FormattableBody} corresponding to a {@code rpc} or {@code action} invocation.
+     *
+     * @param path invocation path
+     * @param data the data
+     */
+    public static NormalizedFormattableBody<ContainerNode> of(final OperationPath path,
+            final ContainerNode data) {
+        return new DataFormattableBody<>(path.databind(), path.inference(), data);
+    }
+
     /**
      * Return data.
      *
diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/spi/OperationOutputBody.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/spi/OperationOutputBody.java
deleted file mode 100644 (file)
index 32ed369..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2024 PANTHEON.tech, s.r.o. 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.restconf.server.spi;
-
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.annotations.VisibleForTesting;
-import java.io.IOException;
-import java.io.OutputStream;
-import javax.xml.XMLConstants;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.opendaylight.restconf.api.FormattableBody;
-import org.opendaylight.restconf.api.query.PrettyPrintParam;
-import org.opendaylight.restconf.server.api.DatabindPath.OperationPath;
-import org.opendaylight.restconf.server.api.DatabindPathFormattableBody;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
-import org.opendaylight.yangtools.yang.data.codec.gson.JSONNormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
-
-/**
- * A {@link FormattableBody} corresponding to a {@code rpc} or {@code action} invocation.
- */
-@NonNullByDefault
-public final class OperationOutputBody extends DatabindPathFormattableBody<OperationPath> {
-    private final ContainerNode output;
-
-    public OperationOutputBody(final OperationPath path, final ContainerNode output) {
-        super(path);
-        this.output = requireNonNull(output);
-        if (output.isEmpty()) {
-            throw new IllegalArgumentException("output may not be empty");
-        }
-    }
-
-    @VisibleForTesting
-    public ContainerNode output() {
-        return output;
-    }
-
-    @Override
-    public void formatToJSON(final PrettyPrintParam prettyPrint, final OutputStream out) throws IOException {
-        final var stack = prepareStack();
-
-        // RpcDefinition/ActionDefinition is not supported as initial codec in JSONStreamWriter, so we need to emit
-        // initial output declaration
-        try (var jsonWriter = FormattableBodySupport.createJsonWriter(out, prettyPrint)) {
-            final var module = stack.currentModule();
-            jsonWriter.beginObject().name(module.argument().getLocalName() + ":output").beginObject();
-
-            final var nnWriter = NormalizedNodeWriter.forStreamWriter(
-                JSONNormalizedNodeStreamWriter.createNestedWriter(path().databind().jsonCodecs(), stack.toInference(),
-                    module.namespace().argument(), jsonWriter));
-            for (var child : output.body()) {
-                nnWriter.write(child);
-            }
-            nnWriter.flush();
-
-            jsonWriter.endObject().endObject();
-        }
-    }
-
-    @Override
-    public void formatToXML(final PrettyPrintParam prettyPrint, final OutputStream out) throws IOException {
-        final var stack = prepareStack();
-
-        // RpcDefinition/ActionDefinition is not supported as initial codec in XMLStreamWriter, so we need to emit
-        // initial output declaration.
-        final var xmlWriter = FormattableBodySupport.createXmlWriter(out, prettyPrint);
-        final var nnWriter = NormalizedNodeWriter.forStreamWriter(
-            XMLStreamNormalizedNodeStreamWriter.create(xmlWriter, stack.toInference()));
-
-        writeElements(xmlWriter, nnWriter, output);
-        nnWriter.flush();
-    }
-
-    @Override
-    protected @NonNull Object bodyAttribute() {
-        return output.prettyTree();
-    }
-
-    private SchemaInferenceStack prepareStack() {
-        final var path = path();
-        final var stack = path.inference().toSchemaInferenceStack();
-        stack.enterSchemaTree(path.outputStatement().argument());
-        return stack;
-    }
-
-    private static void writeElements(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter,
-            final ContainerNode data) throws IOException {
-        final QName nodeType = data.name().getNodeType();
-        final String namespace = nodeType.getNamespace().toString();
-        try {
-            xmlWriter.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, nodeType.getLocalName(), namespace);
-            xmlWriter.writeDefaultNamespace(namespace);
-            for (var child : data.body()) {
-                nnWriter.write(child);
-            }
-            nnWriter.flush();
-            xmlWriter.writeEndElement();
-            xmlWriter.flush();
-        } catch (final XMLStreamException e) {
-            throw new IOException("Failed to write elements", e);
-        }
-    }
-}
index 8819d67139a857c75f319bf4b0fbde44c74c06fb..f0e5e0514d28da2ae637cd164a2e9c97c3b954a0 100644 (file)
@@ -47,7 +47,6 @@ import org.opendaylight.restconf.nb.rfc8040.ErrorTagMapping;
 import org.opendaylight.restconf.server.mdsal.MdsalDatabindProvider;
 import org.opendaylight.restconf.server.mdsal.MdsalRestconfServer;
 import org.opendaylight.restconf.server.spi.NormalizedFormattableBody;
-import org.opendaylight.restconf.server.spi.OperationOutputBody;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
@@ -83,7 +82,7 @@ abstract class AbstractRestconfTest extends AbstractJukeboxTest {
         return JUKEBOX_SCHEMA;
     }
 
-    static final void assertJson(final String expectedJson, final OperationOutputBody payload) {
+    static final void assertJson(final String expectedJson, final NormalizedFormattableBody<?> payload) {
         final var baos = new ByteArrayOutputStream();
         try {
             payload.formatToJSON(PrettyPrintParam.FALSE, baos);
@@ -93,7 +92,7 @@ abstract class AbstractRestconfTest extends AbstractJukeboxTest {
         assertEquals(expectedJson, baos.toString(StandardCharsets.UTF_8));
     }
 
-    static final void assertXml(final String expectedXml, final OperationOutputBody payload) {
+    static final void assertXml(final String expectedXml, final NormalizedFormattableBody<?> payload) {
         final var baos = new ByteArrayOutputStream();
         try {
             payload.formatToXML(PrettyPrintParam.FALSE, baos);
@@ -114,12 +113,12 @@ abstract class AbstractRestconfTest extends AbstractJukeboxTest {
     }
 
     static final ContainerNode assertOperationOutput(final int status, final Consumer<AsyncResponse> invocation) {
-        return assertOperationOutputBody(status, invocation).output();
+        return assertInstanceOf(ContainerNode.class, assertOperationOutputBody(status, invocation).data());
     }
 
-    static final OperationOutputBody assertOperationOutputBody(final int status,
+    static final NormalizedFormattableBody<?> assertOperationOutputBody(final int status,
             final Consumer<AsyncResponse> invocation) {
-        return assertInstanceOf(OperationOutputBody.class, assertFormattableBody(status, invocation));
+        return assertInstanceOf(NormalizedFormattableBody.class, assertFormattableBody(status, invocation));
     }
 
     static final <T> T assertEntity(final Class<T> expectedType, final int expectedStatus,
index 30ba800edfb4a93b1a22006377a6a1c9c1f46a0b..c3e9dfc8d5daf4a05b7ab16c04e28bfbf250a822 100644 (file)
@@ -205,7 +205,7 @@ class RestconfOperationsPostTest extends AbstractRestconfTest {
                     }
                   }
                 }"""), uriInfo, ar));
-        assertEquals(OUTPUT, body.output());
+        assertEquals(OUTPUT, body.data());
         assertJson("""
             {"invoke-rpc-module:output":{"cont-out":{"lf-out":"operation result"}}}""", body);
         assertXml("""