/* * Copyright (c) 2015 Pantheon Technologies 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.impl.schema.tree; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; import java.io.File; import java.net.URI; import org.junit.Before; import org.junit.Test; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; 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.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; 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.api.CollectionNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; public class Bug4295Test { private TipProducingDataTree inMemoryDataTree; private SchemaContext context; private QName root; private QName subRoot; private QName outerList; private QName innerList; private QName oId; private QName iId; private QName oLeaf; private QName iLeaf; private QNameModule foo; @Before public void init() throws Exception { final File resourceFile = new File(Bug4295Test.class.getResource("/bug-4295/foo.yang") .toURI()); context = YangParserTestUtils.parseYangSources(resourceFile); foo = QNameModule.create(new URI("foo"), SimpleDateFormatUtil.getRevisionFormat().parse("1970-01-01")); root = QName.create(foo, "root"); subRoot = QName.create(foo, "sub-root"); outerList = QName.create(foo, "outer-list"); innerList = QName.create(foo, "inner-list"); oId = QName.create(foo, "o-id"); iId = QName.create(foo, "i-id"); oLeaf = QName.create(foo, "o"); iLeaf = QName.create(foo, "i"); inMemoryDataTree = InMemoryDataTreeFactory.getInstance().create(TreeType.OPERATIONAL); inMemoryDataTree.setSchemaContext(context); } @Test public void test() throws DataValidationFailedException { firstModification(); secondModification(1); secondModification(2); secondModification(3); } private void firstModification() throws DataValidationFailedException { /* MERGE */ MapNode outerListNode = ImmutableNodes.mapNodeBuilder().withNodeIdentifier(NodeIdentifier.create(outerList)) .withChild(createOuterListEntry("1", "o-1")) .withChild(createOuterListEntry("2", "o-2")) .withChild(createOuterListEntry("3", "o-3")) .build(); ContainerNode rootContainerNode = createRootContainerBuilder() .withChild( createSubRootContainerBuilder() .withChild(outerListNode) .build()) .build(); YangInstanceIdentifier path = YangInstanceIdentifier.of(root); DataTreeModification modification = inMemoryDataTree.takeSnapshot().newModification(); modification.merge(path, rootContainerNode); /* WRITE INNER LIST WITH ENTRIES*/ MapNode innerListNode = createInnerListBuilder() .withChild(createInnerListEntry("a", "i-a")) .withChild(createInnerListEntry("b", "i-b")) .build(); path = YangInstanceIdentifier.of(root).node(subRoot).node(outerList).node(createOuterListEntryPath("2")).node(innerList); modification.write(path, innerListNode); /* COMMIT */ modification.ready(); inMemoryDataTree.validate(modification); inMemoryDataTree.commit(inMemoryDataTree.prepare(modification)); } private void secondModification(int testScenarioNumber) throws DataValidationFailedException { /* MERGE */ MapNode outerListNode = ImmutableNodes.mapNodeBuilder().withNodeIdentifier(NodeIdentifier.create(outerList)) .withChild(createOuterListEntry("3", "o-3")) .withChild(createOuterListEntry("4", "o-4")) .withChild(createOuterListEntry("5", "o-5")) .build(); ContainerNode rootContainerNode = createRootContainerBuilder() .withChild( createSubRootContainerBuilder() .withChild(outerListNode) .build()) .build(); YangInstanceIdentifier path = YangInstanceIdentifier.of(root); DataTreeModification modification = inMemoryDataTree.takeSnapshot().newModification(); modification.merge(path, rootContainerNode); if (testScenarioNumber == 1) { /* WRITE EMPTY INNER LIST */ writeEmptyInnerList(modification, "2"); } else if (testScenarioNumber == 2) { /* WRITE INNER LIST ENTRY */ MapEntryNode innerListEntryA = createInnerListEntry("a", "i-a-2"); path = YangInstanceIdentifier.of(root).node(subRoot).node(outerList).node(createOuterListEntryPath("2")) .node(innerList).node(createInnerListEntryPath("a")); modification.write(path, innerListEntryA); } else if (testScenarioNumber == 3) { /* WRITE INNER LIST WITH ENTRIES */ MapNode innerListNode = createInnerListBuilder().withChild(createInnerListEntry("a", "i-a-3")) .withChild(createInnerListEntry("c", "i-c")).build(); path = YangInstanceIdentifier.of(root).node(subRoot).node(outerList).node(createOuterListEntryPath("2")) .node(innerList); modification.write(path, innerListNode); } /* COMMIT */ modification.ready(); inMemoryDataTree.validate(modification); inMemoryDataTree.commit(inMemoryDataTree.prepare(modification)); } private void writeEmptyInnerList(DataTreeModification modification, String outerListEntryKey) { YangInstanceIdentifier path = YangInstanceIdentifier.of(root).node(subRoot).node(outerList) .node(createOuterListEntryPath(outerListEntryKey)).node(innerList); modification.write(path, createInnerListBuilder().build()); } private DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> createRootContainerBuilder() { return ImmutableContainerNodeBuilder.create().withNodeIdentifier( new YangInstanceIdentifier.NodeIdentifier(root)); } private DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> createSubRootContainerBuilder() { return ImmutableContainerNodeBuilder.create().withNodeIdentifier( new YangInstanceIdentifier.NodeIdentifier(subRoot)); } private CollectionNodeBuilder<MapEntryNode, MapNode> createInnerListBuilder() { return ImmutableNodes.mapNodeBuilder().withNodeIdentifier(NodeIdentifier.create(innerList)); } private NodeIdentifierWithPredicates createInnerListEntryPath(String keyValue) { Builder<QName, Object> builder = ImmutableMap.builder(); ImmutableMap<QName, Object> keys = builder.put(iId, keyValue).build(); return new YangInstanceIdentifier.NodeIdentifierWithPredicates(innerList, keys); } private NodeIdentifierWithPredicates createOuterListEntryPath(String keyValue) { Builder<QName, Object> builder = ImmutableMap.builder(); ImmutableMap<QName, Object> keys = builder.put(oId, keyValue).build(); return new YangInstanceIdentifier.NodeIdentifierWithPredicates(outerList, keys); } private MapEntryNode createOuterListEntry(String keyValue, String leafValue) { return ImmutableNodes.mapEntryBuilder(outerList, oId, keyValue) .withChild(ImmutableNodes.leafNode(oLeaf, leafValue)).build(); } private MapEntryNode createInnerListEntry(String keyValue, String leafValue) { return ImmutableNodes.mapEntryBuilder(innerList, iId, keyValue) .withChild(ImmutableNodes.leafNode(iLeaf, leafValue)).build(); } }