import java.io.IOException;
import java.io.InputStream;
+import java.io.PushbackInputStream;
import org.eclipse.jdt.annotation.NonNull;
+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.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolder;
+import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
/**
* Stream the {@code input} into a {@link NormalizedNodeStreamWriter}.
*
* @param inference An {@link Inference} of parent {@code rpc} or {@code action} statement
- * @param writer Target writer
+ * @return The document body, or an empty container node
* @throws IOException when an I/O error occurs
*/
- // TODO: pass down DatabindContext corresponding to inference
- public final void streamTo(final @NonNull Inference inference, final @NonNull NormalizedNodeStreamWriter writer)
- throws IOException {
- streamTo(acquireStream(), inference, writer);
+ public @NonNull ContainerNode toContainerNode(final @NonNull Inference inference) throws IOException {
+ try (var is = new PushbackInputStream(acquireStream())) {
+ final var firstByte = is.read();
+ if (firstByte == -1) {
+ return emptyInput(inference);
+ }
+ is.unread(firstByte);
+
+ final var holder = new NormalizationResultHolder();
+ try (var streamWriter = ImmutableNormalizedNodeStreamWriter.from(holder)) {
+ streamTo(is, inference, streamWriter);
+ }
+ return (ContainerNode) holder.getResult().data();
+ }
}
abstract void streamTo(@NonNull InputStream inputStream, @NonNull Inference inference,
@NonNull NormalizedNodeStreamWriter writer) throws IOException;
+
+ private static @NonNull ContainerNode emptyInput(final Inference inference) {
+ return Builders.containerBuilder()
+ .withNodeIdentifier(new NodeIdentifier(extractInput(inference).argument()))
+ .build();
+ }
+
+ private static @NonNull InputEffectiveStatement extractInput(final Inference inference) {
+ final var stmt = inference.toSchemaInferenceStack().currentStatement();
+ if (stmt instanceof RpcEffectiveStatement rpc) {
+ return rpc.input();
+ } else if (stmt instanceof ActionEffectiveStatement action) {
+ return action.streamEffectiveSubstatements(InputEffectiveStatement.class).findFirst().orElseThrow();
+ } else {
+ throw new IllegalStateException(inference + " does not identify an 'rpc' statement");
+ }
+ }
}
import org.opendaylight.yangtools.yang.common.YangConstants;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final var schemaContext = dataBind.modelContext();
final var context = ParserIdentifier.toInstanceIdentifier(identifier, schemaContext, mountPointService);
- final var holder = new NormalizationResultHolder();
- try (var streamWriter = ImmutableNormalizedNodeStreamWriter.from(holder)) {
- body.streamTo(context.inference(), streamWriter);
+ final ContainerNode input;
+ try {
+ input = body.toContainerNode(context.inference());
} catch (IOException e) {
LOG.debug("Error reading input", e);
throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL,
ErrorTag.MALFORMED_MESSAGE, e);
}
final var rpcName = context.getSchemaNode().getQName();
- final var input = (ContainerNode) holder.getResult().data();
final ListenableFuture<? extends DOMRpcResult> future;
final var mountPoint = context.getMountPoint();