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;
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.
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();
}
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;
/**
*
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);
}
--- /dev/null
+/*
+ * 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);
+
+}
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;
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> {
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) {
};
+ yangModeledAnyXmlNodeParser = new YangModeledAnyXmlDomParser(dispatcher);
containerNodeParser = new ContainerNodeDomParser(dispatcher, strictParsing);
mapEntryNodeParser = new MapEntryNodeDomParser(dispatcher, strictParsing);
mapNodeParser = new MapNodeDomParser(mapEntryNodeParser);
};
+ yangModeledAnyXmlNodeParser = new YangModeledAnyXmlDomParser(dispatcher);
containerNodeParser = new ContainerNodeDomParser(dispatcher, buildingStratProvider.forContainer(), strictParsing);
mapEntryNodeParser = new MapEntryNodeDomParser(dispatcher, buildingStratProvider.forMapEntry(), strictParsing);
mapNodeParser = new MapNodeDomParser(mapEntryNodeParser, buildingStratProvider.forMap());
return orderedListNodeParser;
}
+ @Override
+ public ToNormalizedNodeParser<Element, YangModeledAnyXmlNode, YangModeledAnyXmlSchemaNode> getYangModeledAnyXmlNodeParser() {
+ return yangModeledAnyXmlNodeParser;
+ }
+
@Override
public ToNormalizedNodeParser<Element, AnyXmlNode, AnyXmlSchemaNode> getAnyXmlNodeParser() {
return anyXmlNodeParser;
return new BaseDispatcherParser.SimpleBuildingStrategy<>();
}
}
+
}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
--- /dev/null
+<?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
--- /dev/null
+<?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
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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";
+ }
+}
--- /dev/null
+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";
+ }
+}
}
writer.argumentValue(argument, ref);
} else {
- writer.startStatement(QName.create(validStatementDefinition.getModule(), keywordTxt), ref);
+ writer.startStatement(validStatementDefinition, ref);
if (argument != null) {
writer.argumentValue(argument, ref);
}
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;
}
}
}
- 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<>();
}
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)",
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());
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());
}
}
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;
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) {
--- /dev/null
+/*
+ * 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>>>> {
+
+}
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());
}
}
--- /dev/null
+/**
+ * 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();
+ }
+}
-/*
+/**
* Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
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;
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
.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
}
@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
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
--- /dev/null
+/*
+ * 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;
+ }
+}
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;
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;
.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();
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;
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
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();
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
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;
}
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();
- }
-
}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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";
+ }
+}