Bug 3874: Support of yang modeled AnyXML - XML deserialization 38/29738/15
authorPeter Kajsa <pkajsa@cisco.com>
Mon, 16 Nov 2015 09:31:59 +0000 (10:31 +0100)
committerRobert Varga <robert.varga@pantheon.sk>
Sat, 9 Jan 2016 13:41:43 +0000 (14:41 +0100)
- added support of yang modeled anyXml deserialization from XML
- basic unit tests
- added anyxml-schema-location extension support and removed
  hardcoded extension name from AnyxmlStatementImpl

Change-Id: I2add4bd5613417514d84b52be786074e2cc75f4f
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
Signed-off-by: Robert Varga <robert.varga@pantheon.sk>
29 files changed:
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParserFactory.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/NodeParserDispatcher.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/YangModeledAnyXmlNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/DomToNormalizedNodeParserFactory.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/YangModeledAnyXmlDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/retest/YangModeledAnyXMLDeserializationTest.java [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/anyxml-support/xml/bar.xml [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/anyxml-support/xml/foo.xml [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/anyxml-support/yang/bar.yang [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/anyxml-support/yang/foo.yang [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/anyxml-support/yang/yang-ext.yang [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangStatementParserListenerImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YinStatementParserImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/SubstatementValidator.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/AnyxmlSchemaLocationNamespace.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AnyxmlSchemaLocationStatementImpl.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AnyxmlStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SupportedExtensionsMapping.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/AnyXmlEffectiveStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/AnyxmlSchemaLocationEffectiveStatementImpl.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/UnknownEffectiveStatementBase.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/UnknownEffectiveStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/YangModeledAnyXmlEffectiveStatementImpl.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug3874ExtensionTest.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug3874/foo.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug3874/yang-ext.yang [new file with mode: 0644]

index f34ca9bc13ab32ae6f31a4daf3779055885b4fdc..966a79f2eb23fb0987a606a4c5b2bf0a0e652d76 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 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.YangModeledAnyXmlNode;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
@@ -26,6 +27,7 @@ import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.YangModeledAnyXmlSchemaNode;
 
 /**
  * Factory for different normalized node parsers.
@@ -44,6 +46,7 @@ public interface ToNormalizedNodeParserFactory<E> {
     ToNormalizedNodeParser<E, MapNode, ListSchemaNode> getMapNodeParser();
     ToNormalizedNodeParser<E, UnkeyedListNode, ListSchemaNode> getUnkeyedListNodeParser();
     ToNormalizedNodeParser<E, UnkeyedListEntryNode, ListSchemaNode> getUnkeyedListEntryNodeParser();
+    ToNormalizedNodeParser<E, YangModeledAnyXmlNode, YangModeledAnyXmlSchemaNode> getYangModeledAnyXmlNodeParser();
     ToNormalizedNodeParser<E, AnyXmlNode, AnyXmlSchemaNode> getAnyXmlNodeParser();
     ToNormalizedNodeParser<E, OrderedMapNode, ListSchemaNode> getOrderedListNodeParser();
 }
index 1b250a92569b79df12b142cad2748b4d9384f1ee..d38b39868a3caa025af64db5b4eaff36836ea052 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.YangModeledAnyXmlSchemaNode;
 
 /**
  *
@@ -63,6 +64,8 @@ public interface NodeParserDispatcher<E> {
                 return factory.getChoiceNodeParser().parse(childNodes, (ChoiceSchemaNode) schema);
             } else if (schema instanceof AugmentationSchema) {
                 return factory.getAugmentationNodeParser().parse(childNodes, (AugmentationSchema) schema);
+            } else if (schema instanceof YangModeledAnyXmlSchemaNode) {
+                return factory.getYangModeledAnyXmlNodeParser().parse(childNodes,(YangModeledAnyXmlSchemaNode)schema);
             } else if (schema instanceof AnyXmlSchemaNode) {
                 return factory.getAnyXmlNodeParser().parse(childNodes,(AnyXmlSchemaNode)schema);
             }
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/YangModeledAnyXmlNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/YangModeledAnyXmlNodeBaseParser.java
new file mode 100644 (file)
index 0000000..fe26854
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 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.impl.schema.transform.base.parser;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import java.util.Collection;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.YangModeledAnyXmlNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.model.api.YangModeledAnyXmlSchemaNode;
+
+/**
+ * Abstract(base) parser for yang modeled anyXml nodes, parses elements of type E.
+ *
+ * @param <E>
+ *            type of elements to be parsed
+ */
+public abstract class YangModeledAnyXmlNodeBaseParser<E> implements
+        ToNormalizedNodeParser<E, YangModeledAnyXmlNode, YangModeledAnyXmlSchemaNode> {
+
+    @Override
+    public final YangModeledAnyXmlNode parse(Iterable<E> elements, YangModeledAnyXmlSchemaNode schema) {
+        final int size = Iterables.size(elements);
+        Preconditions.checkArgument(size == 1, "Elements mapped to yang modeled any-xml node illegal count: %s", size);
+
+        final E e = elements.iterator().next();
+        final Collection<DataContainerChild<? extends PathArgument, ?>> value = parseAnyXml(e, schema);
+
+        final DataContainerNodeAttrBuilder<NodeIdentifier, YangModeledAnyXmlNode> yangModeledAnyXmlBuilder = Builders
+                .yangModeledAnyXmlBuilder(schema);
+
+        return yangModeledAnyXmlBuilder.withValue(value).build();
+    }
+
+    /**
+     *
+     * Parse the inner value of an YangModeledAnyXmlNode from element of type E.
+     *
+     * @param element
+     *            to be parsed
+     * @param yangModeledAnyXmlSchemaNode
+     *            schema for leaf
+     * @return parsed element as an Object
+     */
+    protected abstract Collection<DataContainerChild<? extends PathArgument, ?>> parseAnyXml(E element, YangModeledAnyXmlSchemaNode yangModeledAnyXmlSchemaNode);
+
+}
index f26434ee5b0b0c701cac9bb02cb8a8c49f1772fc..fc4cae62e2e6a8d9009385ca0c8199ff14370089 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 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.YangModeledAnyXmlNode;
 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
 import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParserFactory;
@@ -37,6 +38,7 @@ import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.YangModeledAnyXmlSchemaNode;
 import org.w3c.dom.Element;
 
 public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeParserFactory<Element> {
@@ -52,6 +54,7 @@ public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeP
     private final UnkeyedListEntryNodeDomParser unkeyedListEntryNodeParser;
     private final UnkeyedListNodeDomParser unkeyedListNodeParser;
     private final OrderedListNodeDomParser orderedListNodeParser;
+    private final YangModeledAnyXmlDomParser yangModeledAnyXmlNodeParser;
     private final AnyXmlDomParser anyXmlNodeParser;
 
     private DomToNormalizedNodeParserFactory(final XmlCodecProvider codecProvider, final SchemaContext schema, final boolean strictParsing) {
@@ -64,6 +67,7 @@ public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeP
 
         };
 
+        yangModeledAnyXmlNodeParser = new YangModeledAnyXmlDomParser(dispatcher);
         containerNodeParser = new ContainerNodeDomParser(dispatcher, strictParsing);
         mapEntryNodeParser = new MapEntryNodeDomParser(dispatcher, strictParsing);
         mapNodeParser = new MapNodeDomParser(mapEntryNodeParser);
@@ -88,6 +92,7 @@ public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeP
 
         };
 
+        yangModeledAnyXmlNodeParser = new YangModeledAnyXmlDomParser(dispatcher);
         containerNodeParser = new ContainerNodeDomParser(dispatcher, buildingStratProvider.forContainer(), strictParsing);
         mapEntryNodeParser = new MapEntryNodeDomParser(dispatcher, buildingStratProvider.forMapEntry(), strictParsing);
         mapNodeParser = new MapNodeDomParser(mapEntryNodeParser, buildingStratProvider.forMap());
@@ -173,6 +178,11 @@ public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeP
         return orderedListNodeParser;
     }
 
+    @Override
+    public ToNormalizedNodeParser<Element, YangModeledAnyXmlNode, YangModeledAnyXmlSchemaNode> getYangModeledAnyXmlNodeParser() {
+        return yangModeledAnyXmlNodeParser;
+    }
+
     @Override
     public ToNormalizedNodeParser<Element, AnyXmlNode, AnyXmlSchemaNode> getAnyXmlNodeParser() {
         return anyXmlNodeParser;
@@ -223,4 +233,5 @@ public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeP
             return new BaseDispatcherParser.SimpleBuildingStrategy<>();
         }
     }
+
 }
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/YangModeledAnyXmlDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/YangModeledAnyXmlDomParser.java
new file mode 100644 (file)
index 0000000..0920aea
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015 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.impl.schema.transform.dom.parser;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+import java.util.Collection;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.YangModeledAnyXmlNodeBaseParser;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.YangModeledAnyXmlSchemaNode;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class YangModeledAnyXmlDomParser extends YangModeledAnyXmlNodeBaseParser<Element> {
+
+    private final NodeParserDispatcher<Element> dispatcher;
+
+    public YangModeledAnyXmlDomParser(final NodeParserDispatcher<Element> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected Collection<DataContainerChild<? extends PathArgument, ?>> parseAnyXml(final Element element,
+            final YangModeledAnyXmlSchemaNode yangModeledAnyXmlSchemaNode) {
+        final QName qName = yangModeledAnyXmlSchemaNode.getQName();
+        Preconditions.checkArgument(element.getNodeName().equals(qName.getLocalName()));
+        Preconditions.checkArgument(element.getNamespaceURI().equals(qName.getNamespace().toString()));
+
+        final ContainerSchemaNode schema = yangModeledAnyXmlSchemaNode.getSchemaOfAnyXmlData();
+
+        Builder<DataContainerChild<? extends PathArgument, ?>> value = ImmutableList.builder();
+        NodeList childNodes = element.getChildNodes();
+        for (int i = 0; i < childNodes.getLength(); i++) {
+            Node node = childNodes.item(i);
+            if (node instanceof Element) {
+                Element elementChild = (Element) node;
+                // :FIXME get child by local name and namespace, not only by localName ?
+                DataSchemaNode schemaChild = schema.getDataChildByName(elementChild.getLocalName());
+
+                Preconditions.checkNotNull(schemaChild,
+                        "Unable to find schema for child element %s of yang modeled anyXml data %s.",
+                        elementChild.getLocalName(), yangModeledAnyXmlSchemaNode.getQName());
+                value.add(dispatcher.dispatchChildElement(schemaChild, ImmutableList.of(elementChild)));
+            }
+        }
+
+        return value.build();
+    }
+}
diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/retest/YangModeledAnyXMLDeserializationTest.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/retest/YangModeledAnyXMLDeserializationTest.java
new file mode 100644 (file)
index 0000000..c41e74f
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2015 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.impl.schema.transform.dom.serializer.retest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLOutputFactory;
+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.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+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.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.YangModeledAnyXmlNode;
+import org.opendaylight.yangtools.yang.data.impl.RetestUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+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.model.api.YangModeledAnyXmlSchemaNode;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+public class YangModeledAnyXMLDeserializationTest {
+    private static final XMLOutputFactory XML_FACTORY;
+    private static final DocumentBuilderFactory BUILDERFACTORY;
+
+    static {
+        XML_FACTORY = XMLOutputFactory.newFactory();
+        XML_FACTORY.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
+
+        BUILDERFACTORY = DocumentBuilderFactory.newInstance();
+        BUILDERFACTORY.setNamespaceAware(true);
+        BUILDERFACTORY.setCoalescing(true);
+        BUILDERFACTORY.setIgnoringElementContentWhitespace(true);
+        BUILDERFACTORY.setIgnoringComments(true);
+    }
+
+    private QNameModule fooModuleQName;
+    private QNameModule barModuleQName;
+    private QName myContainer1;
+    private QName myContainer2;
+    private QName innerContainer;
+    private QName myLeaf3;
+    private QName myLeaf2;
+    private QName myLeaf1;
+    private QName myAnyXMLDataBar;
+    private QName myAnyXMLDataFoo;
+    private SchemaContext schemaContext;
+
+    @Before
+    public void Init() throws Exception {
+        barModuleQName = QNameModule.create(new URI("bar"), SimpleDateFormatUtil.getRevisionFormat()
+                .parse("1970-01-01"));
+        myContainer1 = QName.create(barModuleQName, "my-container-1");
+        myLeaf1 = QName.create(barModuleQName, "my-leaf-1");
+        myAnyXMLDataBar = QName.create(barModuleQName, "my-anyxml-data");
+
+        fooModuleQName = QNameModule.create(new URI("foo"), SimpleDateFormatUtil.getRevisionFormat()
+                .parse("1970-01-01"));
+        myContainer2 = QName.create(fooModuleQName, "my-container-2");
+        innerContainer = QName.create(fooModuleQName, "inner-container");
+        myLeaf3 = QName.create(fooModuleQName, "my-leaf-3");
+        myLeaf2 = QName.create(fooModuleQName, "my-leaf-2");
+        myAnyXMLDataFoo = QName.create(fooModuleQName, "my-anyxml-data");
+        schemaContext = RetestUtils.parseYangSources(new File(getClass().getResource("/anyxml-support/yang/foo.yang")
+                .toURI()), new File(getClass().getResource("/anyxml-support/yang/bar.yang").toURI()), new File(getClass().getResource("/anyxml-support/yang/yang-ext.yang").toURI()));
+    }
+
+    @Test
+    public void testRawAnyXMLFromBar() throws Exception {
+        final Document doc = loadDocument("/anyxml-support/xml/bar.xml");
+
+        DataSchemaNode barContainer = schemaContext.getDataChildByName("bar");
+        assertTrue(barContainer instanceof ContainerSchemaNode);
+        final YangModeledAnyXmlSchemaNode yangModeledAnyXML = new YangModeledAnyXMLSchemaNodeImplTest(myAnyXMLDataBar,
+                (ContainerSchemaNode) barContainer);
+
+        final YangModeledAnyXmlNode output = DomToNormalizedNodeParserFactory
+                .getInstance(DomUtils.defaultValueCodecProvider(), schemaContext).getYangModeledAnyXmlNodeParser()
+                .parse(Collections.singletonList(doc.getDocumentElement()), yangModeledAnyXML);
+
+        assertNotNull(output);
+
+        DataSchemaNode schemaOfAnyXmlData = output.getSchemaOfAnyXmlData();
+        assertEquals(barContainer, schemaOfAnyXmlData);
+
+        Collection<DataContainerChild<? extends PathArgument, ?>> value = output.getValue();
+        assertEquals(2, value.size());
+
+        Optional<DataContainerChild<? extends PathArgument, ?>> child = output
+                .getChild(new NodeIdentifier(myContainer1));
+        assertTrue(child.orNull() instanceof ContainerNode);
+        ContainerNode myContainerNode1 = (ContainerNode) child.get();
+
+        Optional<DataContainerChild<? extends PathArgument, ?>> child2 = myContainerNode1.getChild(new NodeIdentifier(
+                myLeaf1));
+        assertTrue(child2.orNull() instanceof LeafNode);
+        LeafNode<?> LeafNode1 = (LeafNode<?>) child2.get();
+
+        Object leafNode1Value = LeafNode1.getValue();
+        assertEquals("value1", leafNode1Value);
+    }
+
+    @Test
+    public void testRealSchemaContextFromFoo() throws Exception {
+        final Document doc = loadDocument("/anyxml-support/xml/foo.xml");
+
+        final ContainerNode output = DomToNormalizedNodeParserFactory
+                .getInstance(DomUtils.defaultValueCodecProvider(), schemaContext).getContainerNodeParser()
+                .parse(Collections.singletonList(doc.getDocumentElement()), schemaContext);
+
+        assertNotNull(output);
+
+        Optional<DataContainerChild<? extends PathArgument, ?>> child = output.getChild(new NodeIdentifier(
+                myAnyXMLDataFoo));
+        assertTrue(child.orNull() instanceof YangModeledAnyXmlNode);
+        YangModeledAnyXmlNode yangModeledAnyXmlNode = (YangModeledAnyXmlNode) child.get();
+
+        DataSchemaNode schemaOfAnyXmlData = yangModeledAnyXmlNode.getSchemaOfAnyXmlData();
+        DataSchemaNode expectedSchemaOfAnyXmlData = schemaContext.getDataChildByName(myContainer2);
+        assertEquals(expectedSchemaOfAnyXmlData, schemaOfAnyXmlData);
+
+        Collection<DataContainerChild<? extends PathArgument, ?>> value = yangModeledAnyXmlNode.getValue();
+        assertEquals(2, value.size());
+
+        Optional<DataContainerChild<? extends PathArgument, ?>> child2 = yangModeledAnyXmlNode
+                .getChild(new NodeIdentifier(innerContainer));
+        assertTrue(child2.orNull() instanceof ContainerNode);
+        ContainerNode innerContainerNode = (ContainerNode) child2.get();
+
+        Optional<DataContainerChild<? extends PathArgument, ?>> child3 = innerContainerNode
+                .getChild(new NodeIdentifier(myLeaf2));
+        assertTrue(child3.orNull() instanceof LeafNode);
+        LeafNode<?> LeafNode2 = (LeafNode<?>) child3.get();
+
+        Object leafNode2Value = LeafNode2.getValue();
+        assertEquals("any-xml-leaf-2-value", leafNode2Value);
+
+        Optional<DataContainerChild<? extends PathArgument, ?>> child4 = yangModeledAnyXmlNode
+                .getChild(new NodeIdentifier(myLeaf3));
+        assertTrue(child4.orNull() instanceof LeafNode);
+        LeafNode<?> LeafNode3 = (LeafNode<?>) child4.get();
+
+        Object leafNode3Value = LeafNode3.getValue();
+        assertEquals("any-xml-leaf-3-value", leafNode3Value);
+    }
+
+    private static Document loadDocument(final String xmlPath) throws IOException, SAXException {
+        final InputStream resourceAsStream = YangModeledAnyXMLDeserializationTest.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 {
+            dBuilder = BUILDERFACTORY.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;
+    }
+
+    static class YangModeledAnyXMLSchemaNodeImplTest implements YangModeledAnyXmlSchemaNode {
+        private final QName qName;
+        private final ContainerSchemaNode contentSchema;
+
+        public YangModeledAnyXMLSchemaNodeImplTest(QName qName, ContainerSchemaNode contentSchema) {
+            this.qName = qName;
+            this.contentSchema = contentSchema;
+        }
+
+        @Override
+        public boolean isAugmenting() {
+            return false;
+        }
+
+        @Override
+        public boolean isAddedByUses() {
+            return false;
+        }
+
+        @Override
+        public boolean isConfiguration() {
+            return false;
+        }
+
+        @Override
+        public ConstraintDefinition getConstraints() {
+            return null;
+        }
+
+        @Override
+        public QName getQName() {
+            return qName;
+        }
+
+        @Override
+        public SchemaPath getPath() {
+            return null;
+        }
+
+        @Override
+        public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+            return null;
+        }
+
+        @Override
+        public String getDescription() {
+            return null;
+        }
+
+        @Override
+        public String getReference() {
+            return null;
+        }
+
+        @Override
+        public Status getStatus() {
+            return null;
+        }
+
+        @Override
+        public ContainerSchemaNode getSchemaOfAnyXmlData() {
+            return contentSchema;
+        }
+    }
+}
diff --git a/yang/yang-data-impl/src/test/resources/anyxml-support/xml/bar.xml b/yang/yang-data-impl/src/test/resources/anyxml-support/xml/bar.xml
new file mode 100644 (file)
index 0000000..2bf7dbe
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<my-anyxml-data xmlns="bar">
+    <my-container-1>
+        <my-leaf-1>value1</my-leaf-1>
+    </my-container-1>
+    <my-container-2>
+        <my-leaf-2>value2</my-leaf-2>
+    </my-container-2>
+</my-anyxml-data>
\ No newline at end of file
diff --git a/yang/yang-data-impl/src/test/resources/anyxml-support/xml/foo.xml b/yang/yang-data-impl/src/test/resources/anyxml-support/xml/foo.xml
new file mode 100644 (file)
index 0000000..2492e95
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<foo xmlns="foo">
+    <my-container-1>
+        <my-leaf-1>value1</my-leaf-1>
+    </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-container-2>
+
+    <my-anyxml-data>
+        <inner-container>
+            <my-leaf-2>any-xml-leaf-2-value</my-leaf-2>
+        </inner-container>
+        <my-leaf-3>any-xml-leaf-3-value</my-leaf-3>
+    </my-anyxml-data>
+</foo>
\ No newline at end of file
diff --git a/yang/yang-data-impl/src/test/resources/anyxml-support/yang/bar.yang b/yang/yang-data-impl/src/test/resources/anyxml-support/yang/bar.yang
new file mode 100644 (file)
index 0000000..b8c57a8
--- /dev/null
@@ -0,0 +1,18 @@
+module bar {
+    namespace "bar";
+    prefix bar;
+
+    container bar {
+        container my-container-1 {
+            leaf my-leaf-1 {
+                type string;
+            }
+        }
+
+        container my-container-2 {
+            leaf my-leaf-2 {
+                type string;
+            }
+        }
+    }
+}
diff --git a/yang/yang-data-impl/src/test/resources/anyxml-support/yang/foo.yang b/yang/yang-data-impl/src/test/resources/anyxml-support/yang/foo.yang
new file mode 100644 (file)
index 0000000..8d9920a
--- /dev/null
@@ -0,0 +1,27 @@
+module foo {
+    namespace "foo";
+    prefix foo;
+    
+    import yang-ext { prefix ext; revision-date 2013-07-09; }
+    
+    container my-container-1 {
+        leaf my-leaf-1 {
+            type string;
+        }
+    }
+
+    container my-container-2 {
+        container inner-container {
+            leaf my-leaf-2 {
+                type string;
+            }
+        }
+        leaf my-leaf-3 {
+            type string;
+        }
+    }
+
+    anyxml my-anyxml-data {
+        ext:anyxml-schema-location "/my-container-2";
+    }
+}
diff --git a/yang/yang-data-impl/src/test/resources/anyxml-support/yang/yang-ext.yang b/yang/yang-data-impl/src/test/resources/anyxml-support/yang/yang-ext.yang
new file mode 100644 (file)
index 0000000..2cdc211
--- /dev/null
@@ -0,0 +1,75 @@
+module yang-ext {
+    yang-version 1;
+    namespace "urn:opendaylight:yang:extension:yang-ext";
+    prefix "ext";
+
+    contact "Anton Tkacik <ttkacik@cisco.com>";
+
+    description
+        "Copyright (c) 2013 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";
+
+    revision "2013-07-09" {
+        description "";
+    }
+
+    // Augmentation name
+
+    extension "augment-identifier" {
+        description
+                "YANG language extension which assigns an identifier to augmentation.
+                Augment identifier is used to identify specific augment statement
+                by name. The identifier syntax is defined formally defined by
+                the rule 'identifier' in Section 12 of RFC 6020. All augment identifiers
+                defined in a namespace MUST be unique. The namespace of augment
+                identifiers is shared by module and its submodules.";
+
+        /*
+                Discussion:
+                This extension allows for ease of development / debug
+                of YANG modules and it is suitable for code generation,
+                where each augment statement is nicely identified by
+                unique name instead of combination of augment target
+                and when condition. 
+            */
+        argument "identifier";
+    }
+
+    // Context-aware RPCs
+
+    grouping rpc-context-ref {
+        description
+                "A reference to RPC context.";
+        leaf context-instance {
+            type instance-identifier;
+            description "Pointer to the context. ";
+        }
+    }
+
+    extension "rpc-context-instance" {
+        description
+                "YANG language extension which defines enclosing (parent) schema
+                node as referencable context for RPCs. The argument is identity
+                which is used to identify RPC context type.";
+
+        argument "context-type";
+    }
+
+    extension "context-reference" {
+        argument "context-type";
+    }
+
+    extension "context-instance" {
+        argument "context-type";
+    }
+
+    extension "instance-target" {
+        argument "path";
+    }
+
+    extension "anyxml-schema-location" {
+        argument "target-node";
+    }
+}
index 24daa344e2cbc356048601a2ac56af1d583dad4e..5da991b527a05b561303f73571a63dc1152c393c 100644 (file)
@@ -79,7 +79,7 @@ public class YangStatementParserListenerImpl extends YangStatementParserBaseList
                 }
                 writer.argumentValue(argument, ref);
             } else {
-                writer.startStatement(QName.create(validStatementDefinition.getModule(), keywordTxt), ref);
+                writer.startStatement(validStatementDefinition, ref);
                 if (argument != null) {
                     writer.argumentValue(argument, ref);
                 }
index d72c644415cdd8aac2513551af0ec905aeb0a358..5113e68dfd81c052a97589f545111b527dbd9e23 100644 (file)
@@ -147,8 +147,7 @@ public class YinStatementParserImpl {
                 if (identifier.equals(Rfc6020Mapping.TYPE.getStatementName())) {
                     isType = true;
                 } else {
-                    startStatement(QName.create(validStatementDefinition.getModule(), getElementFullName
-                            (inputReader)),  ref);
+                    startStatement(validStatementDefinition, ref);
                     if (isStatementWithYinElement(identifier, stmtDef)) {
                         action = false;
                     }
index 5f0b63f451d1185c09ff46699e3ca10ebecc15d6..362fd04547b535ee2533c3ebc7fc51ea169e73c5 100644 (file)
@@ -61,7 +61,8 @@ public final class SubstatementValidator {
         }
     }
 
-    public void validate(StmtContext ctx) throws InvalidSubstatementException, MissingSubstatementException{
+    public void validate(final StmtContext<?, ?, ?> ctx) throws InvalidSubstatementException,
+            MissingSubstatementException {
         final Map<StatementDefinition, Integer> stmtDefMap = new HashMap<>();
         final Map<StatementDefinition, Integer> validatedMap = new HashMap<>();
         final Collection<StatementContextBase<?, ?, ?>> substatementsInit = new ArrayList<>();
@@ -78,15 +79,16 @@ public final class SubstatementValidator {
         }
 
         if (stmtDefMap.isEmpty() && specialCase == SpecialCase.NOTNULL) {
-            throw new InvalidSubstatementException(String.format("%s must contain atleast 1 element. Error in module " +
-                            "%s (%s)", currentStatement, ctx.getRoot().getStatementArgument(), ctx.getFromNamespace
-                            (ModuleCtxToModuleQName.class, ctx.getRoot())), ctx.getStatementSourceReference());
+            throw new InvalidSubstatementException(String.format("%s must contain atleast 1 element. Error in module "
+                    + "%s (%s)", currentStatement, ctx.getRoot().getStatementArgument(),
+                    ctx.getFromNamespace(ModuleCtxToModuleQName.class, ctx.getRoot())),
+                    ctx.getStatementSourceReference());
         }
 
         for (Map.Entry entry : stmtDefMap.entrySet()) {
             final StatementDefinition key = (StatementDefinition) entry.getKey();
             if (!cardinalityMap.containsKey(key)) {
-                if (ctx.getFromNamespace(ExtensionNamespace.class, key.getArgumentName()) != null) {
+                if (ctx.getFromNamespace(ExtensionNamespace.class, key.getStatementName()) != null) {
                     continue;
                 }
                 throw new InvalidSubstatementException(String.format("%s is not valid for %s. Error in module %s (%s)",
@@ -94,16 +96,16 @@ public final class SubstatementValidator {
                         ctx.getFromNamespace(ModuleCtxToModuleQName.class, ctx.getRoot())),
                         ctx.getStatementSourceReference());
             }
-            if (cardinalityMap.get(key).getMin() > (Integer)entry.getValue()) {
-                throw new InvalidSubstatementException(String.format("Minimal count of %s for %s is %s, detected %s. " +
-                                "Error in module %s (%s)", key, currentStatement, cardinalityMap.get(key).getMin(),
+            if (cardinalityMap.get(key).getMin() > (Integer) entry.getValue()) {
+                throw new InvalidSubstatementException(String.format("Minimal count of %s for %s is %s, detected %s. "
+                        + "Error in module %s (%s)", key, currentStatement, cardinalityMap.get(key).getMin(),
                         entry.getValue(), ctx.getRoot().getStatementArgument(),
                         ctx.getFromNamespace(ModuleCtxToModuleQName.class, ctx.getRoot())),
                         ctx.getStatementSourceReference());
             }
-            if (cardinalityMap.get(key).getMax() < (Integer)entry.getValue()) {
-                throw new InvalidSubstatementException(String.format("Maximal count of %s for %s is %s, detected %s. " +
-                                "Error in module %s (%s)", key, currentStatement, cardinalityMap.get(key).getMax(),
+            if (cardinalityMap.get(key).getMax() < (Integer) entry.getValue()) {
+                throw new InvalidSubstatementException(String.format("Maximal count of %s for %s is %s, detected %s. "
+                        + "Error in module %s (%s)", key, currentStatement, cardinalityMap.get(key).getMax(),
                         entry.getValue(), ctx.getRoot().getStatementArgument(),
                         ctx.getFromNamespace(ModuleCtxToModuleQName.class, ctx.getRoot())),
                         ctx.getStatementSourceReference());
@@ -114,11 +116,11 @@ public final class SubstatementValidator {
         final MapDifference<StatementDefinition, Object> diff = Maps.difference(validatedMap, cardinalityMap);
 
         for (Map.Entry entry : diff.entriesOnlyOnRight().entrySet()) {
-            final int min = ((Cardinality)entry.getValue()).getMin();
+            final int min = ((Cardinality) entry.getValue()).getMin();
             if (min > 0) {
-                throw new MissingSubstatementException(String.format("%s is missing %s. Minimal count is %s. Error in" +
-                        "  module %s (%s)", currentStatement, entry.getKey(), min, ctx.getRoot().getStatementArgument(),
-                        ctx.getFromNamespace(ModuleCtxToModuleQName.class, ctx.getRoot())),
+                throw new MissingSubstatementException(String.format("%s is missing %s. Minimal count is %s. Error in"
+                        + "  module %s (%s)", currentStatement, entry.getKey(), min, ctx.getRoot()
+                        .getStatementArgument(), ctx.getFromNamespace(ModuleCtxToModuleQName.class, ctx.getRoot())),
                         ctx.getStatementSourceReference());
             }
         }
index 3e830d80c71c2f409bfa19ef090becef6211ee95..77b285f16a9a3137dd17a1ac8b6fb3acee136515 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.parser.spi.meta;
 
 import com.google.common.base.Function;
 import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
 import java.util.Collection;
@@ -81,6 +82,18 @@ public final class StmtContextUtils {
         return null;
     }
 
+    @SuppressWarnings("unchecked")
+    public static <AT,DT extends DeclaredStatement<AT>> Collection<StmtContext<AT, DT, ?>> findAllDeclaredSubstatement(
+            final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
+        ImmutableList.Builder<StmtContext<AT, DT, ?>> listBuilder = ImmutableList.builder();
+        for (StmtContext<?, ?, ?> subStmtContext : stmtContext.declaredSubstatements()) {
+            if (producesDeclared(subStmtContext,declaredType)) {
+                listBuilder.add((StmtContext<AT, DT, ?>) subStmtContext);
+            }
+        }
+        return listBuilder.build();
+    }
+
     @SuppressWarnings("unchecked")
     public static <AT,DT extends DeclaredStatement<AT>> StmtContext<AT, ?, ?> findFirstEffectiveSubstatement(
             final StmtContext<?, ?, ?> stmtContext, final Class<DT> declaredType) {
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/AnyxmlSchemaLocationNamespace.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/AnyxmlSchemaLocationNamespace.java
new file mode 100644 (file)
index 0000000..e14c779
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015 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.spi.source;
+
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
+
+/**
+ *
+ * Source-specific mapping of prefixes to namespaces
+ *
+ */
+public interface AnyxmlSchemaLocationNamespace
+        extends
+        IdentifierNamespace<StatementDefinition, Mutable<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>, EffectiveStatement<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>>>> {
+
+}
index 3f34be5ffb38b84388327172a199b8a482d9640b..64351b8818efafe5e5ba4ea85b4c9c2261ecd774 100644 (file)
@@ -99,24 +99,21 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
 
         if (def == null) {
             //unknown-stmts (from import, include or local-scope)
-            if (qNameToStmtDefMap.get(Utils.trimPrefix(name)) != null) {
-                QName key = Utils.qNameFromArgument(current, name.getLocalName());
-                if (key != null) {
-                    final StatementContextBase<?,?,?> extension = (StatementContextBase<?, ?, ?>) currentContext
-                            .getAllFromNamespace(ExtensionNamespace.class).get(key);
-                    if (extension != null) {
-                        final QName arg = (QName) extension.getStatementArgument();
-                        final QName qName = current.getFromNamespace(QNameCacheNamespace.class,
+            if (qNameToStmtDefMap.get(name) != null) {
+                final StatementContextBase<?, ?, ?> extension = (StatementContextBase<?, ?, ?>) currentContext
+                        .getAllFromNamespace(ExtensionNamespace.class).get(name);
+                if (extension != null) {
+                    final QName arg = (QName) extension.getStatementArgument();
+                    final QName qName = current.getFromNamespace(QNameCacheNamespace.class,
                             QName.create(arg, extension.getIdentifier().getArgument()));
 
-                        def = new StatementDefinitionContext<>(new UnknownStatementImpl.Definition
-                                (getNewStatementDefinition(qName)));
-                    } else {
-                        throw new IllegalArgumentException("Not found unknown statement: " + name);
-                    }
+                    def = new StatementDefinitionContext<>(new UnknownStatementImpl.Definition(
+                            getNewStatementDefinition(qName)));
+                } else {
+                    throw new IllegalArgumentException("Not found unknown statement: " + name);
                 }
             } else {
-                //type-body-stmts
+                // type-body-stmts
                 def = resolveTypeBodyStmts(name.getLocalName());
             }
         }
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AnyxmlSchemaLocationStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/AnyxmlSchemaLocationStatementImpl.java
new file mode 100644 (file)
index 0000000..315b2f6
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) 2015 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;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
+import org.opendaylight.yangtools.yang.parser.spi.source.AnyxmlSchemaLocationNamespace;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.AnyxmlSchemaLocationEffectiveStatementImpl;
+
+@Beta
+public final class AnyxmlSchemaLocationStatementImpl extends AbstractDeclaredStatement<SchemaNodeIdentifier> implements
+        UnknownStatement<SchemaNodeIdentifier> {
+
+    AnyxmlSchemaLocationStatementImpl(
+            StmtContext<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>, ?> context) {
+        super(context);
+    }
+
+    public static class AnyxmlSchemaLocationSupport
+            extends
+            AbstractStatementSupport<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>, EffectiveStatement<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>>> {
+
+        public AnyxmlSchemaLocationSupport() {
+            super(SupportedExtensionsMapping.ANYXML_SCHEMA_LOCATION);
+        }
+
+        @Override
+        public SchemaNodeIdentifier parseArgumentValue(StmtContext<?, ?, ?> ctx, String value) {
+            return Utils.nodeIdentifierFromPath(ctx, value);
+        }
+
+        @Override
+        public void onFullDefinitionDeclared(
+                Mutable<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>, EffectiveStatement<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>>> stmt) {
+            stmt.getParentContext().addToNs(AnyxmlSchemaLocationNamespace.class,
+                    SupportedExtensionsMapping.ANYXML_SCHEMA_LOCATION, stmt);
+        }
+
+        @Override
+        public UnknownStatement<SchemaNodeIdentifier> createDeclared(
+                StmtContext<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>, ?> ctx) {
+            return new AnyxmlSchemaLocationStatementImpl(ctx);
+        }
+
+        @Override
+        public EffectiveStatement<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>> createEffective(
+                final StmtContext<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>, EffectiveStatement<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>>> ctx) {
+            return new AnyxmlSchemaLocationEffectiveStatementImpl(ctx);
+        }
+    }
+
+    @Override
+    public SchemaNodeIdentifier getArgument() {
+        return argument();
+    }
+}
index 135b20988bdd3722650896b277bde734c72df706..8cc179e0ae0d07638658b6fe05d6ef09ea3eedc1 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -9,10 +9,14 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
 
 import static org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator.MAX;
 
+import com.google.common.base.Optional;
 import java.util.Collection;
+import java.util.Map;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ConfigStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionStatement;
@@ -20,15 +24,20 @@ import org.opendaylight.yangtools.yang.model.api.stmt.IfFeatureStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.MustStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
 import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement;
 import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
+import org.opendaylight.yangtools.yang.parser.spi.source.AnyxmlSchemaLocationNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.AnyXmlEffectiveStatementImpl;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.YangModeledAnyXmlEffectiveStatementImpl;
 
 public class AnyxmlStatementImpl extends AbstractDeclaredStatement<QName> implements AnyxmlStatement {
     private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(Rfc6020Mapping
@@ -41,21 +50,23 @@ public class AnyxmlStatementImpl extends AbstractDeclaredStatement<QName> implem
             .add(Rfc6020Mapping.REFERENCE, 0, 1)
             .add(Rfc6020Mapping.STATUS, 0, 1)
             .add(Rfc6020Mapping.WHEN, 0, 1)
+            .add(SupportedExtensionsMapping.ANYXML_SCHEMA_LOCATION, 0, 1)
             .build();
 
-    protected AnyxmlStatementImpl(StmtContext<QName, AnyxmlStatement,?> context) {
+    protected AnyxmlStatementImpl(StmtContext<QName, AnyxmlStatement, ?> context) {
         super(context);
     }
 
-    public static class Definition extends AbstractStatementSupport<QName,AnyxmlStatement,EffectiveStatement<QName,AnyxmlStatement>> {
+    public static class Definition extends
+            AbstractStatementSupport<QName, AnyxmlStatement, EffectiveStatement<QName, AnyxmlStatement>> {
 
         public Definition() {
             super(Rfc6020Mapping.ANYXML);
         }
 
         @Override
-        public QName parseArgumentValue(StmtContext<?,?,?> ctx, String value) {
-            return Utils.qNameFromArgument(ctx,value);
+        public QName parseArgumentValue(StmtContext<?, ?, ?> ctx, String value) {
+            return Utils.qNameFromArgument(ctx, value);
         }
 
         @Override
@@ -64,13 +75,24 @@ public class AnyxmlStatementImpl extends AbstractDeclaredStatement<QName> implem
         }
 
         @Override
-        public AnyxmlStatement createDeclared(StmtContext<QName, AnyxmlStatement,?> ctx) {
+        public AnyxmlStatement createDeclared(StmtContext<QName, AnyxmlStatement, ?> ctx) {
             return new AnyxmlStatementImpl(ctx);
         }
 
         @Override
-        public EffectiveStatement<QName,AnyxmlStatement> createEffective(StmtContext<QName,AnyxmlStatement,EffectiveStatement<QName,AnyxmlStatement>> ctx) {
-           return new AnyXmlEffectiveStatementImpl(ctx);
+        public EffectiveStatement<QName, AnyxmlStatement> createEffective(
+                final StmtContext<QName, AnyxmlStatement, EffectiveStatement<QName, AnyxmlStatement>> ctx) {
+            Map<StatementDefinition, Mutable<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>, EffectiveStatement<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>>>> schemaLocations = ctx
+                    .getAllFromCurrentStmtCtxNamespace(AnyxmlSchemaLocationNamespace.class);
+            if (schemaLocations != null && !schemaLocations.isEmpty()) {
+                SchemaNodeIdentifier anyXmlSchemaNodeIdentifier = schemaLocations.values().iterator().next()
+                        .getStatementArgument();
+                Optional<ContainerSchemaNode> anyXmlSchema = getAnyXmlSchema(ctx, anyXmlSchemaNodeIdentifier);
+                if (anyXmlSchema.isPresent()) {
+                    return new YangModeledAnyXmlEffectiveStatementImpl(ctx, anyXmlSchema.get());
+                }
+            }
+            return new AnyXmlEffectiveStatementImpl(ctx);
         }
 
         @Override
@@ -79,6 +101,19 @@ public class AnyxmlStatementImpl extends AbstractDeclaredStatement<QName> implem
             super.onFullDefinitionDeclared(stmt);
             SUBSTATEMENT_VALIDATOR.validate(stmt);
         }
+
+        private Optional<ContainerSchemaNode> getAnyXmlSchema(
+                StmtContext<QName, AnyxmlStatement, EffectiveStatement<QName, AnyxmlStatement>> ctx,
+                SchemaNodeIdentifier contentSchemaPath) {
+            final StatementContextBase<?, ?, ?> findNode = Utils.findNode(ctx.getRoot(), contentSchemaPath);
+            if (findNode != null) {
+                final EffectiveStatement<?, ?> anyXmlSchemaNode = findNode.buildEffective();
+                if (anyXmlSchemaNode instanceof ContainerSchemaNode) {
+                    return Optional.of((ContainerSchemaNode) anyXmlSchemaNode);
+                }
+            }
+            return Optional.absent();
+        }
     }
 
     @Override
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SupportedExtensionsMapping.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SupportedExtensionsMapping.java
new file mode 100644 (file)
index 0000000..d68382d
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 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;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.AnyxmlSchemaLocationEffectiveStatementImpl;
+
+@Beta
+public enum SupportedExtensionsMapping implements StatementDefinition {
+    ANYXML_SCHEMA_LOCATION("urn:opendaylight:yang:extension:yang-ext", "2013-07-09",
+        AnyxmlSchemaLocationStatementImpl.class, AnyxmlSchemaLocationEffectiveStatementImpl.class,
+        "anyxml-schema-location", "target-node");
+
+    private final Class<? extends DeclaredStatement<?>> type;
+    private final Class<? extends EffectiveStatement<?, ?>> effectiveType;
+    private final QName name;
+    private final QName argument;
+
+    private SupportedExtensionsMapping(final String namespace, final String revision,
+            final Class<? extends DeclaredStatement<?>> declared,
+                    final Class<? extends EffectiveStatement<?, ?>> effective, final String nameStr,
+                            final String argumentStr) {
+        type = Preconditions.checkNotNull(declared);
+        effectiveType = Preconditions.checkNotNull(effective);
+        name = createQName(namespace, revision, nameStr);
+        argument = createQName(namespace, revision, argumentStr);
+    }
+
+    @Nonnull
+    private static QName createQName(final String namespace, final String revision, final String localName) {
+        return QName.create(namespace, revision, localName).intern();
+    }
+
+    @Override
+    public QName getStatementName() {
+        return name;
+    }
+
+    @Override
+    @Nullable
+    public QName getArgumentName() {
+        return argument;
+    }
+
+    @Override
+    @Nonnull
+    public Class<? extends DeclaredStatement<?>> getDeclaredRepresentationClass() {
+        return type;
+    }
+
+    @Override
+    public Class<? extends EffectiveStatement<?, ?>> getEffectiveRepresentationClass() {
+        return effectiveType;
+    }
+}
index 85124a198f4f478ac084322b70f9550098b5eae7..4d3889680341b395dd4afad053a469a4ee38f287 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
 import static org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.global;
 import static org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.sourceLocal;
 import static org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.treeScoped;
+
 import com.google.common.collect.ImmutableMap;
 import java.util.Map;
 import org.opendaylight.yangtools.yang.parser.spi.ExtensionNamespace;
@@ -23,6 +24,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.DerivedIdentitiesNamespac
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
 import org.opendaylight.yangtools.yang.parser.spi.meta.QNameCacheNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
+import org.opendaylight.yangtools.yang.parser.spi.source.AnyxmlSchemaLocationNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToModuleContext;
 import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleIdentifier;
 import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleName;
@@ -147,6 +149,8 @@ public final class YangInferencePipeline {
             .addSupport(new FeatureStatementImpl.Definition())
             .addSupport(new PositionStatementImpl.Definition())
             .addSupport(new ValueStatementImpl.Definition())
+            .addSupport(new AnyxmlSchemaLocationStatementImpl.AnyxmlSchemaLocationSupport())
+            .addSupport(treeScoped(AnyxmlSchemaLocationNamespace.class))
             .addSupport(global(StmtOrderingNamespace.class))
             .build();
 
index ec164357064ae4ae9bdf87e38dddf0788dd358d0..b0b21af6256bf3705a9f62224dabea2c85228743 100644 (file)
@@ -16,7 +16,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 
-public final class AnyXmlEffectiveStatementImpl extends AbstractEffectiveDataSchemaNode<AnyxmlStatement> implements
+public class AnyXmlEffectiveStatementImpl extends AbstractEffectiveDataSchemaNode<AnyxmlStatement> implements
         AnyXmlSchemaNode, DerivableSchemaNode {
 
     private final AnyXmlSchemaNode original;
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/AnyxmlSchemaLocationEffectiveStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/AnyxmlSchemaLocationEffectiveStatementImpl.java
new file mode 100644 (file)
index 0000000..27e4cb0
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 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 com.google.common.annotations.Beta;
+import java.util.Objects;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+
+@Beta
+public final class AnyxmlSchemaLocationEffectiveStatementImpl extends
+        UnknownEffectiveStatementBase<SchemaNodeIdentifier> {
+
+    private final SchemaPath path;
+
+    public AnyxmlSchemaLocationEffectiveStatementImpl(
+            final StmtContext<SchemaNodeIdentifier, UnknownStatement<SchemaNodeIdentifier>, ?> ctx) {
+        super(ctx);
+
+        path = ctx.getParentContext().getSchemaPath().get().createChild(getNodeType());
+    }
+
+    @Override
+    public QName getQName() {
+        return getNodeType();
+    }
+
+    @Override
+    public SchemaPath getPath() {
+        return path;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + Objects.hashCode(path);
+        result = prime * result + Objects.hashCode(getNodeType());
+        result = prime * result + Objects.hashCode(getNodeParameter());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        AnyxmlSchemaLocationEffectiveStatementImpl other = (AnyxmlSchemaLocationEffectiveStatementImpl) obj;
+        if (!Objects.equals(path, other.path)) {
+            return false;
+        }
+        if (!Objects.equals(getNodeType(), other.getNodeType())) {
+            return false;
+        }
+        if (!Objects.equals(getNodeParameter(), other.getNodeParameter())) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/UnknownEffectiveStatementBase.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/UnknownEffectiveStatementBase.java
new file mode 100644 (file)
index 0000000..738f70d
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015 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 com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+import java.util.List;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ExtensionStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
+import org.opendaylight.yangtools.yang.parser.spi.ExtensionNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.TypeOfCopy;
+
+public abstract class UnknownEffectiveStatementBase<A> extends AbstractEffectiveDocumentedNode<A, UnknownStatement<A>>
+        implements UnknownSchemaNode {
+
+    private final boolean addedByUses;
+    private final boolean addedByAugmentation;
+
+    private final ExtensionDefinition extension;
+    private final List<UnknownSchemaNode> unknownNodes;
+    private final QName nodeType;
+    private final String nodeParameter;
+
+    public UnknownEffectiveStatementBase(final StmtContext<A, UnknownStatement<A>, ?> ctx) {
+        super(ctx);
+
+        final StmtContext<?, ExtensionStatement, EffectiveStatement<QName, ExtensionStatement>> extensionInit = ctx
+                .getFromNamespace(ExtensionNamespace.class, ctx.getPublicDefinition().getStatementName());
+
+        if (extensionInit == null) {
+            extension = null;
+            nodeType = ctx.getPublicDefinition().getArgumentName();
+        } else {
+            extension = (ExtensionEffectiveStatementImpl) extensionInit.buildEffective();
+            nodeType = extension.getQName();
+        }
+
+        // initCopyType
+        List<TypeOfCopy> copyTypesFromOriginal = ctx.getCopyHistory();
+        if (copyTypesFromOriginal.contains(TypeOfCopy.ADDED_BY_USES_AUGMENTATION)) {
+            this.addedByUses = this.addedByAugmentation = true;
+        } else {
+            this.addedByAugmentation = copyTypesFromOriginal.contains(TypeOfCopy.ADDED_BY_AUGMENTATION);
+            this.addedByUses = copyTypesFromOriginal.contains(TypeOfCopy.ADDED_BY_USES);
+        }
+
+        nodeParameter = (ctx.rawStatementArgument() == null) ? "" : ctx.rawStatementArgument();
+
+        // TODO init other fields (see Bug1412Test)
+        final Builder<UnknownSchemaNode> builder = ImmutableList.builder();
+        for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
+            if (effectiveStatement instanceof UnknownSchemaNode) {
+                builder.add((UnknownSchemaNode) effectiveStatement);
+            }
+        }
+        unknownNodes = builder.build();
+    }
+
+    @Override
+    public boolean isAddedByAugmentation() {
+        return addedByAugmentation;
+    }
+
+    @Override
+    public QName getNodeType() {
+        return nodeType;
+    }
+
+    @Override
+    public String getNodeParameter() {
+        return nodeParameter;
+    }
+
+    @Override
+    public boolean isAddedByUses() {
+        return addedByUses;
+    }
+
+    @Override
+    public ExtensionDefinition getExtensionDefinition() {
+        return extension;
+    }
+
+    @Override
+    public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+        return unknownNodes;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(nodeType.getNamespace());
+        sb.append(":");
+        sb.append(nodeType.getLocalName());
+        sb.append(" ");
+        sb.append(nodeParameter);
+        return sb.toString();
+    }
+
+}
index 0f14b729ccfb8471452a20a34934a5c04a29d9e3..2ee3f8283dc7c087ddd69b8f0fc3ffca30199039 100644 (file)
@@ -8,57 +8,22 @@
 
 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective;
 
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
-import java.util.List;
 import java.util.Objects;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.ExtensionStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
-import org.opendaylight.yangtools.yang.parser.spi.ExtensionNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.TypeOfCopy;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
 
-public final class UnknownEffectiveStatementImpl extends AbstractEffectiveDocumentedNode<String, UnknownStatement<String>>
-        implements UnknownSchemaNode {
+public final class UnknownEffectiveStatementImpl extends UnknownEffectiveStatementBase<String> {
 
-    private final boolean addedByUses;
-    private final boolean addedByAugmentation;
     private final QName maybeQNameArgument;
     private final SchemaPath path;
-    private final ExtensionDefinition extension;
-    private final List<UnknownSchemaNode> unknownNodes;
-    private final QName nodeType;
-    private final String nodeParameter;
 
     public UnknownEffectiveStatementImpl(final StmtContext<String, UnknownStatement<String>, ?> ctx) {
         super(ctx);
 
-        final StmtContext<?, ExtensionStatement, EffectiveStatement<QName, ExtensionStatement>> extensionInit = ctx
-                .getFromNamespace(ExtensionNamespace.class, ctx.getPublicDefinition().getStatementName());
-
-        if (extensionInit == null) {
-            extension = null;
-            nodeType = ctx.getPublicDefinition().getArgumentName();
-        } else {
-            extension = (ExtensionEffectiveStatementImpl) extensionInit.buildEffective();
-            nodeType = extension.getQName();
-        }
-
-        // initCopyType
-        List<TypeOfCopy> copyTypesFromOriginal = ctx.getCopyHistory();
-        if (copyTypesFromOriginal.contains(TypeOfCopy.ADDED_BY_USES_AUGMENTATION)) {
-            this.addedByUses = this.addedByAugmentation = true;
-        } else {
-            this.addedByAugmentation = copyTypesFromOriginal.contains(TypeOfCopy.ADDED_BY_AUGMENTATION);
-            this.addedByUses = copyTypesFromOriginal.contains(TypeOfCopy.ADDED_BY_USES);
-        }
-
         // FIXME: Remove following section after fixing 4380
         final UnknownSchemaNode original = ctx.getOriginalCtx() == null ? null : (UnknownSchemaNode) ctx
                 .getOriginalCtx().buildEffective();
@@ -69,46 +34,11 @@ public final class UnknownEffectiveStatementImpl extends AbstractEffectiveDocume
             try {
                 maybeQNameArgumentInit = Utils.qNameFromArgument(ctx, argument());
             } catch (IllegalArgumentException e) {
-                maybeQNameArgumentInit = nodeType;
+                maybeQNameArgumentInit = getNodeType();
             }
             this.maybeQNameArgument = maybeQNameArgumentInit;
         }
         path = ctx.getParentContext().getSchemaPath().get().createChild(maybeQNameArgument);
-        nodeParameter = (ctx.rawStatementArgument() == null) ? "" : ctx.rawStatementArgument();
-
-        // TODO init other fields (see Bug1412Test)
-        final Builder<UnknownSchemaNode> builder = ImmutableList.builder();
-        for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
-            if (effectiveStatement instanceof UnknownEffectiveStatementImpl) {
-                builder.add((UnknownEffectiveStatementImpl) effectiveStatement);
-            }
-        }
-        unknownNodes = builder.build();
-    }
-
-    @Override
-    public boolean isAddedByAugmentation() {
-        return addedByAugmentation;
-    }
-
-    @Override
-    public QName getNodeType() {
-        return nodeType;
-    }
-
-    @Override
-    public String getNodeParameter() {
-        return nodeParameter;
-    }
-
-    @Override
-    public boolean isAddedByUses() {
-        return addedByUses;
-    }
-
-    @Override
-    public ExtensionDefinition getExtensionDefinition() {
-        return extension;
     }
 
     @Override
@@ -121,19 +51,14 @@ public final class UnknownEffectiveStatementImpl extends AbstractEffectiveDocume
         return path;
     }
 
-    @Override
-    public List<UnknownSchemaNode> getUnknownSchemaNodes() {
-        return unknownNodes;
-    }
-
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
         result = prime * result + Objects.hashCode(maybeQNameArgument);
         result = prime * result + Objects.hashCode(path);
-        result = prime * result + Objects.hashCode(nodeType);
-        result = prime * result + Objects.hashCode(nodeParameter);
+        result = prime * result + Objects.hashCode(getNodeType());
+        result = prime * result + Objects.hashCode(getNodeParameter());
         return result;
     }
 
@@ -155,24 +80,12 @@ public final class UnknownEffectiveStatementImpl extends AbstractEffectiveDocume
         if (!Objects.equals(path, other.path)) {
             return false;
         }
-        if (!Objects.equals(nodeType, other.nodeType)) {
+        if (!Objects.equals(getNodeType(), other.getNodeType())) {
             return false;
         }
-        if (!Objects.equals(nodeParameter, other.nodeParameter)) {
+        if (!Objects.equals(getNodeParameter(), other.getNodeParameter())) {
             return false;
         }
         return true;
     }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(nodeType.getNamespace());
-        sb.append(":");
-        sb.append(nodeType.getLocalName());
-        sb.append(" ");
-        sb.append(nodeParameter);
-        return sb.toString();
-    }
-
 }
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/YangModeledAnyXmlEffectiveStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/YangModeledAnyXmlEffectiveStatementImpl.java
new file mode 100644 (file)
index 0000000..d0b7f00
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015 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 com.google.common.base.Preconditions;
+import java.util.Objects;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.YangModeledAnyXmlSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AnyxmlStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+
+public final class YangModeledAnyXmlEffectiveStatementImpl extends AnyXmlEffectiveStatementImpl implements
+        YangModeledAnyXmlSchemaNode {
+
+    private final ContainerSchemaNode schemaOfAnyXmlData;
+
+    public YangModeledAnyXmlEffectiveStatementImpl(
+            final StmtContext<QName, AnyxmlStatement, EffectiveStatement<QName, AnyxmlStatement>> ctx, final ContainerSchemaNode contentSchema) {
+        super(ctx);
+        schemaOfAnyXmlData = Preconditions.checkNotNull(contentSchema);
+    }
+
+    @Override
+    public ContainerSchemaNode getSchemaOfAnyXmlData() {
+        return schemaOfAnyXmlData;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + Objects.hashCode(getQName());
+        result = prime * result + Objects.hashCode(getPath());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        YangModeledAnyXmlEffectiveStatementImpl other = (YangModeledAnyXmlEffectiveStatementImpl) obj;
+        return Objects.equals(getQName(), other.getQName()) && Objects.equals(getPath(), other.getPath());
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(YangModeledAnyXmlEffectiveStatementImpl.class.getSimpleName());
+        sb.append("[");
+        sb.append("qname=").append(getQName());
+        sb.append(", path=").append(getPath());
+        sb.append("]");
+        return sb.toString();
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug3874ExtensionTest.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug3874ExtensionTest.java
new file mode 100644 (file)
index 0000000..e27d6e0
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015 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.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.List;
+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.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.SupportedExtensionsMapping;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.AnyxmlSchemaLocationEffectiveStatementImpl;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.YangModeledAnyXmlEffectiveStatementImpl;
+
+public class Bug3874ExtensionTest {
+
+    @Test
+    public void test() throws SourceException, FileNotFoundException, ReactorException, URISyntaxException, ParseException {
+            SchemaContext context = StmtTestUtils.parseYangSources("/bugs/bug3874");
+
+            Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("1970-01-01");
+            QNameModule foo = QNameModule.create(new URI("foo"), revision);
+            QName myContainer2QName = QName.create(foo, "my-container-2");
+            QName myAnyXmlDataQName = QName.create(foo, "my-anyxml-data");
+
+            DataSchemaNode dataChildByName = context.getDataChildByName(myAnyXmlDataQName);
+            assertTrue(dataChildByName instanceof YangModeledAnyXmlEffectiveStatementImpl);
+            YangModeledAnyXmlEffectiveStatementImpl yangModeledAnyXml = (YangModeledAnyXmlEffectiveStatementImpl) dataChildByName;
+
+            SchemaNode myContainer2 = SchemaContextUtil.findDataSchemaNode(context, SchemaPath.create(true, myContainer2QName));
+            assertTrue(myContainer2 instanceof ContainerSchemaNode);
+            assertEquals(myContainer2, yangModeledAnyXml.getSchemaOfAnyXmlData());
+
+            List<UnknownSchemaNode> unknownSchemaNodes = yangModeledAnyXml.getUnknownSchemaNodes();
+            assertEquals(1, unknownSchemaNodes.size());
+
+            UnknownSchemaNode next = unknownSchemaNodes.iterator().next();
+            assertTrue(next instanceof UnknownSchemaNode);
+            assertTrue(next instanceof AnyxmlSchemaLocationEffectiveStatementImpl);
+            AnyxmlSchemaLocationEffectiveStatementImpl anyxmlSchemaLocationUnknownNode= (AnyxmlSchemaLocationEffectiveStatementImpl) next;
+            assertEquals(SupportedExtensionsMapping.ANYXML_SCHEMA_LOCATION.getStatementName(), anyxmlSchemaLocationUnknownNode.getNodeType());
+            assertEquals(SupportedExtensionsMapping.ANYXML_SCHEMA_LOCATION.getStatementName(), anyxmlSchemaLocationUnknownNode.getQName());
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug3874/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug3874/foo.yang
new file mode 100644 (file)
index 0000000..a36ba24
--- /dev/null
@@ -0,0 +1,35 @@
+module foo {
+    namespace "foo";
+    prefix foo;
+
+    import yang-ext { prefix ext; revision-date 2013-07-09; }
+
+    container my-container-1 {
+        leaf my-leaf-1 {
+            type string;
+        }
+    }
+
+    container my-container-2 {
+        container inner-container {
+            leaf my-leaf-2 {
+                type string;
+            }
+        }
+        leaf my-leaf-3 {
+            type string;
+        }
+    }
+
+    anyxml my-anyxml-data {
+        ext:anyxml-schema-location "/my-container-2";
+    }
+
+    foo:my-extension "arg-value" {
+        foo:my-extension "arg-value-2";
+    }
+
+    extension my-extension {
+        argument arg-name;
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug3874/yang-ext.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug3874/yang-ext.yang
new file mode 100644 (file)
index 0000000..2cdc211
--- /dev/null
@@ -0,0 +1,75 @@
+module yang-ext {
+    yang-version 1;
+    namespace "urn:opendaylight:yang:extension:yang-ext";
+    prefix "ext";
+
+    contact "Anton Tkacik <ttkacik@cisco.com>";
+
+    description
+        "Copyright (c) 2013 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";
+
+    revision "2013-07-09" {
+        description "";
+    }
+
+    // Augmentation name
+
+    extension "augment-identifier" {
+        description
+                "YANG language extension which assigns an identifier to augmentation.
+                Augment identifier is used to identify specific augment statement
+                by name. The identifier syntax is defined formally defined by
+                the rule 'identifier' in Section 12 of RFC 6020. All augment identifiers
+                defined in a namespace MUST be unique. The namespace of augment
+                identifiers is shared by module and its submodules.";
+
+        /*
+                Discussion:
+                This extension allows for ease of development / debug
+                of YANG modules and it is suitable for code generation,
+                where each augment statement is nicely identified by
+                unique name instead of combination of augment target
+                and when condition. 
+            */
+        argument "identifier";
+    }
+
+    // Context-aware RPCs
+
+    grouping rpc-context-ref {
+        description
+                "A reference to RPC context.";
+        leaf context-instance {
+            type instance-identifier;
+            description "Pointer to the context. ";
+        }
+    }
+
+    extension "rpc-context-instance" {
+        description
+                "YANG language extension which defines enclosing (parent) schema
+                node as referencable context for RPCs. The argument is identity
+                which is used to identify RPC context type.";
+
+        argument "context-type";
+    }
+
+    extension "context-reference" {
+        argument "context-type";
+    }
+
+    extension "context-instance" {
+        argument "context-type";
+    }
+
+    extension "instance-target" {
+        argument "path";
+    }
+
+    extension "anyxml-schema-location" {
+        argument "target-node";
+    }
+}