Added several unit tests.
Change-Id: I57b4b6c84fd489f2546189bb66bc03490ccf194f
Signed-off-by: Igor Foltin <ifoltin@cisco.com>
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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 com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.DifferenceListener;
+import org.custommonkey.xmlunit.IgnoreTextAndAttributeValuesDifferenceListener;
+import org.custommonkey.xmlunit.XMLAssert;
+import org.custommonkey.xmlunit.XMLUnit;
+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.schema.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+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.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
+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.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+public class SchemalessXMLStreamNormalizedNodeStreamWriterTest {
+
+ private QNameModule foobarModule;
+
+ private QName outerContainer;
+
+ private QName myContainer1;
+ private QName myKeyedList;
+ private QName myKeyLeaf;
+ private QName myLeafInList1;
+ private QName myLeafInList2;
+ private QName myOrderedList;
+ private QName myKeyLeafInOrderedList;
+ private QName myLeafInOrderedList1;
+ private QName myLeafInOrderedList2;
+ private QName myUnkeyedList;
+ private QName myLeafInUnkeyedList;
+ private QName myLeaf1;
+ private QName myLeafList;
+ private QName myOrderedLeafList;
+
+ private QName myContainer2;
+ private QName innerContainer;
+ private QName myLeaf2;
+ private QName myLeaf3;
+ private QName myChoice;
+ private QName myLeafInCase2;
+ private QName myAnyxml;
+
+ private QName myContainer3;
+ private QName myDoublyKeyedList;
+ private QName myFirstKeyLeaf;
+ private QName mySecondKeyLeaf;
+ private QName myLeafInList3;
+
+ private DOMSource anyxmlDomSource;
+
+ @Before
+ public void setup() throws URISyntaxException, ParseException {
+ foobarModule = QNameModule.create(new URI("foobar-namespace"), SimpleDateFormatUtil.getRevisionFormat().parse
+ ("2016-09-19"));
+
+ outerContainer = QName.create(foobarModule, "outer-container");
+
+ myContainer1 = QName.create(foobarModule, "my-container-1");
+ myKeyedList = QName.create(foobarModule, "my-keyed-list");
+ myKeyLeaf = QName.create(foobarModule, "my-key-leaf");
+ myLeafInList1 = QName.create(foobarModule, "my-leaf-in-list-1");
+ myLeafInList2 = QName.create(foobarModule, "my-leaf-in-list-2");
+ myOrderedList = QName.create(foobarModule, "my-ordered-list");
+ myKeyLeafInOrderedList = QName.create(foobarModule, "my-key-leaf-in-ordered-list");
+ myLeafInOrderedList1 = QName.create(foobarModule, "my-leaf-in-ordered-list-1");
+ myLeafInOrderedList2 = QName.create(foobarModule, "my-leaf-in-ordered-list-2");
+ myUnkeyedList = QName.create(foobarModule, "my-unkeyed-list");
+ myLeafInUnkeyedList = QName.create(foobarModule, "my-leaf-in-unkeyed-list");
+ myLeaf1 = QName.create(foobarModule, "my-leaf-1");
+ myLeafList = QName.create(foobarModule, "my-leaf-list");
+ myOrderedLeafList = QName.create(foobarModule, "my-ordered-leaf-list");
+
+ myContainer2 = QName.create(foobarModule, "my-container-2");
+ innerContainer = QName.create(foobarModule, "inner-container");
+ myLeaf2 = QName.create(foobarModule, "my-leaf-2");
+ myLeaf3 = QName.create(foobarModule, "my-leaf-3");
+ myChoice = QName.create(foobarModule, "my-choice");
+ myLeafInCase2 = QName.create(foobarModule, "my-leaf-in-case-2");
+ myAnyxml = QName.create(foobarModule, "my-anyxml");
+
+ myContainer3 = QName.create(foobarModule, "my-container-3");
+ myDoublyKeyedList = QName.create(foobarModule, "my-doubly-keyed-list");
+ myFirstKeyLeaf = QName.create(foobarModule, "my-first-key-leaf");
+ mySecondKeyLeaf = QName.create(foobarModule, "my-second-key-leaf");
+ myLeafInList3 = QName.create(foobarModule, "my-leaf-in-list-3");
+
+ anyxmlDomSource = new DOMSource();
+ }
+
+ @Test
+ public void testWrite() throws XMLStreamException, IOException, SAXException {
+ final Document doc = loadDocument("/foobar.xml");
+
+ final Document document = getDocument();
+ final DOMResult domResult = new DOMResult(document);
+
+ final XMLOutputFactory factory = XMLOutputFactory.newInstance();
+ factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
+
+ final XMLStreamWriter xmlStreamWriter = factory.createXMLStreamWriter(domResult);
+
+ final NormalizedNodeStreamWriter schemalessXmlNormalizedNodeStreamWriter =
+ XMLStreamNormalizedNodeStreamWriter.createSchemaless(xmlStreamWriter);
+
+ final NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter
+ (schemalessXmlNormalizedNodeStreamWriter);
+
+ normalizedNodeWriter.write(buildOuterContainerNode());
+
+ XMLUnit.setIgnoreWhitespace(true);
+ XMLUnit.setNormalize(true);
+
+ final String expectedXml = toString(doc.getDocumentElement().getElementsByTagName("outer-container").item(0));
+ final String serializedXml = toString(domResult.getNode());
+ final Diff diff = new Diff(expectedXml, serializedXml);
+
+ final DifferenceListener differenceListener = new IgnoreTextAndAttributeValuesDifferenceListener();
+ diff.overrideDifferenceListener(differenceListener);
+
+ XMLAssert.assertXMLEqual(diff, true);
+ }
+
+ private NormalizedNode<?, ?> buildOuterContainerNode() {
+ // my-container-1
+ MapNode myKeyedListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myKeyedList))
+ .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
+ new NodeIdentifierWithPredicates(myKeyedList, myKeyLeaf, "listkeyvalue1"))
+ .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList1))
+ .withValue("listleafvalue1").build())
+ .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList2))
+ .withValue("listleafvalue2").build()).build())
+ .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
+ new NodeIdentifierWithPredicates(myKeyedList, myKeyLeaf, "listkeyvalue2"))
+ .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList1))
+ .withValue("listleafvalue12").build())
+ .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList2))
+ .withValue("listleafvalue22").build()).build()).build();
+
+ OrderedMapNode myOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(new NodeIdentifier(myOrderedList))
+ .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
+ new NodeIdentifierWithPredicates(myOrderedList, myKeyLeafInOrderedList, "olistkeyvalue1"))
+ .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInOrderedList1))
+ .withValue("olistleafvalue1").build())
+ .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInOrderedList2))
+ .withValue("olistleafvalue2").build()).build())
+ .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
+ new NodeIdentifierWithPredicates(myOrderedList, myKeyLeafInOrderedList, "olistkeyvalue2"))
+ .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInOrderedList1))
+ .withValue("olistleafvalue12").build())
+ .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInOrderedList2))
+ .withValue("olistleafvalue22").build()).build()).build();
+
+ final UnkeyedListEntryNode unkeyedListEntry = Builders.unkeyedListEntryBuilder()
+ .withNodeIdentifier(new NodeIdentifier(myUnkeyedList))
+ .withChild(ImmutableNodes.leafNode(myLeafInUnkeyedList, "foo")).build();
+
+ final List<UnkeyedListEntryNode> unkeyedListEntries = new ArrayList<>();
+ unkeyedListEntries.add(unkeyedListEntry);
+
+ UnkeyedListNode myUnkeyedListNode = Builders.unkeyedListBuilder().withNodeIdentifier(
+ new NodeIdentifier(myUnkeyedList))
+ .withValue(unkeyedListEntries).build();
+
+ LeafNode<?> myLeaf1Node = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf1))
+ .withValue("value1").build();
+
+ LeafSetNode<?> myLeafListNode = Builders.leafSetBuilder().withNodeIdentifier(new NodeIdentifier(myLeafList))
+ .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
+ new NodeWithValue<>(myLeafList, "lflvalue1")).withValue("lflvalue1").build())
+ .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
+ new NodeWithValue<>(myLeafList, "lflvalue2")).withValue("lflvalue2").build()).build();
+
+ LeafSetNode<?> myOrderedLeafListNode = Builders.orderedLeafSetBuilder().withNodeIdentifier(
+ new NodeIdentifier(myOrderedLeafList))
+ .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
+ new NodeWithValue<>(myOrderedLeafList, "olflvalue1")).withValue("olflvalue1").build())
+ .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
+ new NodeWithValue<>(myOrderedLeafList, "olflvalue2")).withValue("olflvalue2").build()).build();
+
+ ContainerNode myContainer1Node = Builders.containerBuilder().withNodeIdentifier(
+ new NodeIdentifier(myContainer1))
+ .withChild(myKeyedListNode)
+ .withChild(myOrderedListNode)
+ .withChild(myUnkeyedListNode)
+ .withChild(myLeaf1Node)
+ .withChild(myLeafListNode)
+ .withChild(myOrderedLeafListNode)
+ .build();
+
+ // my-container-2
+ ContainerNode innerContainerNode = Builders.containerBuilder().withNodeIdentifier(
+ new NodeIdentifier(innerContainer))
+ .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf2))
+ .withValue("value2").build()).build();
+
+ LeafNode<?> myLeaf3Node = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf3))
+ .withValue("value3").build();
+
+ ChoiceNode myChoiceNode = Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(myChoice))
+ .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInCase2))
+ .withValue("case2value").build()).build();
+
+ AnyXmlNode myAnyxmlNode = Builders.anyXmlBuilder().withNodeIdentifier(new NodeIdentifier(myAnyxml))
+ .withValue(anyxmlDomSource).build();
+
+ ContainerNode myContainer2Node = Builders.containerBuilder().withNodeIdentifier(
+ new NodeIdentifier(myContainer2))
+ .withChild(innerContainerNode)
+ .withChild(myLeaf3Node)
+ .withChild(myChoiceNode).build();
+ //.withChild(myAnyxmlNode).build();
+
+ // my-container-3
+ Map<QName, Object> keys = new HashMap<>();
+ keys.put(myFirstKeyLeaf, "listkeyvalue1");
+ keys.put(mySecondKeyLeaf, "listkeyvalue2");
+
+ MapNode myDoublyKeyedListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myDoublyKeyedList))
+ .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
+ new NodeIdentifierWithPredicates(myDoublyKeyedList, keys))
+ .withChild(Builders.leafBuilder().withNodeIdentifier(
+ new NodeIdentifier(myLeafInList3)).withValue("listleafvalue1").build()).build())
+ .build();
+
+ AugmentationNode myDoublyKeyedListAugNode = Builders.augmentationBuilder().withNodeIdentifier(
+ new AugmentationIdentifier(Sets.newHashSet(myDoublyKeyedList)))
+ .withChild(myDoublyKeyedListNode).build();
+
+ ContainerNode myContainer3Node = Builders.containerBuilder().withNodeIdentifier(
+ new NodeIdentifier(myContainer3))
+ .withChild(myDoublyKeyedListAugNode).build();
+
+ AugmentationNode myContainer3AugNode = Builders.augmentationBuilder().withNodeIdentifier(
+ new AugmentationIdentifier(Sets.newHashSet(myContainer3)))
+ .withChild(myContainer3Node).build();
+
+ ContainerNode outerContainerNode = Builders.containerBuilder().withNodeIdentifier(
+ new NodeIdentifier(outerContainer))
+ .withChild(myContainer1Node)
+ .withChild(myContainer2Node)
+ .withChild(myContainer3AugNode).build();
+
+ return outerContainerNode;
+ }
+
+ private static Document loadDocument(final String xmlPath) throws IOException, SAXException {
+ final InputStream resourceAsStream = SchemalessXMLStreamNormalizedNodeStreamWriterTest.class.getResourceAsStream(xmlPath);
+ final Document currentConfigElement = readXmlToDocument(resourceAsStream);
+ Preconditions.checkNotNull(currentConfigElement);
+ return currentConfigElement;
+ }
+
+ private static Document readXmlToDocument(final InputStream xmlContent) throws IOException, SAXException {
+ final DocumentBuilder dBuilder;
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ factory.setCoalescing(true);
+ factory.setIgnoringElementContentWhitespace(true);
+ factory.setIgnoringComments(true);
+ dBuilder = factory.newDocumentBuilder();
+ } catch (final ParserConfigurationException e) {
+ throw new RuntimeException("Failed to parse XML document", e);
+ }
+ final Document doc = dBuilder.parse(xmlContent);
+
+ doc.getDocumentElement().normalize();
+ return doc;
+ }
+
+ private static String toString(final Node xml) {
+ try {
+ final Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+
+ final StreamResult result = new StreamResult(new StringWriter());
+ final DOMSource source = new DOMSource(xml);
+ transformer.transform(source, result);
+
+ return result.getWriter().toString();
+ } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
+ throw new RuntimeException("Unable to serialize xml element " + xml, e);
+ }
+ }
+
+ private static Document getDocument() {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ Document doc = null;
+ try {
+ DocumentBuilder bob = dbf.newDocumentBuilder();
+ doc = bob.newDocument();
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+ return doc;
+ }
+}
final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext);
xmlParser.parse(reader);
+ xmlParser.flush();
+ xmlParser.close();
+
final NormalizedNode<?, ?> transformedInput = result.getResult();
assertNotNull(transformedInput);
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<root xmlns="foobar-namespace">
+ <outer-container>
+ <my-container-1>
+ <my-keyed-list>
+ <my-key-leaf>listkeyvalue1</my-key-leaf>
+ <my-leaf-in-list-1>listleafvalue1</my-leaf-in-list-1>
+ <my-leaf-in-list-2>listleafvalue2</my-leaf-in-list-2>
+ </my-keyed-list>
+
+ <my-keyed-list>
+ <my-key-leaf>listkeyvalue2</my-key-leaf>
+ <my-leaf-in-list-1>listleafvalue12</my-leaf-in-list-1>
+ <my-leaf-in-list-2>listleafvalue22</my-leaf-in-list-2>
+ </my-keyed-list>
+
+ <my-ordered-list>
+ <my-key-leaf-in-ordered-list>olistkeyvalue1</my-key-leaf-in-ordered-list>
+ <my-leaf-in-ordered-list-1>olistleafvalue1</my-leaf-in-ordered-list-1>
+ <my-leaf-in-ordered-list-2>olistleafvalue2</my-leaf-in-ordered-list-2>
+ </my-ordered-list>
+
+ <my-ordered-list>
+ <my-key-leaf-in-ordered-list>olistkeyvalue2</my-key-leaf-in-ordered-list>
+ <my-leaf-in-ordered-list-1>olistleafvalue12</my-leaf-in-ordered-list-1>
+ <my-leaf-in-ordered-list-2>olistleafvalue22</my-leaf-in-ordered-list-2>
+ </my-ordered-list>
+
+ <my-unkeyed-list>
+ <my-leaf-in-unkeyed-list>foo</my-leaf-in-unkeyed-list>
+ </my-unkeyed-list>
+
+ <my-leaf-1>value1</my-leaf-1>
+
+ <my-leaf-list>lflvalue1</my-leaf-list>
+ <my-leaf-list>lflvalue2</my-leaf-list>
+
+ <my-ordered-leaf-list>olflvalue1</my-ordered-leaf-list>
+ <my-ordered-leaf-list>olflvalue2</my-ordered-leaf-list>
+ </my-container-1>
+
+ <my-container-2>
+ <inner-container>
+ <my-leaf-2>value2</my-leaf-2>
+ </inner-container>
+ <my-leaf-3>value3</my-leaf-3>
+ <my-leaf-in-case-2>case2value</my-leaf-in-case-2>
+ </my-container-2>
+
+ <my-container-3>
+ <my-doubly-keyed-list>
+ <my-first-key-leaf>listkeyvalue1</my-first-key-leaf>
+ <my-second-key-leaf>listkeyvalue2</my-second-key-leaf>
+ <my-leaf-in-list-3>listleafvalue1</my-leaf-in-list-3>
+ </my-doubly-keyed-list>
+ </my-container-3>
+ </outer-container>
+</root>
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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.parser.stmt.rfc6020.effective;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.Lists;
+import com.google.common.io.ByteSource;
+import com.google.common.io.Files;
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.text.ParseException;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
+
+public class ConstraintDefinitionsTest {
+
+ @Test
+ public void testConstraintDefinitions() throws ParseException, ReactorException, URISyntaxException, IOException {
+ final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
+
+ final File yangFile = new File(getClass().getResource("/constraint-definitions-test/foo.yang").toURI());
+ assertNotNull(yangFile);
+
+ final ByteSource yangByteSource = Files.asByteSource(yangFile);
+ assertNotNull(yangByteSource);
+
+ final SchemaContext schemaContext = reactor.buildEffective(Lists.newArrayList(yangByteSource));
+ assertNotNull(schemaContext);
+
+ final Module testModule = schemaContext.findModuleByName(
+ "foo", SimpleDateFormatUtil.getRevisionFormat().parse("2016-09-20"));
+ assertNotNull(testModule);
+
+ final LeafSchemaNode mandatoryLeaf1 = (LeafSchemaNode) testModule.getDataChildByName(
+ QName.create(testModule.getQNameModule(), "mandatory-leaf-1"));
+ assertNotNull(mandatoryLeaf1);
+ ConstraintDefinition constraints1 = mandatoryLeaf1.getConstraints();
+
+ final LeafSchemaNode mandatoryLeaf2 = (LeafSchemaNode) testModule.getDataChildByName(
+ QName.create(testModule.getQNameModule(), "mandatory-leaf-2"));
+ assertNotNull(mandatoryLeaf2);
+ ConstraintDefinition constraints2 = mandatoryLeaf2.getConstraints();
+
+ assertEquals(ConstraintDefinitions.hashCode(constraints1), ConstraintDefinitions.hashCode(constraints2));
+ assertTrue(ConstraintDefinitions.equals(constraints1, constraints2));
+
+ assertTrue(ConstraintDefinitions.equals(constraints1, constraints1));
+ assertFalse(ConstraintDefinitions.equals(constraints1, "str"));
+
+ final LeafSchemaNode mandatoryLeaf3 = (LeafSchemaNode) testModule.getDataChildByName(
+ QName.create(testModule.getQNameModule(), "mandatory-leaf-3"));
+ assertNotNull(mandatoryLeaf3);
+ ConstraintDefinition constraints3 = mandatoryLeaf3.getConstraints();
+
+ assertNotEquals(ConstraintDefinitions.hashCode(constraints2), ConstraintDefinitions.hashCode(constraints3));
+ assertFalse(ConstraintDefinitions.equals(constraints2, constraints3));
+
+ final LeafSchemaNode mandatoryLeaf4 = (LeafSchemaNode) testModule.getDataChildByName(
+ QName.create(testModule.getQNameModule(), "mandatory-leaf-4"));
+ assertNotNull(mandatoryLeaf4);
+ ConstraintDefinition constraints4 = mandatoryLeaf4.getConstraints();
+
+ assertNotEquals(ConstraintDefinitions.hashCode(constraints3), ConstraintDefinitions.hashCode(constraints4));
+ assertFalse(ConstraintDefinitions.equals(constraints3, constraints4));
+
+ final LeafSchemaNode mandatoryLeaf5 = (LeafSchemaNode) testModule.getDataChildByName(
+ QName.create(testModule.getQNameModule(), "mandatory-leaf-5"));
+ assertNotNull(mandatoryLeaf5);
+ final ConstraintDefinition constraints5 = mandatoryLeaf5.getConstraints();
+
+ assertNotEquals(ConstraintDefinitions.hashCode(constraints4), ConstraintDefinitions.hashCode(constraints5));
+ assertFalse(ConstraintDefinitions.equals(constraints4, constraints5));
+
+ final LeafListSchemaNode constrainedLeafList1 = (LeafListSchemaNode) testModule.getDataChildByName(
+ QName.create(testModule.getQNameModule(), "constrained-leaf-list-1"));
+ assertNotNull(constrainedLeafList1);
+ constraints1 = constrainedLeafList1.getConstraints();
+
+ final LeafListSchemaNode constrainedLeafList2 = (LeafListSchemaNode) testModule.getDataChildByName(
+ QName.create(testModule.getQNameModule(), "constrained-leaf-list-2"));
+ assertNotNull(constrainedLeafList2);
+ constraints2 = constrainedLeafList2.getConstraints();
+
+ assertEquals(ConstraintDefinitions.hashCode(constraints1), ConstraintDefinitions.hashCode(constraints2));
+ assertTrue(ConstraintDefinitions.equals(constraints1, constraints2));
+
+ final LeafListSchemaNode constrainedLeafList3 = (LeafListSchemaNode) testModule.getDataChildByName(
+ QName.create(testModule.getQNameModule(), "constrained-leaf-list-3"));
+ assertNotNull(constrainedLeafList3);
+ constraints3 = constrainedLeafList3.getConstraints();
+
+ assertNotEquals(ConstraintDefinitions.hashCode(constraints2), ConstraintDefinitions.hashCode(constraints3));
+ assertFalse(ConstraintDefinitions.equals(constraints2, constraints3));
+
+ final LeafListSchemaNode constrainedLeafList4 = (LeafListSchemaNode) testModule.getDataChildByName(
+ QName.create(testModule.getQNameModule(), "constrained-leaf-list-4"));
+ assertNotNull(constrainedLeafList4);
+ constraints4 = constrainedLeafList4.getConstraints();
+
+ assertNotEquals(ConstraintDefinitions.hashCode(constraints3), ConstraintDefinitions.hashCode(constraints4));
+ assertFalse(ConstraintDefinitions.equals(constraints3, constraints4));
+
+ final String constraintsString = ConstraintDefinitions.toString(constraints4);
+ assertEquals("EffectiveConstraintDefinitionImpl{whenCondition=foo = 'bar', mustConstraints=[bar != 'foo'], " +
+ "mandatory=true, minElements=50, maxElements=100}", constraintsString);
+ }
+}
\ No newline at end of file
private static final StatementStreamSource FOO_MODULE =
new YangStatementSourceImpl("/deviation-stmt-test/foo.yang", false);
+ private static final StatementStreamSource BAR_MODULE =
+ new YangStatementSourceImpl("/deviation-stmt-test/bar.yang", false);
@Test
public void testDeviationAndDeviate() throws ReactorException, ParseException {
final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
- reactor.addSources(FOO_MODULE);
+ reactor.addSources(FOO_MODULE, BAR_MODULE);
final SchemaContext schemaContext = reactor.buildEffective();
assertNotNull(schemaContext);
- final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2016-06-23");
+ Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2016-06-23");
- final Module testModule = schemaContext.findModuleByName("foo", revision);
+ Module testModule = schemaContext.findModuleByName("foo", revision);
assertNotNull(testModule);
- final Set<Deviation> deviations = testModule.getDeviations();
+ Set<Deviation> deviations = testModule.getDeviations();
assertEquals(4, deviations.size());
for (Deviation deviation : deviations) {
assertEquals(2, deviates.iterator().next().getDeviatedUniques().size());
}
}
+
+ revision = SimpleDateFormatUtil.getRevisionFormat().parse("2016-09-22");
+ testModule = schemaContext.findModuleByName("bar", revision);
+ assertNotNull(testModule);
+
+ deviations = testModule.getDeviations();
+ assertEquals(7, deviations.size());
+
+ Deviation deviation1 = null;
+ Deviation deviation2 = null;
+ Deviation deviation3 = null;
+ Deviation deviation4 = null;
+ Deviation deviation5 = null;
+ Deviation deviation6 = null;
+ Deviation deviation7 = null;
+
+ for (Deviation deviation : deviations) {
+ final List<DeviateDefinition> deviates = deviation.getDeviates();
+ final String targetLocalName = deviation.getTargetPath().getLastComponent().getLocalName();
+
+ if ("bar-container-1".equals(targetLocalName)) {
+ deviation1 = deviation;
+ }
+
+ if ("bar-container-2".equals(targetLocalName)) {
+ DeviateKind deviateKind = deviates.iterator().next().getDeviateType();
+ if (deviateKind.equals(DeviateKind.NOT_SUPPORTED)) {
+ deviation2 = deviation;
+ } else if (deviateKind.equals(DeviateKind.ADD)) {
+ deviation3 = deviation;
+ }
+ }
+
+ if ("bar-leaf-1".equals(targetLocalName)) {
+ if ("desc".equals(deviation.getDescription())) {
+ deviation4 = deviation;
+ } else {
+ deviation5 = deviation;
+ }
+ }
+
+ if ("bar-leaf-2".equals(targetLocalName)) {
+ if ("ref".equals(deviation.getReference())) {
+ deviation6 = deviation;
+ } else {
+ deviation7 = deviation;
+ }
+ }
+ }
+
+ assertEquals(1, deviation1.getUnknownSchemaNodes().size());
+ assertTrue(deviation1.equals(deviation1));
+ assertFalse(deviation1.equals(null));
+ assertFalse(deviation1.equals("str"));
+
+ DeviateDefinition deviate = deviation1.getDeviates().iterator().next();
+ assertTrue(deviate.equals(deviate));
+ assertFalse(deviate.equals(null));
+ assertFalse(deviate.equals("str"));
+
+ assertFalse(deviation1.equals(deviation2));
+ assertFalse(deviation2.equals(deviation3));
+ assertFalse(deviation4.equals(deviation5));
+ assertFalse(deviation6.equals(deviation7));
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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.stmt;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.Lists;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.ParseException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext;
+
+public class EffectiveSchemaContextTest {
+
+ @Test
+ public void testEffectiveSchemaContext() throws ReactorException, ParseException, FileNotFoundException,
+ URISyntaxException {
+ final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
+
+ final File yangFile1 = new File(getClass().getResource("/effective-schema-context-test/foo.yang").toURI());
+ assertNotNull(yangFile1);
+ final File yangFile2 = new File(getClass().getResource("/effective-schema-context-test/bar.yang").toURI());
+ assertNotNull(yangFile2);
+ final File yangFile3 = new File(getClass().getResource("/effective-schema-context-test/baz.yang").toURI());
+ assertNotNull(yangFile3);
+
+ final InputStream yangInputStream1 = new FileInputStream(yangFile1);
+ assertNotNull(yangInputStream1);
+ final InputStream yangInputStream2 = new FileInputStream(yangFile2);
+ assertNotNull(yangInputStream2);
+ final InputStream yangInputStream3 = new FileInputStream(yangFile3);
+ assertNotNull(yangInputStream3);
+
+ final SchemaContext schemaContext = reactor.buildEffective(Lists.newArrayList(
+ yangInputStream1, yangInputStream2, yangInputStream3));
+ assertNotNull(schemaContext);
+
+ final Set<DataSchemaNode> dataDefinitions = schemaContext.getDataDefinitions();
+ assertEquals(3, dataDefinitions.size());
+
+ final Collection<DataSchemaNode> childNodes = schemaContext.getChildNodes();
+ assertEquals(3, childNodes.size());
+
+ final Set<NotificationDefinition> notifications = schemaContext.getNotifications();
+ assertEquals(3, notifications.size());
+
+ final Set<RpcDefinition> rpcs = schemaContext.getOperations();
+ assertEquals(3, rpcs.size());
+
+ final Set<ExtensionDefinition> extensions = schemaContext.getExtensions();
+ assertEquals(3, extensions.size());
+
+ final List<UnknownSchemaNode> unknownSchemaNodes = schemaContext.getUnknownSchemaNodes();
+ assertEquals(3, unknownSchemaNodes.size());
+
+ assertNull(schemaContext.getDataChildByName(QName.create("foo-namespace", "2016-09-21", "foo-cont")));
+
+ assertNull(schemaContext.findModuleByName("foo", SimpleDateFormatUtil.getRevisionFormat().parse("2016-08-21")));
+ assertNull(schemaContext.findModuleByNamespaceAndRevision(
+ null, SimpleDateFormatUtil.getRevisionFormat().parse("2016-09-21")));
+ assertNull(schemaContext.findModuleByNamespaceAndRevision(
+ URI.create("foo-namespace"), SimpleDateFormatUtil.getRevisionFormat().parse("2016-08-21")));
+
+ assertFalse(schemaContext.isAugmenting());
+ assertFalse(schemaContext.isAddedByUses());
+ assertFalse(schemaContext.isConfiguration());
+ assertFalse(schemaContext.isPresenceContainer());
+ assertNull(schemaContext.getConstraints());
+ assertNull(schemaContext.getDescription());
+ assertNull(schemaContext.getReference());
+ assertEquals(SchemaContext.NAME, schemaContext.getQName());
+ assertEquals(SchemaPath.ROOT, schemaContext.getPath());
+ assertEquals(Status.CURRENT, schemaContext.getStatus());
+ assertTrue(schemaContext.getUses() instanceof Set);
+ assertTrue(schemaContext.getUses().isEmpty());
+ assertTrue(schemaContext.getAvailableAugmentations() instanceof Set);
+ assertTrue(schemaContext.getAvailableAugmentations().isEmpty());
+
+ Module fooModule = schemaContext.findModuleByName(
+ "foo", SimpleDateFormatUtil.getRevisionFormat().parse("2016-09-21"));
+ assertFalse(schemaContext.getModuleSource(fooModule).isPresent());
+
+ assertEquals(3, schemaContext.getAllModuleIdentifiers().size());
+ assertEquals(3, ((EffectiveSchemaContext) schemaContext).getRootDeclaredStatements().size());
+ assertEquals(3,((EffectiveSchemaContext) schemaContext).getRootEffectiveStatements().size());
+
+ final Set<Module> modules = schemaContext.getModules();
+ final SchemaContext copiedSchemaContext = EffectiveSchemaContext.resolveSchemaContext(modules);
+ assertNotNull(copiedSchemaContext);
+ assertEquals(modules, copiedSchemaContext.getModules());
+ }
+}
package org.opendaylight.yangtools.yang.stmt;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import java.text.ParseException;
+import java.util.Set;
import org.junit.Test;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
private static final YangStatementSourceImpl RPC_MODULE = new YangStatementSourceImpl("/model/baz.yang", false);
private static final YangStatementSourceImpl IMPORTED_MODULE = new YangStatementSourceImpl("/model/bar.yang",
false);
+ private static final YangStatementSourceImpl FOO_MODULE = new YangStatementSourceImpl("/rpc-stmt-test/foo.yang",
+ false);
@Test
- public void rpcTest() throws ReactorException {
+ public void rpcTest() throws ReactorException, ParseException {
final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
- StmtTestUtils.addSources(reactor, RPC_MODULE, IMPORTED_MODULE);
+ StmtTestUtils.addSources(reactor, RPC_MODULE, IMPORTED_MODULE, FOO_MODULE);
final EffectiveSchemaContext result = reactor.buildEffective();
assertNotNull(result);
anyXml = (AnyXmlSchemaNode) output.getDataChildByName(QName.create(testModule.getQNameModule(), "data"));
assertNotNull(anyXml);
+
+ final Module fooModule = result.findModuleByName("foo", SimpleDateFormatUtil.getRevisionFormat().parse("2016-09-23"));
+ assertNotNull(fooModule);
+
+ final Set<RpcDefinition> rpcs = fooModule.getRpcs();
+ assertEquals(2, rpcs.size());
+
+ RpcDefinition fooRpc1 = null;
+ RpcDefinition fooRpc2 = null;
+
+ for (RpcDefinition rpcDefinition : rpcs) {
+ if ("foo-rpc-1".equals(rpcDefinition.getQName().getLocalName())) {
+ fooRpc1 = rpcDefinition;
+ } else if ("foo-rpc-2".equals(rpcDefinition.getQName().getLocalName())) {
+ fooRpc2 = rpcDefinition;
+ }
+ }
+
+ assertFalse(fooRpc1.equals(null));
+ assertFalse(fooRpc1.equals("str"));
+ assertFalse(fooRpc1.equals(fooRpc2));
+
+ assertNotEquals(fooRpc1.getInput().hashCode(), fooRpc2.getInput().hashCode());
+ assertNotEquals(fooRpc1.getOutput().hashCode(), fooRpc2.getOutput().hashCode());
+
+ assertTrue(fooRpc1.getInput().equals(fooRpc1.getInput()));
+ assertFalse(fooRpc1.getInput().equals(null));
+ assertFalse(fooRpc1.getInput().equals("str"));
+ assertFalse(fooRpc1.getInput().equals(fooRpc2.getInput()));
+
+ assertTrue(fooRpc1.getOutput().equals(fooRpc1.getOutput()));
+ assertFalse(fooRpc1.getOutput().equals(null));
+ assertFalse(fooRpc1.getOutput().equals("str"));
+ assertFalse(fooRpc1.getOutput().equals(fooRpc2.getOutput()));
}
}
final Module testModule = TestUtils.findModule(modules, "simple-nodes");
final AnyXmlSchemaNode data = (AnyXmlSchemaNode) testModule.getDataChildByName(QName.create(testModule.getQNameModule(), "data"));
assertNotNull("'anyxml data not found'", data);
+ assertFalse(data.equals(null));
+ assertEquals("AnyXmlEffectiveStatementImpl[qname=(urn:opendaylight:simple-nodes?revision=2013-07-30)data, " +
+ "path=AbsoluteSchemaPath{path=[(urn:opendaylight:simple-nodes?revision=2013-07-30)data]}]", data.toString());
// test SchemaNode args
final QName qname = data.getQName();
--- /dev/null
+module foo {
+ namespace foo-namespace;
+ prefix foo-prefix;
+
+ revision 2016-09-20;
+
+ leaf mandatory-leaf-1 {
+ type int32;
+ mandatory true;
+ when "foo = 'bar'";
+ must "bar != 'foo'";
+ }
+
+ leaf mandatory-leaf-2 {
+ type int32;
+ mandatory true;
+ when "foo = 'bar'";
+ must "bar != 'foo'";
+ }
+
+ leaf mandatory-leaf-3 {
+ type int32;
+ mandatory false;
+ when "foo = 'bar'";
+ must "bar != 'foo'";
+ }
+
+ leaf mandatory-leaf-4 {
+ type int32;
+ mandatory false;
+ when "foo = 'baz'";
+ must "bar != 'foo'";
+ }
+
+ leaf mandatory-leaf-5 {
+ type int32;
+ mandatory false;
+ when "foo = 'baz'";
+ must "baz != 'foo'";
+ }
+
+ leaf-list constrained-leaf-list-1 {
+ type int32;
+ when "foo = 'bar'";
+ must "bar != 'foo'";
+ min-elements 10;
+ max-elements 100;
+ }
+
+ leaf-list constrained-leaf-list-2 {
+ type int32;
+ when "foo = 'bar'";
+ must "bar != 'foo'";
+ min-elements 10;
+ max-elements 100;
+ }
+
+ leaf-list constrained-leaf-list-3 {
+ type int32;
+ when "foo = 'bar'";
+ must "bar != 'foo'";
+ min-elements 50;
+ max-elements 500;
+ }
+
+ leaf-list constrained-leaf-list-4 {
+ type int32;
+ when "foo = 'bar'";
+ must "bar != 'foo'";
+ min-elements 50;
+ max-elements 100;
+ }
+}
\ No newline at end of file
--- /dev/null
+module bar {
+ namespace bar-namespace;
+ prefix bar-prefix;
+
+ revision "2016-09-22";
+
+ deviation "/bar-container-1" {
+ deviate not-supported;
+ bar-prefix:bar-extension;
+ }
+
+ deviation "/bar-container-2" {
+ deviate not-supported;
+ }
+
+ deviation "/bar-container-2" {
+ deviate add {
+ config false;
+ }
+ }
+
+ deviation "/bar-container-1/bar-leaf-1" {
+ deviate add {
+ default "def-val";
+ }
+ description "desc";
+ }
+
+ deviation "/bar-container-1/bar-leaf-1" {
+ deviate add {
+ default "def-val";
+ }
+ description "another desc";
+ }
+
+ deviation "/bar-container-1/bar-leaf-2" {
+ deviate add {
+ default "def-val";
+ }
+ reference "ref";
+ }
+
+ deviation "/bar-container-1/bar-leaf-2" {
+ deviate add {
+ default "def-val";
+ }
+ reference "another ref";
+ }
+
+ container bar-container-1 {
+ leaf bar-leaf-1 {
+ type string;
+ }
+ }
+
+ container bar-container-2 {
+ leaf bar-leaf-2 {
+ type string;
+ }
+ }
+
+ extension bar-extension {}
+}
\ No newline at end of file
--- /dev/null
+module bar {
+ namespace bar-namespace;
+ prefix bar-prefix;
+
+ revision 2016-09-21;
+
+ container bar-container {}
+
+ notification bar-notification {}
+
+ rpc bar-rpc {}
+
+ extension bar-extension {}
+
+ bar-prefix:bar-extension;
+}
\ No newline at end of file
--- /dev/null
+module baz {
+ namespace baz-namespace;
+ prefix baz-prefix;
+
+ revision 2016-09-21;
+
+ container baz-container {}
+
+ notification baz-notification {}
+
+ rpc baz-rpc {}
+
+ extension baz-extension {}
+
+ baz-prefix:baz-extension;
+}
\ No newline at end of file
--- /dev/null
+module foo {
+ namespace foo-namespace;
+ prefix foo-prefix;
+
+ revision 2016-09-21;
+
+ container foo-container {}
+
+ notification foo-notification {}
+
+ rpc foo-rpc {}
+
+ extension foo-extension {}
+
+ foo-prefix:foo-extension;
+}
\ No newline at end of file
--- /dev/null
+module foo {
+ namespace foo-namespace;
+ prefix foo-prefix;
+
+ revision 2016-09-23;
+
+ rpc foo-rpc-1 {
+ input {
+ leaf foo-leaf-1 {
+ type string;
+ }
+ }
+
+ output {
+ leaf foo-leaf-2 {
+ type string;
+ }
+ }
+ }
+
+ rpc foo-rpc-2 {
+ input {
+ leaf foo-leaf-3 {
+ type string;
+ }
+ }
+
+ output {
+ leaf foo-leaf-4 {
+ type string;
+ }
+ }
+ }
+}
\ No newline at end of file