package org.opendaylight.controller.cluster.datastore.node.utils.transformer;
+import com.google.common.base.Optional;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
public class NormalizedNodeBuilderWrapper {
private final NormalizedNodeContainerBuilder<?,?,?,?> builder;
private final YangInstanceIdentifier.PathArgument identifier;
+ private final Optional<DataSchemaContextNode<?>> schemaNode;
-
- NormalizedNodeBuilderWrapper(NormalizedNodeContainerBuilder<?,?,?,?> builder, YangInstanceIdentifier.PathArgument identifier) {
+ NormalizedNodeBuilderWrapper(NormalizedNodeContainerBuilder<?,?,?,?> builder,
+ YangInstanceIdentifier.PathArgument identifier, Optional<DataSchemaContextNode<?>> schemaNode) {
this.builder = builder;
this.identifier = identifier;
+ this.schemaNode = schemaNode;
}
public NormalizedNodeContainerBuilder builder(){
return identifier;
}
+ public Optional<DataSchemaContextNode<?>> getSchema() {
+ return schemaNode;
+ }
}
package org.opendaylight.controller.cluster.datastore.node.utils.transformer;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import java.io.IOException;
import java.net.URI;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
import javax.xml.transform.dom.DOMSource;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
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.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
*
*/
public class NormalizedNodePruner implements NormalizedNodeStreamWriter {
+ private static final Logger LOG = LoggerFactory.getLogger(NormalizedNodePruner.class);
public static final URI BASE_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
private final SimpleStack<NormalizedNodeBuilderWrapper> stack = new SimpleStack<>();
private NormalizedNode<?,?> normalizedNode;
- private final Set<URI> validNamespaces;
+ private final DataSchemaContextNode<?> nodePathSchemaNode;
private boolean sealed = false;
- public NormalizedNodePruner(SchemaContext schemaContext) {
- this(NormalizedNodePruner.namespaces(schemaContext));
- }
-
- public NormalizedNodePruner(Set<URI> validNamespaces) {
- this.validNamespaces = validNamespaces;
+ public NormalizedNodePruner(YangInstanceIdentifier nodePath, SchemaContext schemaContext) {
+ nodePathSchemaNode = findSchemaNodeForNodePath(nodePath, schemaContext);
}
@SuppressWarnings("unchecked")
checkNotSealed();
- if(!isValidNamespace(nodeIdentifier)){
- return;
- }
-
NormalizedNodeBuilderWrapper parent = stack.peek();
LeafNode<Object> leafNode = Builders.leafBuilder().withNodeIdentifier(nodeIdentifier).withValue(o).build();
if(parent != null) {
- parent.builder().addChild(leafNode);
+ if(hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
+ parent.builder().addChild(leafNode);
+ }
} else {
// If there's no parent node then this is a stand alone LeafNode.
- this.normalizedNode = leafNode;
+ if(nodePathSchemaNode != null) {
+ this.normalizedNode = leafNode;
+ }
+
sealed = true;
}
}
public void leafSetEntryNode(QName name, Object o) throws IOException, IllegalArgumentException {
checkNotSealed();
- if(!isValidNamespace(name)){
- return;
- }
-
NormalizedNodeBuilderWrapper parent = stack.peek();
if(parent != null) {
- parent.builder().addChild(Builders.leafSetEntryBuilder().withValue(o).withNodeIdentifier(
- new YangInstanceIdentifier.NodeWithValue<>(parent.nodeType(), o)).build());
+ if(hasValidSchema(name, parent)) {
+ parent.builder().addChild(Builders.leafSetEntryBuilder().withValue(o).withNodeIdentifier(
+ new YangInstanceIdentifier.NodeWithValue<>(parent.nodeType(), o)).build());
+ }
} else {
// If there's no parent LeafSetNode then this is a stand alone LeafSetEntryNode.
- this.normalizedNode = Builders.leafSetEntryBuilder().withValue(o).withNodeIdentifier(
- new YangInstanceIdentifier.NodeWithValue<>(name, o)).build();
+ if(nodePathSchemaNode != null) {
+ this.normalizedNode = Builders.leafSetEntryBuilder().withValue(o).withNodeIdentifier(
+ new YangInstanceIdentifier.NodeWithValue<>(name, o)).build();
+ }
+
sealed = true;
}
}
public void anyxmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object o) throws IOException, IllegalArgumentException {
checkNotSealed();
- if(!isValidNamespace(nodeIdentifier)){
- return;
- }
-
NormalizedNodeBuilderWrapper parent = stack.peek();
AnyXmlNode anyXmlNode = Builders.anyXmlBuilder().withNodeIdentifier(nodeIdentifier).
withValue((DOMSource) o).build();
if(parent != null) {
- parent.builder().addChild(anyXmlNode);
+ if(hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
+ parent.builder().addChild(anyXmlNode);
+ }
} else {
// If there's no parent node then this is a stand alone AnyXmlNode.
- this.normalizedNode = anyXmlNode;
+ if(nodePathSchemaNode != null) {
+ this.normalizedNode = anyXmlNode;
+ }
+
sealed = true;
}
}
Preconditions.checkState(child != null, "endNode called on an empty stack");
- if(!isValidNamespace(child.identifier())){
+ if(!child.getSchema().isPresent()) {
+ LOG.debug("Schema not found for {}", child.identifier());
return;
}
+
NormalizedNode<?,?> normalizedNode = child.builder().build();
- if(stack.size() > 0){
+ if(stack.size() > 0) {
NormalizedNodeBuilderWrapper parent = stack.peek();
parent.builder().addChild(normalizedNode);
} else {
Preconditions.checkState(!sealed, "Pruner can be used only once");
}
- private boolean isValidNamespace(QName qName){
- return validNamespaces.contains(qName.getNamespace());
- }
-
- private boolean isValidNamespace(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier){
- Set<QName> possibleChildNames = augmentationIdentifier.getPossibleChildNames();
-
- for(QName qName : possibleChildNames){
- if(isValidNamespace(qName)){
- return true;
- }
+ private boolean hasValidSchema(QName name, NormalizedNodeBuilderWrapper parent) {
+ boolean valid = parent.getSchema().isPresent() && parent.getSchema().get().getChild(name) != null;
+ if(!valid) {
+ LOG.debug("Schema not found for {}", name);
}
- return false;
+ return valid;
}
- private boolean isValidNamespace(YangInstanceIdentifier.PathArgument identifier){
- if(identifier instanceof YangInstanceIdentifier.AugmentationIdentifier){
- return isValidNamespace((YangInstanceIdentifier.AugmentationIdentifier) identifier);
+ private NormalizedNodeBuilderWrapper addBuilder(NormalizedNodeContainerBuilder<?,?,?,?> builder,
+ PathArgument identifier){
+ final Optional<DataSchemaContextNode<?>> schemaNode;
+ NormalizedNodeBuilderWrapper parent = stack.peek();
+ if(parent == null) {
+ schemaNode = Optional.fromNullable(nodePathSchemaNode);
+ } else if(parent.getSchema().isPresent()) {
+ schemaNode = Optional.fromNullable(parent.getSchema().get().getChild(identifier));
+ } else {
+ schemaNode = Optional.absent();
}
- return isValidNamespace(identifier.getNodeType());
- }
-
- private NormalizedNodeBuilderWrapper addBuilder(NormalizedNodeContainerBuilder<?,?,?,?> builder, YangInstanceIdentifier.PathArgument identifier){
- NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier);
+ NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier, schemaNode);
stack.push(wrapper);
return wrapper;
}
+ private static DataSchemaContextNode<?> findSchemaNodeForNodePath(YangInstanceIdentifier nodePath,
+ SchemaContext schemaContext) {
+ DataSchemaContextNode<?> schemaNode = DataSchemaContextTree.from(schemaContext).getRoot();
+ for(PathArgument arg : nodePath.getPathArguments()) {
+ schemaNode = schemaNode.getChild(arg);
+ if(schemaNode == null) {
+ break;
+ }
+ }
+
+ return schemaNode;
+ }
+
@VisibleForTesting
static class SimpleStack<E> {
List<E> stack = new LinkedList<>();
return stack.size();
}
}
-
- @VisibleForTesting
- SimpleStack<NormalizedNodeBuilderWrapper> stack(){
- return stack;
- }
-
- public static Set<URI> namespaces(SchemaContext schemaContext){
- Set<URI> namespaces = new HashSet<>(schemaContext.getModules().size());
- namespaces.add(BASE_NAMESPACE);
- for(org.opendaylight.yangtools.yang.model.api.Module module : schemaContext.getModules()){
- namespaces.add(module.getNamespace());
- }
- return namespaces;
- }
}
package org.opendaylight.controller.cluster.datastore.node.utils.transformer;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
+import com.google.common.collect.Sets;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import javax.xml.transform.dom.DOMSource;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeNavigator;
import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeVisitor;
import org.opendaylight.controller.cluster.datastore.util.TestModel;
-import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
public class NormalizedNodePrunerTest {
-
- private NormalizedNodePruner prunerFullSchema;
-
- private NormalizedNodePruner prunerNoAugSchema;
-
- @Mock
- private NormalizedNodeBuilderWrapper normalizedNodeBuilderWrapper;
-
- @Mock
- private NormalizedNodeContainerBuilder normalizedNodeContainerBuilder;
-
- @Mock
- private NormalizedNode<?,?> normalizedNode;
+ private static final SchemaContext NO_TEST_SCHEMA = TestModel.createTestContextWithoutTestSchema();
+ private static final SchemaContext NO_AUG_SCHEMA = TestModel.createTestContextWithoutAugmentationSchema();
+ private static final SchemaContext FULL_SCHEMA = TestModel.createTestContext();
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
- prunerFullSchema = new NormalizedNodePruner(TestModel.createTestContext());
- prunerNoAugSchema = new NormalizedNodePruner(TestModel.createTestContextWithoutAugmentationSchema());
- doReturn(normalizedNodeContainerBuilder).when(normalizedNodeBuilderWrapper).builder();
- doReturn(TestModel.BOOLEAN_LEAF_QNAME).when(normalizedNodeBuilderWrapper).nodeType();
- doReturn(normalizedNode).when(normalizedNodeContainerBuilder).build();
- doReturn(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
+ }
+
+ private NormalizedNodePruner prunerFullSchema(YangInstanceIdentifier path) {
+ return new NormalizedNodePruner(path, FULL_SCHEMA);
+ }
+
+ private NormalizedNodePruner prunerNoAugSchema(YangInstanceIdentifier path) {
+ return new NormalizedNodePruner(path, NO_AUG_SCHEMA);
+ }
+
+ private NormalizedNodePruner prunerNoTestSchema(YangInstanceIdentifier path) {
+ return new NormalizedNodePruner(path, NO_TEST_SCHEMA);
}
@Test
public void testNodesNotPrunedWhenSchemaPresent() throws IOException {
- NormalizedNodePruner pruner = prunerFullSchema;
+ NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH);
NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
@Test(expected = IllegalStateException.class)
public void testReusePruner() throws IOException {
- NormalizedNodePruner pruner = prunerFullSchema;
+ NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH);
NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
@Test
- public void testNodesPrunedWhenAugmentationSchemaNotPresent() throws IOException {
- NormalizedNodePruner pruner = prunerNoAugSchema;
+ public void testNodesPrunedWhenAugmentationSchemaMissing() throws IOException {
+ NormalizedNodePruner pruner = prunerNoAugSchema(TestModel.TEST_PATH);
NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
}
@Test
- public void testNodesPrunedWhenTestSchemaNotPresent() throws IOException {
- NormalizedNodePruner pruner = new NormalizedNodePruner(TestModel.createTestContextWithoutTestSchema());
+ public void testNodesPrunedWhenTestSchemaMissing() throws IOException {
+ NormalizedNodePruner pruner = prunerNoTestSchema(TestModel.TEST_PATH);
NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
}
-
private static int countNodes(NormalizedNode<?,?> normalizedNode, final String namespaceFilter){
if(normalizedNode == null){
return 0;
}
@Test
- public void testLeafNodeHasNoParent() throws IOException {
+ public void testLeafNodeNotPrunedWhenHasNoParent() throws IOException {
+ NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.DESC_QNAME));
NormalizedNode<?, ?> input = Builders.leafBuilder().withNodeIdentifier(
new NodeIdentifier(TestModel.DESC_QNAME)).withValue("test").build();
- NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
assertEquals("normalizedNode", input, actual);
}
@Test
- public void testLeafNodeHasParent() throws IOException {
+ public void testLeafNodePrunedWhenHasAugmentationParentAndSchemaMissing() throws IOException {
+ AugmentationIdentifier augId = new AugmentationIdentifier(Sets.newHashSet(TestModel.AUG_CONT_QNAME));
+ NormalizedNodePruner pruner = prunerFullSchema(YangInstanceIdentifier.builder().
+ node(TestModel.TEST_QNAME).node(TestModel.AUGMENTED_LIST_QNAME).
+ node(TestModel.AUGMENTED_LIST_QNAME).node(augId).build());
LeafNode<Object> child = Builders.leafBuilder().withNodeIdentifier(
- new NodeIdentifier(TestModel.DESC_QNAME)).withValue("test").build();
- NormalizedNode<?, ?> input = Builders.containerBuilder().withNodeIdentifier(
- new NodeIdentifier(TestModel.AUG_CONT_QNAME)).withChild(child).build();
- NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
+ new NodeIdentifier(TestModel.INVALID_QNAME)).withValue("test").build();
+ NormalizedNode<?, ?> input = Builders.augmentationBuilder().withNodeIdentifier(augId).withChild(child).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
- assertEquals("normalizedNode", input, actual);
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertEquals("normalizedNode", Builders.augmentationBuilder().withNodeIdentifier(augId).build(), actual);
}
@Test
- public void testLeafNodeSchemaMissing() throws IOException {
- prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
- prunerNoAugSchema.leafNode(new NodeIdentifier(TestModel.AUG_CONT_QNAME), mock(Object.class));
- verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
+ public void testLeafNodePrunedWhenHasNoParentAndSchemaMissing() throws IOException {
+ NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.INVALID_QNAME));
+ NormalizedNode<?, ?> input = Builders.leafBuilder().withNodeIdentifier(
+ new NodeIdentifier(TestModel.INVALID_QNAME)).withValue("test").build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
+
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertNull(actual);
}
+
@Test
- public void testLeafSetEntryNodeHasNoParent() throws IOException {
- NormalizedNode<?, ?> input = Builders.leafSetEntryBuilder().withValue("test").withNodeIdentifier(
- new NodeWithValue<>(TestModel.FAMILY_QNAME, "test")).build();
- NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
+ public void testLeafSetEntryNodeNotPrunedWhenHasNoParent() throws IOException {
+ NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.SHOE_QNAME));
+ NormalizedNode<?, ?> input = Builders.leafSetEntryBuilder().withValue("puma").withNodeIdentifier(
+ new NodeWithValue<>(TestModel.SHOE_QNAME, "puma")).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
assertEquals("normalizedNode", input, actual);
}
@Test
- public void testLeafSetEntryNodeHasParent() throws IOException {
- LeafSetEntryNode<Object> child = Builders.leafSetEntryBuilder().withValue("test").withNodeIdentifier(
- new NodeWithValue<>(TestModel.FAMILY_QNAME, "test")).build();
+ public void testLeafSetEntryNodeNotPrunedWhenHasParent() throws IOException {
+ NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.SHOE_QNAME));
+ LeafSetEntryNode<Object> child = Builders.leafSetEntryBuilder().withValue("puma").withNodeIdentifier(
+ new NodeWithValue<>(TestModel.SHOE_QNAME, "puma")).build();
NormalizedNode<?, ?> input = Builders.leafSetBuilder().withNodeIdentifier(
- new NodeIdentifier(TestModel.FAMILY_QNAME)).withChild(child).build();
- NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
+ new NodeIdentifier(TestModel.SHOE_QNAME)).withChild(child).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
assertEquals("normalizedNode", input, actual);
}
@Test
- public void testLeafSetEntryNodeSchemaMissing() throws IOException {
- doReturn(new NodeIdentifier(TestModel.AUG_CONT_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
-
- prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
- prunerNoAugSchema.leafSetEntryNode(TestModel.AUG_CONT_QNAME, "");
+ public void testLeafSetEntryNodePrunedWhenHasNoParentAndSchemaMissing() throws IOException {
+ NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.INVALID_QNAME));
+ NormalizedNode<?, ?> input = Builders.leafSetEntryBuilder().withValue("test").withNodeIdentifier(
+ new NodeWithValue<>(TestModel.INVALID_QNAME, "test")).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertNull(actual);
}
@Test
- public void testAnyXMLNodeHasNoParent() throws IOException {
- NormalizedNode<?, ?> input = Builders.anyXmlBuilder().withNodeIdentifier(
- new NodeIdentifier(TestModel.CHILD_NAME_QNAME)).
- withValue(mock(DOMSource.class)).build();
- NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
+ public void testLeafSetEntryNodePrunedWhenHasParentAndSchemaMissing() throws IOException {
+ NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.INVALID_QNAME));
+ LeafSetEntryNode<Object> child = Builders.leafSetEntryBuilder().withValue("test").withNodeIdentifier(
+ new NodeWithValue<>(TestModel.INVALID_QNAME, "test")).build();
+ NormalizedNode<?, ?> input = Builders.leafSetBuilder().withNodeIdentifier(
+ new NodeIdentifier(TestModel.INVALID_QNAME)).withChild(child).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
- assertEquals("normalizedNode", input, actual);
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertNull(actual);
}
@Test
- public void testAnyXMLNodeHasParent() throws IOException {
- AnyXmlNode child = Builders.anyXmlBuilder().withNodeIdentifier(
- new NodeIdentifier(TestModel.CHILD_NAME_QNAME)).
- withValue(mock(DOMSource.class)).build();
- NormalizedNode<?, ?> input = Builders.containerBuilder().withNodeIdentifier(
- new NodeIdentifier(TestModel.AUG_CONT_QNAME)).withChild(child).build();
- NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
+ public void testAnyXMLNodeNotPrunedWhenHasNoParent() throws IOException {
+ NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.ANY_XML_QNAME));
+ NormalizedNode<?, ?> input = Builders.anyXmlBuilder().withNodeIdentifier(
+ new NodeIdentifier(TestModel.ANY_XML_QNAME)).withValue(mock(DOMSource.class)).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
assertEquals("normalizedNode", input, actual);
}
- @Test
- public void testAnyXmlNodeSchemaMissing() throws IOException {
- prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
- prunerNoAugSchema.anyxmlNode(new NodeIdentifier(TestModel.AUG_CONT_QNAME), mock(DOMSource.class));
-
- verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
- }
-
-
- @Test
- public void testLeafSetPushesBuilderToStack() throws IOException {
- prunerFullSchema.startLeafSet(new NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
-
- assertEquals(1, prunerFullSchema.stack().size());
- assertNotNull(prunerFullSchema.stack().peek());
- assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof ListNodeBuilder);
- }
@Test
- public void testStartContainerNodePushesBuilderToStack() throws IOException {
- prunerFullSchema.startContainerNode(new NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
+ public void testAnyXMLNodeNotPrunedWhenHasParent() throws IOException {
+ NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH);
+ AnyXmlNode child = Builders.anyXmlBuilder().withNodeIdentifier(
+ new NodeIdentifier(TestModel.ANY_XML_QNAME)).withValue(mock(DOMSource.class)).build();
+ NormalizedNode<?, ?> input = Builders.containerBuilder().withNodeIdentifier(
+ new NodeIdentifier(TestModel.TEST_QNAME)).withChild(child).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- assertEquals(1, prunerFullSchema.stack().size());
- assertNotNull(prunerFullSchema.stack().peek());
- assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertEquals("normalizedNode", input, actual);
}
@Test
- public void testStartUnkeyedListPushesBuilderToStack() throws IOException {
- prunerFullSchema.startUnkeyedList(new NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
+ public void testAnyXmlNodePrunedWhenHasNoParentAndSchemaMissing() throws IOException {
+ NormalizedNodePruner pruner = prunerNoTestSchema(TestModel.TEST_PATH.node(TestModel.ANY_XML_QNAME));
+ NormalizedNode<?, ?> input = Builders.anyXmlBuilder().withNodeIdentifier(
+ new NodeIdentifier(TestModel.ANY_XML_QNAME)).withValue(mock(DOMSource.class)).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- assertEquals(1, prunerFullSchema.stack().size());
- assertNotNull(prunerFullSchema.stack().peek());
- assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertNull(actual);
}
@Test
- public void testStartUnkeyedListItemPushesBuilderToStack() throws IOException {
- prunerFullSchema.startUnkeyedListItem(new NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
-
- assertEquals(1, prunerFullSchema.stack().size());
- assertNotNull(prunerFullSchema.stack().peek());
- assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
- }
+ public void testInnerContainerNodeWithFullPathPathNotPruned() throws IOException {
+ YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
+ node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
+ node(TestModel.INNER_LIST_QNAME).nodeWithKey(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").
+ node(TestModel.INNER_CONTAINER_QNAME).build();
+ NormalizedNodePruner pruner = prunerFullSchema(path);
- @Test
- public void testStartMapNodePushesBuilderToStack() throws IOException {
- prunerFullSchema.startMapNode(new NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
+ NormalizedNode<?, ?> input = ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME);
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- assertEquals(1, prunerFullSchema.stack().size());
- assertNotNull(prunerFullSchema.stack().peek());
- assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertEquals("normalizedNode", input, actual);
}
@Test
- public void testStartMapEntryNodePushesBuilderToStack() throws IOException {
- prunerFullSchema.startMapEntryNode(
- new NodeIdentifierWithPredicates(TestModel.BOOLEAN_LEAF_QNAME,
- ImmutableMap.<QName, Object>of(TestModel.BOOLEAN_LEAF_QNAME, "value")), 10);
-
- assertEquals(1, prunerFullSchema.stack().size());
- assertNotNull(prunerFullSchema.stack().peek());
- assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
- }
+ public void testInnerContainerNodeWithFullPathPrunedWhenSchemaMissing() throws IOException {
+ YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
+ node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
+ node(TestModel.INNER_LIST_QNAME).nodeWithKey(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").
+ node(TestModel.INVALID_QNAME).build();
+ NormalizedNodePruner pruner = prunerFullSchema(path);
- @Test
- public void testStartOrderedMapNodePushesBuilderToStack() throws IOException {
- prunerFullSchema.startOrderedMapNode(new NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
+ NormalizedNode<?, ?> input = ImmutableNodes.containerNode(TestModel.INVALID_QNAME);
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- assertEquals(1, prunerFullSchema.stack().size());
- assertNotNull(prunerFullSchema.stack().peek());
- assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertNull(actual);
}
@Test
- public void testStartChoiceNodePushesBuilderToStack() throws IOException {
- prunerFullSchema.startChoiceNode(new NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
-
- assertEquals(1, prunerFullSchema.stack().size());
- assertNotNull(prunerFullSchema.stack().peek());
- assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeBuilder);
+ public void testInnerContainerNodeWithParentPathPrunedWhenSchemaMissing() throws IOException {
+ YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
+ node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).build();
+ NormalizedNodePruner pruner = prunerFullSchema(path);
+
+ MapNode innerList = mapNodeBuilder(TestModel.INNER_LIST_QNAME).withChild(mapEntryBuilder(
+ TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").withChild(
+ ImmutableNodes.containerNode(TestModel.INVALID_QNAME)).build()).build();
+ NormalizedNode<?, ?> input = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
+ withChild(innerList).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
+
+ NormalizedNode<?, ?> expected = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
+ withChild(mapNodeBuilder(TestModel.INNER_LIST_QNAME).withChild(mapEntryBuilder(
+ TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").build()).build()).build();
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertEquals("normalizedNode", expected, actual);
}
@Test
- public void testStartAugmentationPushesBuilderToStack() throws IOException {
- prunerFullSchema.startAugmentationNode(new AugmentationIdentifier(ImmutableSet.of(TestModel.AUG_CONT_QNAME)));
+ public void testInnerListNodeWithFullPathNotPruned() throws IOException {
+ YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
+ node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
+ node(TestModel.INNER_LIST_QNAME).build();
+ NormalizedNodePruner pruner = prunerFullSchema(path);
- assertEquals(1, prunerFullSchema.stack().size());
- assertNotNull(prunerFullSchema.stack().peek());
- assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeBuilder);
- }
+ MapNode input = mapNodeBuilder(TestModel.INNER_LIST_QNAME).withChild(mapEntryBuilder(
+ TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").withChild(
+ ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME)).build()).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- @Test(expected = IllegalStateException.class)
- public void testEndNodeWhenNoBuildersOnStack() throws IOException {
- prunerFullSchema.endNode();
- }
-
- @Test
- public void testEndNodeWhenOneBuildersOnStack() throws IOException {
- prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
- prunerFullSchema.endNode();
- assertEquals(normalizedNode, prunerFullSchema.normalizedNode());
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertEquals("normalizedNode", input, actual);
}
@Test
- public void testEndNodeSchemaMissing() throws IOException {
- doReturn(new NodeIdentifier(TestModel.AUG_CONT_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
+ public void testInnerListNodeWithFullPathPrunedWhenSchemaMissing() throws IOException {
+ YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
+ node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
+ node(TestModel.INVALID_QNAME).build();
+ NormalizedNodePruner pruner = prunerFullSchema(path);
- prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
- prunerNoAugSchema.endNode();
+ MapNode input = mapNodeBuilder(TestModel.INVALID_QNAME).withChild(mapEntryBuilder(
+ TestModel.INVALID_QNAME, TestModel.NAME_QNAME, "one").withChild(
+ ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME)).build()).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
- assertEquals(null, prunerNoAugSchema.normalizedNode());
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertNull(actual);
}
@Test
- public void testEndNodeWhenMoreThanOneBuilderOnStack() throws IOException {
- // A little lazy in adding the "parent" builder
- prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
- prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
- prunerFullSchema.endNode();
- assertEquals(null, prunerFullSchema.normalizedNode());
-
- verify(normalizedNodeContainerBuilder).addChild(any(NormalizedNode.class));
+ public void testInnerListNodeWithParentPathPrunedWhenSchemaMissing() throws IOException {
+ YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
+ node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).build();
+ NormalizedNodePruner pruner = prunerFullSchema(path);
+
+ MapNode innerList = mapNodeBuilder(TestModel.INVALID_QNAME).withChild(mapEntryBuilder(
+ TestModel.INVALID_QNAME, TestModel.NAME_QNAME, "one").withChild(
+ ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME)).build()).build();
+ NormalizedNode<?, ?> input = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
+ withChild(innerList).build();
+ NormalizedNodeWriter.forStreamWriter(pruner).write(input);
+
+ NormalizedNode<?, ?> expected = mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1);
+ NormalizedNode<?, ?> actual = pruner.normalizedNode();
+ assertEquals("normalizedNode", expected, actual);
}
private static NormalizedNode<?, ?> createTestContainer() {
new NodeIdentifier(TestModel.BINARY_LEAF_LIST_QNAME)).
withChild(entry1).withChild(entry2).withChild(entry3).build()).
withChild(ImmutableNodes.leafNode(TestModel.SOME_BINARY_DATA_QNAME, new byte[]{1, 2, 3, 4})).
- withChild(Builders.orderedMapBuilder().
- withNodeIdentifier(new NodeIdentifier(TestModel.ORDERED_LIST_QNAME)).
- withChild(ImmutableNodes.mapEntry(TestModel.ORDERED_LIST_ENTRY_QNAME,
- TestModel.ID_QNAME, 11)).build()).
build();
}
}
\ No newline at end of file
import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.io.InputStream;
public static final QName POINTER_QNAME = QName.create(TEST_QNAME, "pointer");
public static final QName SOME_BINARY_DATA_QNAME = QName.create(TEST_QNAME, "some-binary-data");
public static final QName BINARY_LEAF_LIST_QNAME = QName.create(TEST_QNAME, "binary_leaf_list");
- public static final QName SOME_REF_QNAME = QName.create(TEST_QNAME,
- "some-ref");
- public static final QName MYIDENTITY_QNAME = QName.create(TEST_QNAME,
- "myidentity");
- public static final QName SWITCH_FEATURES_QNAME = QName.create(TEST_QNAME,
- "switch-features");
+ public static final QName SOME_REF_QNAME = QName.create(TEST_QNAME, "some-ref");
+ public static final QName MYIDENTITY_QNAME = QName.create(TEST_QNAME, "myidentity");
+ public static final QName SWITCH_FEATURES_QNAME = QName.create(TEST_QNAME, "switch-features");
public static final QName AUGMENTED_LIST_QNAME = QName.create(TEST_QNAME, "augmented-list");
public static final QName AUGMENTED_LIST_ENTRY_QNAME = QName.create(TEST_QNAME, "augmented-list-entry");
- public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME,
- "outer-list");
- public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME,
- "inner-list");
- public static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME,
- "outer-choice");
+ public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
+ public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
+ public static final QName INNER_CONTAINER_QNAME = QName.create(TEST_QNAME, "inner-container");
+ public static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
public static final QName ID_QNAME = QName.create(TEST_QNAME, "id");
public static final QName NAME_QNAME = QName.create(TEST_QNAME, "name");
public static final QName VALUE_QNAME = QName.create(TEST_QNAME, "value");
public static final QName BIGINTEGER_LEAF_QNAME = QName.create(TEST_QNAME, "biginteger-leaf");
public static final QName BIGDECIMAL_LEAF_QNAME = QName.create(TEST_QNAME, "bigdecimal-leaf");
public static final QName ORDERED_LIST_QNAME = QName.create(TEST_QNAME, "ordered-list");
- public static final QName ORDERED_LIST_ENTRY_QNAME = QName.create(TEST_QNAME, "ordered-list-entry");
+ public static final QName ORDERED_LIST_ENTRY_QNAME = QName.create(TEST_QNAME, "ordered-list-leaf");
public static final QName UNKEYED_LIST_QNAME = QName.create(TEST_QNAME, "unkeyed-list");
public static final QName UNKEYED_LIST_ENTRY_QNAME = QName.create(TEST_QNAME, "unkeyed-list-entry");
public static final QName CHOICE_QNAME = QName.create(TEST_QNAME, "choice");
+ public static final QName SHOE_QNAME = QName.create(TEST_QNAME, "shoe");
+ public static final QName ANY_XML_QNAME = QName.create(TEST_QNAME, "any");
+ public static final QName INVALID_QNAME = QName.create(TEST_QNAME, "invalid");
private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
- private static final String DATASTORE_AUG_YANG =
- "/odl-datastore-augmentation.yang";
- private static final String DATASTORE_TEST_NOTIFICATION_YANG =
- "/odl-datastore-test-notification.yang";
+ private static final String DATASTORE_AUG_YANG = "/odl-datastore-augmentation.yang";
+ private static final String DATASTORE_TEST_NOTIFICATION_YANG = "/odl-datastore-test-notification.yang";
- public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier
- .of(TEST_QNAME);
- public static final YangInstanceIdentifier DESC_PATH = YangInstanceIdentifier
- .builder(TEST_PATH).node(DESC_QNAME).build();
+ public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier.of(TEST_QNAME);
+ public static final YangInstanceIdentifier DESC_PATH = YangInstanceIdentifier.
+ builder(TEST_PATH).node(DESC_QNAME).build();
public static final YangInstanceIdentifier OUTER_LIST_PATH =
YangInstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME).build();
+ public static final QName TWO_THREE_QNAME = QName.create(TEST_QNAME, "two");
public static final QName TWO_QNAME = QName.create(TEST_QNAME, "two");
public static final QName THREE_QNAME = QName.create(TEST_QNAME, "three");
private static final Short SHORT_ID = 1;
private static final Byte BYTE_ID = 1;
// Family specific constants
- public static final QName FAMILY_QNAME =
- QName
- .create(
- "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:notification-test",
- "2014-04-17", "family");
- public static final QName CHILDREN_QNAME = QName.create(FAMILY_QNAME,
- "children");
- public static final QName GRAND_CHILDREN_QNAME = QName.create(FAMILY_QNAME,
- "grand-children");
- public static final QName CHILD_NUMBER_QNAME = QName.create(FAMILY_QNAME,
- "child-number");
- public static final QName CHILD_NAME_QNAME = QName.create(FAMILY_QNAME,
- "child-name");
- public static final QName GRAND_CHILD_NUMBER_QNAME = QName.create(
- FAMILY_QNAME, "grand-child-number");
- public static final QName GRAND_CHILD_NAME_QNAME = QName.create(FAMILY_QNAME,
- "grand-child-name");
-
- public static final YangInstanceIdentifier FAMILY_PATH =
- YangInstanceIdentifier.of(FAMILY_QNAME);
+ public static final QName FAMILY_QNAME = QName.create(
+ "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:notification-test", "2014-04-17", "family");
+ public static final QName CHILDREN_QNAME = QName.create(FAMILY_QNAME, "children");
+ public static final QName GRAND_CHILDREN_QNAME = QName.create(FAMILY_QNAME, "grand-children");
+ public static final QName CHILD_NUMBER_QNAME = QName.create(FAMILY_QNAME, "child-number");
+ public static final QName CHILD_NAME_QNAME = QName.create(FAMILY_QNAME, "child-name");
+ public static final QName GRAND_CHILD_NUMBER_QNAME = QName.create(FAMILY_QNAME, "grand-child-number");
+ public static final QName GRAND_CHILD_NAME_QNAME = QName.create(FAMILY_QNAME,"grand-child-name");
+
+ public static final YangInstanceIdentifier FAMILY_PATH = YangInstanceIdentifier.of(FAMILY_QNAME);
public static final YangInstanceIdentifier FAMILY_DESC_PATH =
YangInstanceIdentifier.builder(FAMILY_PATH).node(DESC_QNAME).build();
public static final YangInstanceIdentifier CHILDREN_PATH =
public static DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> createBaseTestContainerBuilder() {
// Create a list of shoes
// This is to test leaf list entry
- final LeafSetEntryNode<Object> nike =
- ImmutableLeafSetEntryNodeBuilder
- .create()
- .withNodeIdentifier(
- new NodeWithValue<>(QName.create(
- TEST_QNAME, "shoe"), "nike")).withValue("nike").build();
+ final LeafSetEntryNode<Object> nike = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
+ new NodeWithValue<>(SHOE_QNAME, "nike")).withValue("nike").build();
- final LeafSetEntryNode<Object> puma =
- ImmutableLeafSetEntryNodeBuilder
- .create()
- .withNodeIdentifier(
- new NodeWithValue<>(QName.create(
- TEST_QNAME, "shoe"), "puma")).withValue("puma").build();
-
- final LeafSetNode<Object> shoes =
- ImmutableLeafSetNodeBuilder
- .create()
- .withNodeIdentifier(
- new NodeIdentifier(QName.create(
- TEST_QNAME, "shoe"))).withChild(nike).withChild(puma)
- .build();
+ final LeafSetEntryNode<Object> puma = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
+ new NodeWithValue<>(SHOE_QNAME, "puma")).withValue("puma").build();
+ final LeafSetNode<Object> shoes = ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(
+ new NodeIdentifier(SHOE_QNAME)).withChild(nike).withChild(puma).build();
// Test a leaf-list where each entry contains an identity
final LeafSetEntryNode<Object> cap1 =
// Create unkeyed list entry
UnkeyedListEntryNode unkeyedListEntry =
- Builders.unkeyedListEntryBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(UNKEYED_LIST_ENTRY_QNAME)).
+ Builders.unkeyedListEntryBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(UNKEYED_LIST_QNAME)).
withChild(ImmutableNodes.leafNode(NAME_QNAME, "unkeyed-entry-name")).build();
// Create YangInstanceIdentifier with all path arg types.
.withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(UNKEYED_LIST_QNAME))
.withChild(unkeyedListEntry).build())
.withChild(Builders.choiceBuilder()
- .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_QNAME))
- .withChild(ImmutableNodes.leafNode(DESC_QNAME, LONG_ID)).build())
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TWO_THREE_QNAME))
+ .withChild(ImmutableNodes.leafNode(TWO_QNAME, "two")).build())
.withChild(Builders.orderedMapBuilder().
- withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(DESC_QNAME)).
- withValue(ImmutableList.<MapEntryNode>builder().add(augMapEntry).build()).build())
- // .withChild(augmentationNode)
+ withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(ORDERED_LIST_QNAME)).
+ withValue(ImmutableList.<MapEntryNode>builder().add(
+ mapEntryBuilder(ORDERED_LIST_QNAME, ORDERED_LIST_ENTRY_QNAME, "1").build(),
+ mapEntryBuilder(ORDERED_LIST_QNAME, ORDERED_LIST_ENTRY_QNAME, "2").build()).build()).build())
.withChild(shoes)
.withChild(numbers)
.withChild(switchFeatures)
.create()
.withNodeIdentifier(
new YangInstanceIdentifier.NodeIdentifierWithPredicates(
- AUGMENTED_LIST_ENTRY_QNAME, ID_QNAME, id))
+ AUGMENTED_LIST_QNAME, ID_QNAME, id))
.withChild(ImmutableNodes.leafNode(ID_QNAME, id))
.withChild(augmentationNode).build();
}
leaf desc {
type string;
}
+
+ leaf short-leaf {
+ type uint16;
+ }
+
+ leaf biginteger-leaf {
+ type uint64;
+ }
+
+ leaf bigdecimal-leaf {
+ type decimal64 {
+ fraction-digits 2;
+ }
+ }
+
+ leaf boolean-leaf {
+ type boolean;
+ }
+
+ leaf byte-leaf {
+ type uint8;
+ }
+
+ list unkeyed-list {
+ leaf name {
+ type string;
+ }
+ }
+
+ choice outer-choice {
+ case one {
+ leaf one {
+ type string;
+ }
+ }
+ case two-three {
+ leaf two {
+ type string;
+ }
+ leaf three {
+ type string;
+ }
+ }
+ }
+
+ list ordered-list {
+ key ordered-list-leaf;
+ ordered-by user;
+
+ leaf ordered-list-leaf {
+ type string;
+ }
+ }
+
list outer-list {
key id;
leaf id {
type uint16;
}
- choice outer-choice {
- case one {
- leaf one {
- type string;
- }
- }
- case two-three {
- leaf two {
- type string;
- }
- leaf three {
- type string;
- }
- }
- }
- list inner-list {
+
+ list inner-list {
key name;
leaf name {
type string;
leaf value {
type string;
}
+
+ container inner-container {
+ }
}
}
type binary;
}
-
+ anyxml any {
+ }
}
}
--- /dev/null
+org.slf4j.simpleLogger.showDateTime=true
+org.slf4j.simpleLogger.dateTimeFormat=hh:mm:ss,S a
+org.slf4j.simpleLogger.logFile=System.out
+org.slf4j.simpleLogger.showShortLogName=true
+org.slf4j.simpleLogger.levelInBrackets=true
+org.slf4j.simpleLogger.log.org.opendaylight.controller.cluster=debug
import com.google.common.base.Preconditions;
import java.io.IOException;
-import java.net.URI;
-import java.util.Set;
import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
-import org.opendaylight.controller.cluster.datastore.node.utils.transformer.NormalizedNodePruner;
import org.opendaylight.controller.cluster.datastore.utils.PruningDataTreeModification;
import org.opendaylight.controller.cluster.datastore.utils.SerializationUtils;
import org.opendaylight.controller.cluster.raft.RaftActorRecoveryCohort;
* @author Thomas Pantelis
*/
class ShardRecoveryCoordinator implements RaftActorRecoveryCohort {
- private static final YangInstanceIdentifier ROOT = YangInstanceIdentifier.builder().build();
private final ShardDataTree store;
private final String shardName;
private final Logger log;
- private final Set<URI> validNamespaces;
+ private final SchemaContext schemaContext;
private PruningDataTreeModification transaction;
private int size;
private final byte[] restoreFromSnapshot;
this.restoreFromSnapshot = restoreFromSnapshot;
this.shardName = shardName;
this.log = log;
- this.validNamespaces = NormalizedNodePruner.namespaces(schemaContext);
+ this.schemaContext = schemaContext;
}
@Override
public void startLogRecoveryBatch(int maxBatchSize) {
log.debug("{}: starting log recovery batch with max size {}", shardName, maxBatchSize);
- transaction = new PruningDataTreeModification(store.newModification(), validNamespaces);
+ transaction = new PruningDataTreeModification(store.newModification(), store.getDataTree(), schemaContext);
size = 0;
}
}
private void commitTransaction(PruningDataTreeModification tx) throws DataValidationFailedException {
- store.commit(tx.getDelegate());
+ store.commit(tx.getResultingModification());
}
/**
log.debug("{}: Applying recovered snapshot", shardName);
final NormalizedNode<?, ?> node = SerializationUtils.deserializeNormalizedNode(snapshotBytes);
- final PruningDataTreeModification tx = new PruningDataTreeModification(store.newModification(), validNamespaces);
- tx.write(ROOT, node);
+ final PruningDataTreeModification tx = new PruningDataTreeModification(store.newModification(),
+ store.getDataTree(), schemaContext);
+ tx.write(YangInstanceIdentifier.EMPTY, node);
try {
commitTransaction(tx);
} catch (DataValidationFailedException e) {
private DataTreeModification dataTreeModification() {
DataTreeModification dataTreeModification = transaction;
if(transaction instanceof PruningDataTreeModification){
- dataTreeModification = ((PruningDataTreeModification) transaction).getDelegate();
+ dataTreeModification = ((PruningDataTreeModification) transaction).getResultingModification();
}
return dataTreeModification;
}
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import java.io.IOException;
-import java.net.URI;
-import java.util.Set;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import javax.annotation.Nonnull;
import org.opendaylight.controller.cluster.datastore.node.utils.transformer.NormalizedNodePruner;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+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.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModificationCursor;
import org.opendaylight.yangtools.yang.data.impl.schema.tree.SchemaValidationFailedException;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PruningDataTreeModification implements DataTreeModification {
private static final Logger LOG = LoggerFactory.getLogger(PruningDataTreeModification.class);
- private final DataTreeModification delegate;
- private final Set<URI> validNamespaces;
+ private DataTreeModification delegate;
+ private final SchemaContext schemaContext;
+ private final DataTree dataTree;
- public PruningDataTreeModification(DataTreeModification delegate, Set<URI> validNamespaces) {
+ public PruningDataTreeModification(DataTreeModification delegate, DataTree dataTree, SchemaContext schemaContext) {
this.delegate = delegate;
- this.validNamespaces = validNamespaces;
+ this.dataTree = dataTree;
+ this.schemaContext = schemaContext;
}
@Override
delegate.merge(yangInstanceIdentifier, normalizedNode);
}
} catch (SchemaValidationFailedException e){
- if(!isValidYangInstanceIdentifier(yangInstanceIdentifier)){
- LOG.warn("Invalid node identifier {} ignoring merge", yangInstanceIdentifier);
- return;
- }
+ LOG.warn("Node at path {} was pruned during merge due to validation error: {}",
+ yangInstanceIdentifier, e.getMessage());
pruneAndMergeNode(yangInstanceIdentifier, normalizedNode);
}
}
private void pruneAndMergeNode(YangInstanceIdentifier yangInstanceIdentifier, NormalizedNode<?, ?> normalizedNode) {
- LOG.warn("Node at path : {} was pruned during merge", yangInstanceIdentifier);
-
- NormalizedNode<?,?> pruned = pruneNormalizedNode(normalizedNode);
+ NormalizedNode<?,?> pruned = pruneNormalizedNode(yangInstanceIdentifier, normalizedNode);
if(pruned != null) {
delegate.merge(yangInstanceIdentifier, pruned);
delegate.write(yangInstanceIdentifier, normalizedNode);
}
} catch (SchemaValidationFailedException e){
- if(!isValidYangInstanceIdentifier(yangInstanceIdentifier)){
- LOG.warn("Invalid node identifier {} ignoring write", yangInstanceIdentifier);
- return;
- }
+ LOG.warn("Node at path : {} was pruned during write due to validation error: {}",
+ yangInstanceIdentifier, e.getMessage());
pruneAndWriteNode(yangInstanceIdentifier, normalizedNode);
}
}
private void pruneAndWriteNode(YangInstanceIdentifier yangInstanceIdentifier, NormalizedNode<?, ?> normalizedNode) {
- LOG.warn("Node at path : {} was pruned during write", yangInstanceIdentifier);
-
- NormalizedNode<?,?> pruned = pruneNormalizedNode(normalizedNode);
+ NormalizedNode<?,?> pruned = pruneNormalizedNode(yangInstanceIdentifier, normalizedNode);
if(pruned != null) {
delegate.write(yangInstanceIdentifier, pruned);
@Override
public void ready() {
- delegate.ready();
+ try {
+ delegate.ready();
+ } catch (SchemaValidationFailedException e) {
+ DataTreeModification newModification = dataTree.takeSnapshot().newModification();
+ delegate.applyToCursor(new PruningDataTreeModificationCursor(newModification, this));
+
+ delegate = newModification;
+ delegate.ready();
+ }
}
@Override
@Override
public DataTreeModification newModification() {
- return new PruningDataTreeModification(delegate.newModification(), validNamespaces);
+ return new PruningDataTreeModification(delegate.newModification(), dataTree, schemaContext);
}
@VisibleForTesting
- NormalizedNode<?, ?> pruneNormalizedNode(NormalizedNode<?,?> input){
- NormalizedNodePruner pruner = new NormalizedNodePruner(validNamespaces);
+ NormalizedNode<?, ?> pruneNormalizedNode(YangInstanceIdentifier path, NormalizedNode<?,?> input) {
+ NormalizedNodePruner pruner = new NormalizedNodePruner(path, schemaContext);
try {
NormalizedNodeWriter.forStreamWriter(pruner).write(input);
} catch (IOException ioe) {
return pruner.normalizedNode();
}
- public DataTreeModification getDelegate(){
+ public DataTreeModification getResultingModification(){
return delegate;
}
- private boolean isValidYangInstanceIdentifier(YangInstanceIdentifier instanceIdentifier){
- for(YangInstanceIdentifier.PathArgument pathArgument : instanceIdentifier.getPathArguments()){
- if(!validNamespaces.contains(pathArgument.getNodeType().getNamespace())){
- return false;
+ private static class PruningDataTreeModificationCursor implements DataTreeModificationCursor {
+ private final Deque<YangInstanceIdentifier> stack = new ArrayDeque<>();
+ private final DataTreeModification toModification;
+ private final PruningDataTreeModification pruningModification;
+
+ PruningDataTreeModificationCursor(DataTreeModification toModification,
+ PruningDataTreeModification pruningModification) {
+ this.toModification = toModification;
+ this.pruningModification = pruningModification;
+ stack.push(YangInstanceIdentifier.EMPTY);
+ }
+
+ @Override
+ public void write(PathArgument child, NormalizedNode<?, ?> data) {
+ YangInstanceIdentifier path = stack.peek().node(child);
+ NormalizedNode<?, ?> prunedNode = pruningModification.pruneNormalizedNode(path, data);
+ if(prunedNode != null) {
+ toModification.write(path, prunedNode);
}
}
- return true;
- }
+ @Override
+ public void merge(PathArgument child, NormalizedNode<?, ?> data) {
+ YangInstanceIdentifier path = stack.peek().node(child);
+ NormalizedNode<?, ?> prunedNode = pruningModification.pruneNormalizedNode(path, data);
+ if(prunedNode != null) {
+ toModification.merge(path, prunedNode);
+ }
+ }
+ @Override
+ public void delete(PathArgument child) {
+ try {
+ toModification.delete(stack.peek().node(child));
+ } catch(SchemaValidationFailedException e) {
+ // Ignoring since we would've already logged this in the call to the original modification.
+ }
+ }
+
+ @Override
+ public void enter(@Nonnull final PathArgument child) {
+ stack.push(stack.peek().node(child));
+ }
+
+ @Override
+ public void enter(@Nonnull final PathArgument... path) {
+ for (PathArgument arg : path) {
+ enter(arg);
+ }
+ }
+
+ @Override
+ public void enter(@Nonnull final Iterable<PathArgument> path) {
+ for (PathArgument arg : path) {
+ enter(arg);
+ }
+ }
+
+ @Override
+ public void exit() {
+ stack.pop();
+ }
+
+ @Override
+ public void exit(final int depth) {
+ Preconditions.checkArgument(depth < stack.size(), "Stack holds only %s elements, cannot exit %s levels", stack.size(), depth);
+ for (int i = 0; i < depth; ++i) {
+ stack.pop();
+ }
+ }
+
+ @Override
+ public Optional<NormalizedNode<?, ?>> readNode(@Nonnull final PathArgument child) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void close() {
+ }
+ }
}
final DataTreeCandidateNode mockCandidateNode = mock(DataTreeCandidateNode.class, name + "-node");
doReturn(ModificationType.WRITE).when(mockCandidateNode).getModificationType();
doReturn(Optional.of(ImmutableNodes.containerNode(CarsModel.CARS_QNAME))).when(mockCandidateNode).getDataAfter();
- doReturn(YangInstanceIdentifier.builder().build()).when(mockCandidate).getRootPath();
+ doReturn(CarsModel.BASE_PATH).when(mockCandidate).getRootPath();
doReturn(mockCandidateNode).when(mockCandidate).getRootNode();
return mockCandidate;
}
}
@Test
- public void testReadyWithImmediateCommit() throws Exception{
+ public void testReadyWithReadWriteImmediateCommit() throws Exception{
testReadyWithImmediateCommit(true);
+ }
+
+ @Test
+ public void testReadyWithWriteOnlyImmediateCommit() throws Exception{
testReadyWithImmediateCommit(false);
}
}
@Test
- public void testCommitWithPersistenceDisabled() throws Throwable {
+ public void testReadWriteCommitWithPersistenceDisabled() throws Throwable {
+ testCommitWithPersistenceDisabled(true);
+ }
+
+ @Test
+ public void testWriteOnlyCommitWithPersistenceDisabled() throws Throwable {
testCommitWithPersistenceDisabled(true);
- testCommitWithPersistenceDisabled(false);
}
private void testCommitWithPersistenceDisabled(final boolean readWrite) throws Throwable {
}
@Test
- public void testCommitWhenTransactionHasNoModifications() {
+ public void testReadWriteCommitWhenTransactionHasNoModifications() {
testCommitWhenTransactionHasNoModifications(true);
+ }
+
+ @Test
+ public void testWriteOnlyCommitWhenTransactionHasNoModifications() {
testCommitWhenTransactionHasNoModifications(false);
}
}
@Test
- public void testCommitWhenTransactionHasModifications() {
+ public void testReadWriteCommitWhenTransactionHasModifications() {
testCommitWhenTransactionHasModifications(true);
+ }
+
+ @Test
+ public void testWriteOnlyCommitWhenTransactionHasModifications() {
testCommitWhenTransactionHasModifications(false);
}
package org.opendaylight.controller.cluster.datastore.utils;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import java.net.URI;
-import java.util.Set;
+import static org.opendaylight.controller.md.cluster.datastore.model.CompositeModel.AUG_CONTAINER;
+import static org.opendaylight.controller.md.cluster.datastore.model.CompositeModel.AUG_INNER_CONTAINER;
+import static org.opendaylight.controller.md.cluster.datastore.model.CompositeModel.AUG_QNAME;
+import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.NAME_QNAME;
+import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.TEST_QNAME;
+import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.innerNode;
+import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerNode;
+import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerNodeEntry;
+import com.google.common.base.Optional;
+import com.google.common.reflect.Reflection;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.cluster.datastore.ShardDataTree;
import org.opendaylight.controller.md.cluster.datastore.model.CarsModel;
+import org.opendaylight.controller.md.cluster.datastore.model.PeopleModel;
+import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateTip;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModificationCursor;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.TipProducingDataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
import org.opendaylight.yangtools.yang.data.impl.schema.tree.SchemaValidationFailedException;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
public class PruningDataTreeModificationTest {
+ static final SchemaContext SCHEMA_CONTEXT = SchemaContextHelper.select(SchemaContextHelper.CARS_YANG,
+ SchemaContextHelper.ODL_DATASTORE_TEST_YANG);
- @Mock
- DataTreeModification delegate;
-
- @Mock
- Set<URI> validNamespaces;
+ static final QName INVALID_TEST_QNAME = QName.create(TestModel.TEST_QNAME, "invalid");
+ static final YangInstanceIdentifier INVALID_TEST_PATH = YangInstanceIdentifier.of(INVALID_TEST_QNAME);
@Mock
- NormalizedNode<?,?> prunedNormalizedNode;
+ private DataTreeModification mockModification;
- PruningDataTreeModification pruningDataTreeModification;
+ private TipProducingDataTree dataTree;
+ private DataTreeModification realModification;
+ private DataTreeModification proxyModification;
+ private PruningDataTreeModification pruningDataTreeModification;
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
- pruningDataTreeModification = new PruningDataTreeModification(delegate, validNamespaces) {
+
+ dataTree = InMemoryDataTreeFactory.getInstance().create(TreeType.CONFIGURATION);
+ dataTree.setSchemaContext(SCHEMA_CONTEXT);
+
+ realModification = dataTree.takeSnapshot().newModification();
+ proxyModification = Reflection.newProxy(DataTreeModification.class, new InvocationHandler() {
@Override
- NormalizedNode<?, ?> pruneNormalizedNode(NormalizedNode<?, ?> input) {
- return prunedNormalizedNode;
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ try {
+ method.invoke(mockModification, args);
+ return method.invoke(realModification, args);
+ } catch (InvocationTargetException e) {
+ throw e.getCause();
+ }
}
- };
+ });
+
+ pruningDataTreeModification = new PruningDataTreeModification(proxyModification, dataTree, SCHEMA_CONTEXT);
}
@Test
public void testDelete(){
pruningDataTreeModification.delete(CarsModel.BASE_PATH);
- verify(delegate).delete(CarsModel.BASE_PATH);
+ verify(mockModification, times(1)).delete(CarsModel.BASE_PATH);
}
@Test
public void testDeleteOnException(){
YangInstanceIdentifier path = CarsModel.BASE_PATH;
- doThrow(SchemaValidationFailedException.class).when(delegate).delete(path);
+ doThrow(SchemaValidationFailedException.class).when(mockModification).delete(path);
pruningDataTreeModification.delete(path);
- verify(delegate, times(1)).delete(path);
+ verify(mockModification, times(1)).delete(path);
}
YangInstanceIdentifier path = CarsModel.BASE_PATH;
pruningDataTreeModification.merge(path, normalizedNode);
- verify(delegate, times(1)).merge(path, normalizedNode);
+ verify(mockModification, times(1)).merge(path, normalizedNode);
}
@Test
- public void testMergeOnException(){
- NormalizedNode<?, ?> normalizedNode = CarsModel.create();
- YangInstanceIdentifier path = CarsModel.BASE_PATH;
+ public void testMergeWithInvalidNamespace() throws DataValidationFailedException{
+ NormalizedNode<?, ?> normalizedNode = PeopleModel.emptyContainer();
+ YangInstanceIdentifier path = PeopleModel.BASE_PATH;
+
+ pruningDataTreeModification.merge(path, normalizedNode);
+
+ verify(mockModification, times(1)).merge(path, normalizedNode);
- doThrow(SchemaValidationFailedException.class).when(delegate).merge(path, normalizedNode);
- doReturn(true).when(validNamespaces).contains(any(YangInstanceIdentifier.PathArgument.class));
+ DataTreeCandidateTip candidate = getCandidate();
+ assertEquals("getModificationType", ModificationType.UNMODIFIED, candidate.getRootNode().getModificationType());
+ }
+
+ @Test
+ public void testMergeWithInvalidChildNodeNames() throws DataValidationFailedException{
+ ContainerNode augContainer = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+ new YangInstanceIdentifier.NodeIdentifier(AUG_CONTAINER)).withChild(
+ ImmutableNodes.containerNode(AUG_INNER_CONTAINER)).build();
+
+ DataContainerChild<?, ?> outerNode = outerNode(outerNodeEntry(1, innerNode("one", "two")));
+ ContainerNode normalizedNode = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+ new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME)).withChild(outerNode).withChild(augContainer).
+ withChild(ImmutableNodes.leafNode(AUG_QNAME, "aug")).build();
+
+ YangInstanceIdentifier path = TestModel.TEST_PATH;
pruningDataTreeModification.merge(path, normalizedNode);
- verify(delegate, times(1)).merge(path, normalizedNode);
- verify(delegate, times(1)).merge(path, prunedNormalizedNode);
+ dataTree.commit(getCandidate());
+
+ ContainerNode prunedNode = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+ new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME)).withChild(outerNode).build();
+
+ Optional<NormalizedNode<?, ?>> actual = dataTree.takeSnapshot().readNode(path);
+ assertEquals("After pruning present", true, actual.isPresent());
+ assertEquals("After pruning", prunedNode, actual.get());
+ }
+
+ @Test
+ public void testMergeWithValidNamespaceAndInvalidNodeName() throws DataValidationFailedException{
+ NormalizedNode<?, ?> normalizedNode = ImmutableNodes.containerNode(INVALID_TEST_QNAME);
+ YangInstanceIdentifier path = INVALID_TEST_PATH;
+
+ pruningDataTreeModification.merge(path, normalizedNode);
+
+ verify(mockModification, times(1)).merge(path, normalizedNode);
+
+ DataTreeCandidateTip candidate = getCandidate();
+ assertEquals("getModificationType", ModificationType.UNMODIFIED, candidate.getRootNode().getModificationType());
}
@Test
YangInstanceIdentifier path = CarsModel.BASE_PATH;
pruningDataTreeModification.write(path, normalizedNode);
- verify(delegate, times(1)).write(path, normalizedNode);
+ verify(mockModification, times(1)).write(path, normalizedNode);
}
@Test
- public void testWriteOnException(){
- NormalizedNode<?, ?> normalizedNode = CarsModel.create();
- YangInstanceIdentifier path = CarsModel.BASE_PATH;
+ public void testWriteRootNode() throws Exception{
+ ShardDataTree shardDataTree = new ShardDataTree(SCHEMA_CONTEXT, TreeType.CONFIGURATION);
+ DataTreeModification mod = shardDataTree.newModification();
- doThrow(SchemaValidationFailedException.class).when(delegate).write(path, normalizedNode);
- doReturn(true).when(validNamespaces).contains(any(YangInstanceIdentifier.PathArgument.class));
+ mod.write(CarsModel.BASE_PATH, CarsModel.create());
+ shardDataTree.commit(mod);
+
+ NormalizedNode<?, ?> normalizedNode = shardDataTree.readNode(YangInstanceIdentifier.EMPTY).get();
+ pruningDataTreeModification.write(YangInstanceIdentifier.EMPTY, normalizedNode);
+ dataTree.commit(getCandidate());
+
+ Optional<NormalizedNode<?, ?>> actual = dataTree.takeSnapshot().readNode(YangInstanceIdentifier.EMPTY);
+ assertEquals("Root present", true, actual.isPresent());
+ assertEquals("Root node", normalizedNode, actual.get());
+
+ }
+
+ @Test
+ public void testWriteRootNodeWithInvalidChild() throws Exception{
+ ShardDataTree shardDataTree = new ShardDataTree(SCHEMA_CONTEXT, TreeType.CONFIGURATION);
+ NormalizedNode<?, ?> root = shardDataTree.readNode(YangInstanceIdentifier.EMPTY).get();
+
+ NormalizedNode<?, ?> normalizedNode = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+ new YangInstanceIdentifier.NodeIdentifier(root.getNodeType())).withChild(
+ ImmutableNodes.containerNode(AUG_CONTAINER)).build();
+ pruningDataTreeModification.write(YangInstanceIdentifier.EMPTY, normalizedNode);
+ dataTree.commit(getCandidate());
+
+ Optional<NormalizedNode<?, ?>> actual = dataTree.takeSnapshot().readNode(YangInstanceIdentifier.EMPTY);
+ assertEquals("Root present", true, actual.isPresent());
+ assertEquals("Root node", root, actual.get());
+
+ }
+
+ @Test
+ public void testWriteWithInvalidNamespace() throws DataValidationFailedException{
+ NormalizedNode<?, ?> normalizedNode = PeopleModel.emptyContainer();
+ YangInstanceIdentifier path = PeopleModel.BASE_PATH;
+
+ pruningDataTreeModification.write(path, normalizedNode);
+
+ verify(mockModification, times(1)).write(path, normalizedNode);
+
+ DataTreeCandidateTip candidate = getCandidate();
+ assertEquals("getModificationType", ModificationType.UNMODIFIED, candidate.getRootNode().getModificationType());
+ }
+
+ @Test
+ public void testWriteWithInvalidChildNodeNames() throws DataValidationFailedException{
+ ContainerNode augContainer = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+ new YangInstanceIdentifier.NodeIdentifier(AUG_CONTAINER)).withChild(
+ ImmutableNodes.containerNode(AUG_INNER_CONTAINER)).build();
+
+ DataContainerChild<?, ?> outerNode = outerNode(outerNodeEntry(1, innerNode("one", "two")));
+ ContainerNode normalizedNode = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+ new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME)).withChild(outerNode).withChild(augContainer).
+ withChild(ImmutableNodes.leafNode(AUG_QNAME, "aug")).
+ withChild(ImmutableNodes.leafNode(NAME_QNAME, "name")).build();
+
+ YangInstanceIdentifier path = TestModel.TEST_PATH;
pruningDataTreeModification.write(path, normalizedNode);
- verify(delegate, times(1)).write(path, normalizedNode);
- verify(delegate, times(1)).write(path, prunedNormalizedNode);
+ dataTree.commit(getCandidate());
+
+ ContainerNode prunedNode = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+ new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME)).withChild(outerNode).
+ withChild(ImmutableNodes.leafNode(NAME_QNAME, "name")).build();
+
+ Optional<NormalizedNode<?, ?>> actual = dataTree.takeSnapshot().readNode(path);
+ assertEquals("After pruning present", true, actual.isPresent());
+ assertEquals("After pruning", prunedNode, actual.get());
}
@Test
public void testReady(){
pruningDataTreeModification.ready();
- verify(delegate).ready();
+ verify(mockModification).ready();
}
@Test
DataTreeModificationCursor dataTreeModificationCursor = mock(DataTreeModificationCursor.class);
pruningDataTreeModification.applyToCursor(dataTreeModificationCursor);
- verify(delegate).applyToCursor(dataTreeModificationCursor);
+ verify(mockModification).applyToCursor(dataTreeModificationCursor);
}
@Test
public void testReadNode(){
pruningDataTreeModification.readNode(CarsModel.BASE_PATH);
- verify(delegate).readNode(CarsModel.BASE_PATH);
+ verify(mockModification).readNode(CarsModel.BASE_PATH);
}
@Test
public void testNewModification(){
+ realModification.ready();
DataTreeModification dataTreeModification = pruningDataTreeModification.newModification();
assertTrue("new modification not of type PruningDataTreeModification", dataTreeModification instanceof PruningDataTreeModification);
}
+
+ private DataTreeCandidateTip getCandidate() throws DataValidationFailedException {
+ pruningDataTreeModification.ready();
+ DataTreeModification mod = pruningDataTreeModification.getResultingModification();
+ mod = mod == proxyModification ? realModification : mod;
+ dataTree.validate(mod);
+ DataTreeCandidateTip candidate = dataTree.prepare(mod);
+ return candidate;
+ }
}
\ No newline at end of file
package org.opendaylight.controller.md.cluster.datastore.model;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
-
public class CompositeModel {
public static final QName TEST_QNAME = QName.create(
"urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:aug",
"2014-03-13", "name");
+ public static final QName AUG_CONTAINER = QName.create(AUG_QNAME, "aug-container");
+ public static final QName AUG_INNER_CONTAINER = QName.create(AUG_QNAME, "aug-inner-container");
public static final QName DESC_QNAME = QName.create(TEST_QNAME, "desc");
public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME,
"outer-list");
}
}
+ augment "/test:test" {
+ container aug-container {
+ container aug-inner-container {
+ }
+ }
+ }
}
\ No newline at end of file