2 * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.restconf.server.api;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.annotations.VisibleForTesting;
13 import com.google.common.base.MoreObjects.ToStringHelper;
14 import java.io.IOException;
15 import java.io.OutputStream;
16 import org.eclipse.jdt.annotation.NonNullByDefault;
17 import org.opendaylight.restconf.nb.rfc8040.jersey.providers.ParameterAwareNormalizedNodeWriter;
18 import org.opendaylight.restconf.server.api.DatabindPath.OperationPath;
19 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
20 import org.opendaylight.yangtools.yang.data.codec.gson.JSONNormalizedNodeStreamWriter;
21 import org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter;
22 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
25 * A {@link FormattableBody} corresponding to a {@code rpc} or {@code action} invocation.
28 public final class OperationOutputBody extends FormattableBody {
29 private final OperationPath path;
30 private final ContainerNode output;
32 public OperationOutputBody(final FormatParameters format, final OperationPath path, final ContainerNode output) {
34 this.path = requireNonNull(path);
35 this.output = requireNonNull(output);
36 if (output.isEmpty()) {
37 throw new IllegalArgumentException("output may not be empty");
42 public ContainerNode output() {
47 void formatToJSON(final OutputStream out, final FormatParameters format) throws IOException {
48 final var stack = prepareStack();
50 // RpcDefinition/ActionDefinition is not supported as initial codec in JSONStreamWriter, so we need to emit
51 // initial output declaration
52 try (var jsonWriter = createJsonWriter(out, format)) {
53 final var module = stack.currentModule();
54 jsonWriter.beginObject().name(module.argument().getLocalName() + ":output").beginObject();
56 final var nnWriter = ParameterAwareNormalizedNodeWriter.forStreamWriter(
57 JSONNormalizedNodeStreamWriter.createNestedWriter(path.databind().jsonCodecs(), stack.toInference(),
58 module.namespace().argument(), jsonWriter), null, null);
59 for (var child : output.body()) {
60 nnWriter.write(child);
64 jsonWriter.endObject().endObject();
69 void formatToXML(final OutputStream out, final FormatParameters format) throws IOException {
70 final var stack = prepareStack();
72 // RpcDefinition/ActionDefinition is not supported as initial codec in XMLStreamWriter, so we need to emit
73 // initial output declaration.
74 final var xmlWriter = createXmlWriter(out, format);
75 final var nnWriter = ParameterAwareNormalizedNodeWriter.forStreamWriter(
76 XMLStreamNormalizedNodeStreamWriter.create(xmlWriter, stack.toInference()), null, null);
78 writeElements(xmlWriter, nnWriter, output);
83 ToStringHelper addToStringAttributes(final ToStringHelper helper) {
84 return super.addToStringAttributes(helper.add("path", path).add("output", output.prettyTree()));
87 private SchemaInferenceStack prepareStack() {
88 final var stack = path.inference().toSchemaInferenceStack();
89 stack.enterSchemaTree(path.outputStatement().argument());