import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter.MountPointExtension;
import org.opendaylight.yangtools.yang.data.util.NormalizedNodeStreamWriterStack;
-import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.EffectiveStatementInference;
import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.PresenceEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
import org.w3c.dom.Element;
}
/**
- * RFC6020 deviation: we are not required to emit empty containers unless they
- * are marked as 'presence'.
+ * RFC6020 deviation: we are not required to emit empty containers unless they are marked as 'presence'.
*/
private static final boolean DEFAULT_EMIT_EMPTY_CONTAINERS = true;
private final JSONCodecFactory codecs;
private final JsonWriter writer;
private final DefaultJSONValueWriter valueWriter;
+
private JSONStreamWriterContext context;
- JSONNormalizedNodeStreamWriter(final JSONCodecFactory codecFactory, final NormalizedNodeStreamWriterStack tracker,
- final JsonWriter writer, final JSONStreamWriterRootContext rootContext) {
+ private JSONNormalizedNodeStreamWriter(final JSONCodecFactory codecFactory,
+ final NormalizedNodeStreamWriterStack tracker, final JsonWriter writer,
+ final JSONStreamWriterRootContext rootContext) {
this.writer = requireNonNull(writer);
codecs = requireNonNull(codecFactory);
this.tracker = requireNonNull(tracker);
context = new JSONStreamWriterListContext(context, name);
}
- /*
- * Warning suppressed due to static final constant which triggers a warning
- * for the call to schema.isPresenceContainer().
- */
@Override
public final void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
- final boolean isPresence = tracker.startContainerNode(name) instanceof ContainerSchemaNode container
- ? container.isPresenceContainer() : DEFAULT_EMIT_EMPTY_CONTAINERS;
- context = new JSONStreamWriterNamedObjectContext(context, name, isPresence);
+ final boolean emitIfEmpty = tracker.startContainerNode(name) instanceof ContainerEffectiveStatement container
+ ? container.findFirstEffectiveSubstatement(PresenceEffectiveStatement.class).isPresent()
+ : DEFAULT_EMIT_EMPTY_CONTAINERS;
+ context = new JSONStreamWriterNamedObjectContext(context, name, emitIfEmpty);
}
@Override
@Override
public void scalarValue(final Object value) throws IOException {
- final Object current = tracker.getParent();
+ final var current = tracker.currentStatement();
if (current instanceof TypedDataSchemaNode typed) {
writeValue(value, codecs.codecFor(typed, tracker));
- } else if (current instanceof AnydataSchemaNode) {
+ } else if (current instanceof AnydataEffectiveStatement) {
writeAnydataValue(value);
} else {
throw new IllegalStateException(String.format("Cannot emit scalar %s for %s", value, current));
@Override
public void domSourceValue(final DOMSource value) throws IOException {
- final Object current = tracker.getParent();
- checkState(current instanceof AnyxmlSchemaNode, "Cannot emit DOMSource %s for %s", value, current);
+ final var current = tracker.currentStatement();
+ checkState(current instanceof AnyxmlEffectiveStatement, "Cannot emit DOMSource %s for %s", value, current);
// FIXME: should have a codec based on this :)
writeAnyXmlValue(value);
}
--- /dev/null
+/*
+ * 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.yangtools.yang.data.codec.gson;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import org.junit.jupiter.api.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.Uint64;
+import org.opendaylight.yangtools.yang.common.Uint8;
+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.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+class YT1570Test {
+ private static final QName INPUT = QName.create("foo", "input");
+ private static final QName OUTPUT = QName.create("foo", "output");
+ private static final QName FOO = QName.create("foo", "foo");
+ private static final QName BAR = QName.create("foo", "bar");
+ private static final QName BAZ = QName.create("foo", "baz");
+ private static final QName UINT = QName.create("foo", "uint");
+
+ private static final EffectiveModelContext MODEL_CONTEXT = YangParserTestUtils.parseYang("""
+ module foo {
+ namespace foo;
+ prefix foo;
+ yang-version 1.1;
+
+ rpc foo {
+ input {
+ leaf uint {
+ type uint8;
+ }
+ }
+ output {
+ leaf uint {
+ type uint64;
+ }
+ }
+ }
+
+ container bar {
+ action baz {
+ input {
+ leaf uint {
+ type uint8;
+ }
+ }
+ output {
+ leaf uint {
+ type uint64;
+ }
+ }
+ }
+ }
+ }""");
+
+ @Test
+ void testRpcInput() {
+ assertEquals("""
+ {
+ "foo:input": {
+ "uint": 1
+ }
+ }""",
+ serialize(ImmutableNodes.newContainerBuilder()
+ .withNodeIdentifier(new NodeIdentifier(INPUT))
+ .withChild(ImmutableNodes.leafNode(UINT, Uint8.ONE))
+ .build(), FOO));
+ }
+
+ @Test
+ void testRpcOutput() {
+ assertEquals("""
+ {
+ "foo:output": {
+ "uint": "1"
+ }
+ }""",
+ serialize(ImmutableNodes.newContainerBuilder()
+ .withNodeIdentifier(new NodeIdentifier(OUTPUT))
+ .withChild(ImmutableNodes.leafNode(UINT, Uint64.ONE))
+ .build(), FOO));
+ }
+
+ @Test
+ void testActionInput() {
+ assertEquals("""
+ {
+ "foo:input": {
+ "uint": 2
+ }
+ }""",
+ serialize(ImmutableNodes.newContainerBuilder()
+ .withNodeIdentifier(new NodeIdentifier(INPUT))
+ .withChild(ImmutableNodes.leafNode(UINT, Uint8.TWO))
+ .build(), BAR, BAZ));
+ }
+
+ @Test
+ void testActionOutput() {
+ assertEquals("""
+ {
+ "foo:output": {
+ "uint": "2"
+ }
+ }""",
+ serialize(ImmutableNodes.newContainerBuilder()
+ .withNodeIdentifier(new NodeIdentifier(OUTPUT))
+ .withChild(ImmutableNodes.leafNode(UINT, Uint64.TWO))
+ .build(), BAR, BAZ));
+ }
+
+ private static String serialize(final ContainerNode container, final QName... nodeIdentifiers) {
+ final var writer = new StringWriter();
+ final var jsonStream = JSONNormalizedNodeStreamWriter.createExclusiveWriter(
+ JSONCodecFactorySupplier.RFC7951.getShared(MODEL_CONTEXT),
+ SchemaInferenceStack.of(MODEL_CONTEXT, Absolute.of(nodeIdentifiers)).toInference(), null,
+ JsonWriterFactory.createJsonWriter(writer, 2));
+ try (var nodeWriter = NormalizedNodeWriter.forStreamWriter(jsonStream)) {
+ nodeWriter.write(container);
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ return writer.toString();
+ }
+}
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.util.NormalizedNodeStreamWriterStack;
-import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerLike;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ListEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
final class SchemaAwareXMLStreamNormalizedNodeStreamWriter
@Override
public void endNode() throws IOException {
- final Object schema = tracker.endNode();
- if (schema instanceof ListSchemaNode || schema instanceof LeafListSchemaNode) {
+ final var schema = tracker.endNode();
+ if (schema instanceof ListEffectiveStatement || schema instanceof LeafListEffectiveStatement) {
// For lists, we only emit end element on the inner frame
- final Object parent = tracker.getParent();
- if (parent == schema) {
+ if (tracker.currentStatement() == schema) {
endElement();
}
- } else if (schema instanceof ContainerLike || schema instanceof LeafSchemaNode
- || schema instanceof AnydataSchemaNode || schema instanceof AnyxmlSchemaNode) {
+ } else if (schema instanceof ContainerEffectiveStatement || schema instanceof LeafEffectiveStatement
+ || schema instanceof AnydataEffectiveStatement || schema instanceof AnyxmlEffectiveStatement
+ || schema instanceof InputEffectiveStatement || schema instanceof OutputEffectiveStatement
+ || schema instanceof NotificationEffectiveStatement) {
endElement();
}
}
@Override
public void scalarValue(final Object value) throws IOException {
- final Object current = tracker.getParent();
+ final var current = tracker.currentStatement();
if (current instanceof TypedDataSchemaNode typedSchema) {
writeValue(value, typedSchema);
- } else if (current instanceof AnydataSchemaNode) {
+ } else if (current instanceof AnydataEffectiveStatement) {
anydataValue(value);
} else {
throw new IllegalStateException("Unexpected scalar value " + value + " with " + current);
@Override
public void domSourceValue(final DOMSource value) throws IOException {
- final Object current = tracker.getParent();
- checkState(current instanceof AnyxmlSchemaNode, "Unexpected value %s with %s", value, current);
+ final var current = tracker.currentStatement();
+ checkState(current instanceof AnyxmlEffectiveStatement, "Unexpected value %s with %s", value, current);
anyxmlValue(value);
}
--- /dev/null
+/*
+ * 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.yangtools.yang.data.codec.xml;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import javax.xml.stream.XMLStreamException;
+import org.junit.jupiter.api.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.Uint64;
+import org.opendaylight.yangtools.yang.common.Uint8;
+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.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+class YT1570Test {
+ private static final QName INPUT = QName.create("foo", "input");
+ private static final QName OUTPUT = QName.create("foo", "output");
+ private static final QName FOO = QName.create("foo", "foo");
+ private static final QName BAR = QName.create("foo", "bar");
+ private static final QName BAZ = QName.create("foo", "baz");
+ private static final QName UINT = QName.create("foo", "uint");
+
+ private static final EffectiveModelContext MODEL_CONTEXT = YangParserTestUtils.parseYang("""
+ module foo {
+ namespace foo;
+ prefix foo;
+ yang-version 1.1;
+
+ rpc foo {
+ input {
+ leaf uint {
+ type uint8;
+ }
+ }
+ output {
+ leaf uint {
+ type uint64;
+ }
+ }
+ }
+
+ container bar {
+ action baz {
+ input {
+ leaf uint {
+ type uint8;
+ }
+ }
+ output {
+ leaf uint {
+ type uint64;
+ }
+ }
+ }
+ }
+ }""");
+
+ @Test
+ void testRpcInput() {
+ assertEquals("""
+ <input xmlns="foo"><uint>1</uint></input>""",
+ serialize(ImmutableNodes.newContainerBuilder()
+ .withNodeIdentifier(new NodeIdentifier(INPUT))
+ .withChild(ImmutableNodes.leafNode(UINT, Uint8.ONE))
+ .build(), FOO));
+ }
+
+ @Test
+ void testRpcOutput() {
+ assertEquals("""
+ <output xmlns="foo"><uint>1</uint></output>""",
+ serialize(ImmutableNodes.newContainerBuilder()
+ .withNodeIdentifier(new NodeIdentifier(OUTPUT))
+ .withChild(ImmutableNodes.leafNode(UINT, Uint64.ONE))
+ .build(), FOO));
+ }
+
+ @Test
+ void testActionInput() {
+ assertEquals("""
+ <input xmlns="foo"><uint>2</uint></input>""",
+ serialize(ImmutableNodes.newContainerBuilder()
+ .withNodeIdentifier(new NodeIdentifier(INPUT))
+ .withChild(ImmutableNodes.leafNode(UINT, Uint8.TWO))
+ .build(), BAR, BAZ));
+ }
+
+ @Test
+ void testActionOutput() {
+ assertEquals("""
+ <output xmlns="foo"><uint>2</uint></output>""",
+ serialize(ImmutableNodes.newContainerBuilder()
+ .withNodeIdentifier(new NodeIdentifier(OUTPUT))
+ .withChild(ImmutableNodes.leafNode(UINT, Uint64.TWO))
+ .build(), BAR, BAZ));
+ }
+
+ private static String serialize(final ContainerNode container, final QName... nodeIdentifiers) {
+ final var writer = new StringWriter();
+ try {
+ final var xmlStream = XMLStreamNormalizedNodeStreamWriter.create(
+ TestFactories.DEFAULT_OUTPUT_FACTORY.createXMLStreamWriter(writer),
+ SchemaInferenceStack.of(MODEL_CONTEXT, Absolute.of(nodeIdentifiers)).toInference());
+ try (var nodeWriter = NormalizedNodeWriter.forStreamWriter(xmlStream)) {
+ nodeWriter.write(container);
+ }
+ } catch (IOException | XMLStreamException e) {
+ throw new AssertionError(e);
+ }
+ return writer.toString();
+ }
+}
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.Beta;
-import com.google.common.base.VerifyException;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerLike;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.EffectiveStatementInference;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnydataEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ListEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
public final class NormalizedNodeStreamWriterStack implements LeafrefResolver {
private static final Logger LOG = LoggerFactory.getLogger(NormalizedNodeStreamWriterStack.class);
- private final Deque<DataSchemaNode> schemaStack = new ArrayDeque<>();
+ private final Deque<EffectiveStatement<?, ?>> schemaStack = new ArrayDeque<>();
private final SchemaInferenceStack dataTree;
- private final DataNodeContainer root;
+ private final Object root;
private NormalizedNodeStreamWriterStack(final EffectiveModelContext context) {
dataTree = SchemaInferenceStack.of(context);
this.dataTree = requireNonNull(dataTree);
if (!dataTree.isEmpty()) {
final var current = dataTree.currentStatement();
- if (current instanceof DataNodeContainer container) {
+ if (current instanceof DataTreeAwareEffectiveStatement container) {
root = container;
} else {
throw new IllegalArgumentException("Cannot instantiate on " + current);
return dataTree.resolveLeafref(type);
}
- public Object getParent() {
- final var schema = schemaStack.peek();
- return schema == null ? root : schema;
+ /**
+ * Return the current {@link EffectiveStatement}, or {@code null}.
+ *
+ * @return the current {@link EffectiveStatement}, or {@code null}
+ */
+ public @Nullable EffectiveStatement<?, ?> currentStatement() {
+ return schemaStack.peek();
}
- private @NonNull SchemaNode enterDataTree(final PathArgument name) {
+ private @NonNull DataTreeEffectiveStatement<?> enterDataTree(final PathArgument name) {
final var qname = name.getNodeType();
final var stmt = dataTree.enterDataTree(qname);
- if (!(stmt instanceof SchemaNode ret)) {
- throw new VerifyException("Unexpected result " + stmt);
+ if (currentStatement() instanceof ChoiceEffectiveStatement choice) {
+ final var check = choice.findDataTreeNode(qname).orElse(null);
+ verify(check == stmt, "Data tree result %s does not match choice result %s", stmt, check);
}
- if (getParent() instanceof ChoiceSchemaNode choice) {
- final var check = choice.findDataSchemaChild(qname).orElse(null);
- verify(check == ret, "Data tree result %s does not match choice result %s", ret, check);
- }
- return ret;
+ return stmt;
}
- private <T extends DataSchemaNode> @NonNull T enterDataTree(final PathArgument name,
+ private <T extends DataTreeEffectiveStatement<?>> @NonNull T enterDataTree(final PathArgument name,
final @NonNull Class<T> expectedClass, final @NonNull String humanString) {
final var schema = enterDataTree(name);
- final T casted;
+ final @NonNull T casted;
try {
casted = expectedClass.cast(schema);
} catch (ClassCastException e) {
}
public void startList(final PathArgument name) {
- enterDataTree(name, ListSchemaNode.class, "a list");
+ enterDataTree(name, ListEffectiveStatement.class, "a list");
}
public void startListItem(final PathArgument name) throws IOException {
- if (!(getParent() instanceof ListSchemaNode parentList)) {
+ if (!(currentStatement() instanceof ListEffectiveStatement parentList)) {
throw new IllegalArgumentException("List item is not appropriate");
}
schemaStack.push(parentList);
}
public void startLeafNode(final NodeIdentifier name) throws IOException {
- enterDataTree(name, LeafSchemaNode.class, "a leaf");
+ enterDataTree(name, LeafEffectiveStatement.class, "a leaf");
}
public void startLeafSet(final NodeIdentifier name) {
- enterDataTree(name, LeafListSchemaNode.class, "a leaf-list");
+ enterDataTree(name, LeafListEffectiveStatement.class, "a leaf-list");
+ }
+
+ public void startLeafSetEntryNode(final NodeWithValue<?> name) {
+ schemaStack.push(leafSetEntryNode(name.getNodeType()));
}
- private @NonNull LeafListSchemaNode leafSetEntryNode(final QName qname) {
- final Object parent = getParent();
- if (parent instanceof LeafListSchemaNode leafList) {
+ private @NonNull LeafListEffectiveStatement leafSetEntryNode(final QName qname) {
+ final var parent = currentStatement();
+ if (parent instanceof LeafListEffectiveStatement leafList) {
return leafList;
}
- if (parent instanceof DataNodeContainer parentContainer) {
- final var child = parentContainer.dataChildByName(qname);
- if (child instanceof LeafListSchemaNode childLeafList) {
+ if (parent instanceof DataTreeAwareEffectiveStatement parentContainer) {
+ final var child = parentContainer.findDataTreeNode(qname).orElse(null);
+ if (child instanceof LeafListEffectiveStatement childLeafList) {
return childLeafList;
}
throw new IllegalArgumentException(
throw new IllegalArgumentException("Cannot lookup " + qname + " in parent " + parent);
}
- public void startLeafSetEntryNode(final NodeWithValue<?> name) {
- schemaStack.push(leafSetEntryNode(name.getNodeType()));
- }
-
public void startChoiceNode(final NodeIdentifier name) {
LOG.debug("Enter choice {}", name);
- final var stmt = dataTree.enterChoice(name.getNodeType());
- if (stmt instanceof ChoiceSchemaNode choice) {
- schemaStack.push(choice);
- } else {
- throw new VerifyException("Node " + stmt + " is not a choice");
- }
+ schemaStack.push(dataTree.enterChoice(name.getNodeType()));
}
- public @NonNull ContainerLike startContainerNode(final NodeIdentifier name) {
+ public @NonNull DataTreeAwareEffectiveStatement<QName, ?> startContainerNode(final NodeIdentifier name) {
LOG.debug("Enter container {}", name);
- final ContainerLike schema;
- if (schemaStack.isEmpty() && root instanceof NotificationDefinition notification
- && name.getNodeType().equals(notification.getQName())) {
+ final DataTreeAwareEffectiveStatement<QName, ?> ret;
+ if (schemaStack.isEmpty() && root instanceof NotificationEffectiveStatement notification
+ && name.getNodeType().equals(notification.argument())) {
// Special case for stacks initialized at notification. We pretend the first container is contained within
// itself.
// FIXME: 8.0.0: factor this special case out to something more reasonable, like being initialized at the
// Notification's parent and knowing to enterSchemaTree() instead of enterDataTree().
- schema = notification.toContainerLike();
- schemaStack.push(schema);
+ ret = notification;
} else {
- schema = enterDataTree(name, ContainerLike.class, "a container");
+ final var child = enterDataTree(name);
+ if (child instanceof ContainerEffectiveStatement container) {
+ ret = container;
+ } else if (child instanceof InputEffectiveStatement input) {
+ ret = input;
+ } else if (child instanceof OutputEffectiveStatement output) {
+ ret = output;
+ } else {
+ dataTree.exitToDataTree();
+ throw new IllegalArgumentException("Node " + child + " is not a container");
+ }
}
- return schema;
+ schemaStack.push(ret);
+ return ret;
}
public void startAnyxmlNode(final NodeIdentifier name) {
- enterDataTree(name, AnyxmlSchemaNode.class, "anyxml");
+ enterDataTree(name, AnyxmlEffectiveStatement.class, "anyxml");
}
public void startAnydataNode(final NodeIdentifier name) {
- enterDataTree(name, AnydataSchemaNode.class, "anydata");
+ enterDataTree(name, AnydataEffectiveStatement.class, "anydata");
}
- public Object endNode() {
+ public EffectiveStatement<?, ?> endNode() {
final var ret = schemaStack.pop();
// If this is a data tree node, make sure it is updated. Before that, though, we need to check if this is not
// actually listEntry -> list or leafListEntry -> leafList exit.
- if (getParent() != ret) {
+ if (currentStatement() != ret) {
dataTree.exit();
}
return ret;