xtend-gen
target
.DS_Store
+META-INF
\ No newline at end of file
--- /dev/null
+# YANG Tools
+
+YANG Tools is to develop necessary tooling and libraries to provide Java runtime
+and support for [YANG modeling language][RFC6020], data structures modeled by YANG and their
+serialization and deserialization as defined in IETF drafts and standards.
+
+## Current Features
+
+* parsing of [YANG sources][RFC6020] and semantic inference of relationship across YANG models as defined in [RFC6020]
+* representation of YANG-modeled data in Java
+ * **DOM-like APIs** - DOM-like tree model, which uses conceptual meta-model
+ * **Java Bindings** - Concrete data model generated from YANG models
+* serialization / deserialization of YANG-modeled data driven by YANG models
+ * XML - as defined in [RFC6020]
+ * JSON - as defined in [draft-lhotka-netmod-yang-json-01]
+* Integration of YANG model parsing into Maven build lifecycle and
+ support for third-party generators processing YANG models.
+
+
+[RFC6020]:https://tools.ietf.org/html/rfc6020
+[draft-lhotka-netmod-yang-json-01]:https://tools.ietf.org/html/draft-lhotka-netmod-yang-json-01
--- /dev/null
+= Contributor Guide
+
+== Architecture
+
+== Design
+
+=== Design considerations
+
+=== Design decisions
+
+== Common concepts
+
+== Recomendations
--- /dev/null
+= Developer Guide
+
+== Overview
+
+=== Architecture
+
+=== Concepts
+
+=== Components
+
+==== YANG Model API
+
+==== YANG Parser
+
+==== YANG Data API
+
+==== YANG Data Codecs
+
+==== YANG Maven Plugin
+
+== How to / Tutorials
+
+=== Working with YANG Model
+
+=== Working with YANG Data
+
+=== Serialization / deserialization of YANG Data
+
+=== Introducing schema source repositories
+
+=== Writing YANG driven generators
+
+=== Introducing specific extension support for YANG parser
+
+=== Diagnostics
<module>restconf</module>
<module>websocket</module>
<module>yang</module>
+ <module>yang-validation-tool</module>
<!-- module>third-party</module -->
</modules>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yangtools-aggregator</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>yang-validation-tool</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-parser-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.argparse4j</groupId>
+ <artifactId>argparse4j</artifactId>
+ <version>0.4.3</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-yang-types-20130715</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <configuration></configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <!-- TODO investigate why jar fails without this
+ filter -->
+ <filters>
+ <filter>
+ <artifact>*:*</artifact>
+ <excludes>
+ <exclude>META-INF/*.SF</exclude>
+ <exclude>META-INF/*.DSA</exclude>
+ <exclude>META-INF/*.RSA</exclude>
+ </excludes>
+ </filter>
+ </filters>
+ <transformers>
+ <transformer
+ implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <mainClass>org.opendaylight.yangtools.yang.validation.tool.Main</mainClass>
+ </transformer>
+ </transformers>
+ <shadedArtifactAttached>true</shadedArtifactAttached>
+ <shadedClassifierName>executable</shadedClassifierName>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2014 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.validation.tool;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public final class Main {
+ private Main() {
+
+ }
+
+ public static void main(final String[] args) throws URISyntaxException {
+ final Params params = ParamsUtil.parseArgs(args, Params.getParser());
+ final YangParserImpl yangParser = new YangParserImpl();
+
+ if (params.isValid()) {
+ final File[] yangModels = params.getYangSourceDir().listFiles();
+
+ try {
+ yangParser.parseFiles(Arrays.asList(yangModels));
+ } catch (Exception e) {
+
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.validation.tool;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import net.sourceforge.argparse4j.ArgumentParsers;
+import net.sourceforge.argparse4j.annotation.Arg;
+import net.sourceforge.argparse4j.inf.ArgumentParser;
+
+final class Params {
+
+ @Arg(dest = "yang-source-dir")
+ private File yangSourceDir;
+
+ static ArgumentParser getParser() throws URISyntaxException {
+ final ArgumentParser parser = ArgumentParsers.newArgumentParser("jar_file_name");
+ parser.description("Validation Tool for Yang Models")
+ .formatUsage();
+
+ parser.addArgumentGroup("Required arguments")
+ .addArgument("--yang-source-dir")
+ .type(File.class)
+ .required(true)
+ .help("directory containing yang models which will be parsed")
+ .dest("yang-source-dir")
+ .metavar("");
+
+ return parser;
+ }
+
+ public boolean isValid() {
+ if (yangSourceDir == null) {
+ return false;
+ }
+ if (!yangSourceDir.exists()) {
+ System.err.println("Yang source directory has to exist");
+ return false;
+ }
+ if (!yangSourceDir.canRead()) {
+ System.err.println("Yang source directory has to be readable");
+ return false;
+ }
+ if (yangSourceDir.list().length == 0) {
+ System.err.printf("Yang source directory '%s' does't contain any model%n", yangSourceDir.getPath());
+ return false;
+ }
+
+ return true;
+ }
+
+ public File getYangSourceDir() {
+ return yangSourceDir;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.validation.tool;
+
+import net.sourceforge.argparse4j.inf.ArgumentParser;
+import net.sourceforge.argparse4j.inf.ArgumentParserException;
+
+final class ParamsUtil {
+ private ParamsUtil() {
+
+ }
+
+ public static Params parseArgs(final String[] args, final ArgumentParser parser) {
+ final Params params = new Params();
+ try {
+ parser.parseArgs(args, params);
+ return params;
+ } catch (final ArgumentParserException e) {
+ parser.handleError(e);
+ }
+ System.exit(1);
+ return null;
+ }
+}
* 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.binding.test;
+package org.opendaylight.yangtools.yang.binding;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-
import org.junit.Test;
+import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.test.mock.FooChild;
import org.opendaylight.yangtools.yang.binding.test.mock.InstantiatedFoo;
assertFalse(nodeOne.contains(nodes));
assertTrue(nodes.contains(nodeOne));
+
+ assertTrue(nodes.containsWildcarded(nodeOne));
+ assertFalse(nodeOne.containsWildcarded(nodes));
}
@Test
}
-
void childOfTest() {
InstanceIdentifier.builder(Nodes.class).child(InstantiatedFoo.class).child(FooChild.class);
}
+ @Test
+ public void basicTests() {
+ InstanceIdentifier<DataObject> instanceIdentifier1 = InstanceIdentifier.create(DataObject.class);
+ InstanceIdentifier<DataObject> instanceIdentifier2 = InstanceIdentifier.create(DataObject.class);
+ Object object = new Object();
+
+ assertTrue(instanceIdentifier1.equals(instanceIdentifier1));
+ assertFalse(instanceIdentifier1.equals(null));
+ assertFalse(instanceIdentifier1.equals(object));
+ assertTrue(instanceIdentifier1.equals(instanceIdentifier2));
+
+ assertNotNull(instanceIdentifier1.hashCode());
+
+ assertNotNull(instanceIdentifier1.toString());
+ }
+
+ @Test
+ public void firstIdentifierOfTest() {
+ InstanceIdentifier<Node> instanceIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class,new NodeKey(10)).build();
+
+ InstanceIdentifier<Nodes> nodesIdentifier = instanceIdentifier.firstIdentifierOf(Nodes.class);
+ assertNotNull(nodesIdentifier);
+ InstanceIdentifier<DataObject> dataObjectIdentifier = instanceIdentifier.firstIdentifierOf(DataObject.class);
+ assertNull(dataObjectIdentifier);
+ }
}
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
*
* @return {@link YangInstanceIdentifier}
*/
+ @Override
YangInstanceIdentifier build();
/*
return this;
}
+ @Override
@Deprecated
public YangInstanceIdentifier toInstance() {
return build();
}
}
+ private Object readResolve() throws ObjectStreamException {
+ return legacyPath.isEmpty() ? EMPTY : this;
+ }
+
private void writeObject(final ObjectOutputStream outputStream) throws IOException {
/*
* This may look strange, but what we are doing here is side-stepping the fact
package org.opendaylight.yangtools.yang.data.api;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
*
* @author Thomas Pantelis
*/
-public class InstanceIdentifierTest {
+public class YangInstanceIdentifierTest {
static QName nodeName1 = QName.create("test", "2014-5-28", "node1");
static QName nodeName2 = QName.create("test", "2014-5-28", "node2");
static QName key2 = QName.create("test", "2014-5-28", "key2");
static QName key3 = QName.create("test", "2014-5-28", "key3");
+ @Test
+ public void testGetLastPathArgument() {
+ YangInstanceIdentifier id1 = YangInstanceIdentifier.create(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2));
+ assertEquals( "getLastPathArgument", new NodeIdentifier(nodeName2), id1.getLastPathArgument());
+ YangInstanceIdentifier id2 = YangInstanceIdentifier.create();
+ assertNull( id2.getLastPathArgument() );
+ }
+
@Test
public void testHashCodeEquals() {
+ YangInstanceIdentifier id1 = YangInstanceIdentifier.create(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2));
+ YangInstanceIdentifier id2 = YangInstanceIdentifier.create(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2));
+
+ assertEquals( "hashCode", id1.hashCode(), id2.hashCode() );
+ }
+
+ @Test
+ public void testEquals() {
+
YangInstanceIdentifier id1 = YangInstanceIdentifier.create(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2));
YangInstanceIdentifier id2 = YangInstanceIdentifier.create(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2));
YangInstanceIdentifier id3 = YangInstanceIdentifier.create(new NodeIdentifier(nodeName2), new NodeIdentifier(nodeName1));
YangInstanceIdentifier id4 = YangInstanceIdentifier.create(new NodeIdentifier(nodeName1));
- assertEquals( "hashCode", id1.hashCode(), id2.hashCode() );
+ assertEquals( "equals", false, id1.equals( null ) );
+ assertEquals( "equals", true, id1.equals( id1 ) );
assertEquals( "equals", true, id1.equals( id2 ) );
-
assertEquals( "equals", false, id1.equals( id3 ) );
assertEquals( "equals", false, id1.equals( id4 ) );
assertEquals( "equals", false, id1.equals( new Object() ) );
}
+ @Test
+ public void testToString() {
+ YangInstanceIdentifier id = YangInstanceIdentifier.create(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2));
+
+ assertNotNull( id.toString() );
+
+ }
+
@Test
public void testNode() {
Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
Optional<YangInstanceIdentifier> relative = id1.relativeTo( id2 );
-
assertEquals( "isPresent", true, relative.isPresent() );
Iterable<PathArgument> p = relative.get().getPathArguments();
assertEquals( "isPresent", false, relative.isPresent() );
}
+ @Test(expected=IllegalArgumentException.class)
+ public void testContainsNull() {
+ final YangInstanceIdentifier id = YangInstanceIdentifier.create(new NodeIdentifier(nodeName1));
+
+ id.contains( null );
+ }
+
@Test
public void testContains() {
assertEquals( "equals", false, node1.equals( new Object() ) );
assertNotNull( node1.toString() ); // for code coverage
+ assertNotNull( node1.toRelativeString(node2) );
NodeIdentifierWithPredicates node3 = new NodeIdentifierWithPredicates( nodeName1,
ImmutableMap.<QName, Object>builder().put( key1, 10 ).put( key2, 20 ).build() );
assertEquals( "equals", false, node1.equals( new Object() ) );
assertNotNull( node1.toString() ); // for code coverage
+ assertNotNull( node1.toRelativeString(node2) );
NodeWithValue node3 = new NodeWithValue( nodeName1, new byte[]{1,2} );
NodeWithValue node4 = new NodeWithValue( nodeName1, new byte[]{1,2} );
NodeIdentifier node1 = new NodeIdentifier( nodeName1 );
assertEquals( "getNodeType", nodeName1, node1.getNodeType() );
-
NodeIdentifier node2 = new NodeIdentifier( nodeName1 );
+ AugmentationIdentifier node3 = new AugmentationIdentifier( Sets.newHashSet( nodeName1, nodeName2 ) );
assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
- assertEquals( "equals", true, node1.equals( node2 ) );
assertEquals( "compareTo", 0, node1.compareTo( node2 ) );
+ assertEquals( "compareTo", true, node1.compareTo( new NodeIdentifier( nodeName3 ) ) != 0 );
+ assertEquals( "equals", false, node1.equals( null ) );
+ assertEquals( "equals", false, node1.equals( node3 ) );
+ assertEquals( "equals", true, node1.equals( node1 ) );
+ assertEquals( "equals", true, node1.equals( node2 ) );
assertEquals( "equals", false, node1.equals( new NodeIdentifier( nodeName3 ) ) );
- assertEquals( "compareTo", true, node1.compareTo( new NodeIdentifier( nodeName3 ) ) != 0 );
assertEquals( "equals", false, node1.equals( new Object() ) );
assertNotNull( node1.toString() ); // for code coverage
}
+ @Test(expected=UnsupportedOperationException.class)
+ public void testAugmentationIdentifierNodeType() {
+ AugmentationIdentifier node1 = new AugmentationIdentifier( Sets.newHashSet( nodeName1, nodeName2 ) );
+ node1.getNodeType();
+ }
+
@Test
public void testAugmentationIdentifier() {
AugmentationIdentifier node1 = new AugmentationIdentifier( Sets.newHashSet( nodeName1, nodeName2 ) );
assertEquals( "getPossibleChildNames", Sets.newHashSet( nodeName1, nodeName2 ), node1.getPossibleChildNames() );
-
AugmentationIdentifier node2 = new AugmentationIdentifier( Sets.newHashSet( nodeName2, nodeName1 ) );
+ AugmentationIdentifier node3 = new AugmentationIdentifier( Sets.newHashSet( nodeName1, nodeName3 ) );
+ AugmentationIdentifier node4 = new AugmentationIdentifier( Sets.newHashSet( nodeName1, nodeName2, nodeName3 ) );
+ NodeIdentifier node5 = new NodeIdentifier( nodeName3 );
assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
- assertEquals( "equals", true, node1.equals( node2 ) );
- assertEquals( "equals", false,
- node1.equals( new AugmentationIdentifier( Sets.newHashSet( nodeName1, nodeName3 ) ) ) );
- assertEquals( "equals", false,
- node1.equals( new AugmentationIdentifier( Sets.newHashSet( nodeName1 ) ) ) );
+ assertEquals( "equals", true, node1.equals( node1 ) );
+ assertEquals( "equals", true, node1.equals( node2 ) );
+ assertEquals( "equals", false, node1.equals( node3 ) );
+ assertEquals( "equals", false, node1.equals( new AugmentationIdentifier( Sets.newHashSet( nodeName1 ) ) ) );
assertEquals( "equals", false, node1.equals( new Object() ) );
+ assertEquals( "compareTo", -1, node1.compareTo( node5 ) );
+ assertNotEquals( "compareTo", -1, node1.compareTo( node2 ) );
+ assertEquals( "compareTo", 0, node1.compareTo( node2 ) );
+ assertEquals( "compareTo", 1, node1.compareTo( node4 ) );
+ assertEquals( "compareTo", -1, node4.compareTo( node1 ) );
+
assertNotNull( node1.toString() ); // for code coverage
+ assertNotNull( node1.toRelativeString(node5));
}
@Test
CompositeNodeDataWithSchema caseNodeDataWithSchema = findChoice(childNodes, choiceCandidate, caseCandidate);
if (caseNodeDataWithSchema == null) {
ChoiceNodeDataWithSchema choiceNodeDataWithSchema = new ChoiceNodeDataWithSchema(choiceNode);
- addChild(choiceNodeDataWithSchema);
+ childNodes.add(choiceNodeDataWithSchema);
caseNodeDataWithSchema = choiceNodeDataWithSchema.addCompositeChild(caseNode);
}
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Map.Entry;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataValidationException;
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerAttrNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class ImmutableMapEntryNodeBuilder extends AbstractImmutableDataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> {
-
+ private static final Logger LOG = LoggerFactory.getLogger(ImmutableMapEntryNodeBuilder.class);
protected final Map<QName, YangInstanceIdentifier.PathArgument> childrenQNamesToPaths;
protected ImmutableMapEntryNodeBuilder() {
@Override
public MapEntryNode build() {
- checkKeys();
- return new ImmutableMapEntryNode(getNodeIdentifier(), buildValue(), getAttributes());
- }
-
- private void checkKeys() {
- for (final QName keyQName : getNodeIdentifier().getKeyValues().keySet()) {
- DataContainerChild<?, ?> childNode = getChild(childrenQNamesToPaths.get(keyQName));
- DataValidationException.checkListKey(childNode, getNodeIdentifier().getKeyValues(), keyQName, getNodeIdentifier());
+ for (final Entry<QName, Object> key : getNodeIdentifier().getKeyValues().entrySet()) {
+ final DataContainerChild<?, ?> childNode = getChild(childrenQNamesToPaths.get(key.getValue()));
+
+ // We have enough information to fill-in missing leaf nodes, so let's do that
+ if (childNode == null) {
+ LeafNode<Object> leaf = ImmutableNodes.leafNode(key.getKey(), key.getValue());
+ LOG.debug("Adding leaf {} implied by key {}", leaf, key);
+ withChild(leaf);
+ } else {
+ DataValidationException.checkListKey(getNodeIdentifier(), key.getKey(), key.getValue(), childNode.getValue());
+ }
}
+
+ return new ImmutableMapEntryNode(getNodeIdentifier(), buildValue(), getAttributes());
}
private static final class ImmutableMapEntryNode extends AbstractImmutableDataContainerAttrNode<YangInstanceIdentifier.NodeIdentifierWithPredicates> implements MapEntryNode {
}
}
+ public static void checkListKey(final NodeIdentifierWithPredicates nodeId, final QName keyQName, final Object expected, final Object actual) {
+ // Objects.equals() does not deal with arrays, but is faster
+ if (!Objects.equals(expected, actual) && !Objects.deepEquals(expected, actual)) {
+ throw new IllegalListKeyException(keyQName, nodeId, actual, expected);
+ }
+ }
+
public static void checkListKey(final DataContainerChild<?, ?> childNode, final Map<QName, Object> keyValues, final QName keyQName,
final NodeIdentifierWithPredicates nodeId) {
checkListKey(childNode, keyQName, nodeId);
- final Object expected = nodeId.getKeyValues().get(keyQName);
+ final Object expected = keyValues.get(keyQName);
final Object actual = childNode.getValue();
- // Objects.equals() does not deal with arrays, but is faster
- if (!Objects.equals(expected, actual) && !Objects.deepEquals(expected, actual)) {
- throw new IllegalListKeyException(keyQName, nodeId, actual, expected);
- }
+ checkListKey(nodeId, keyQName, expected, actual);
}
public static void checkListKey(final DataContainerChild<?, ?> childNode, final QName keyQName, final NodeIdentifierWithPredicates nodeId) {
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
+import java.util.Collection;
import java.util.Map;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version);
- if (Iterables.isEmpty(modification.getChildren())) {
+ if (modification.getChildren().isEmpty()) {
return newValueMeta;
}
* The user has issued an empty merge operation. In this case we do not perform
* a data tree mutation, do not pass GO, and do not collect useless garbage.
*/
- final Iterable<ModifiedNode> children = modification.getChildren();
- if (Iterables.isEmpty(children)) {
+ final Collection<ModifiedNode> children = modification.getChildren();
+ if (children.isEmpty()) {
newMeta.setData(currentMeta.getData());
return newMeta.seal();
}
public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
- AugmentationSchema augSchema = null;
-
- allAugments:
- for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
- for (DataSchemaNode child : potential.getChildNodes()) {
- if (identifier.getPossibleChildNames().contains(child.getQName())) {
- augSchema = potential;
- break allAugments;
- }
+ for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
+ for (DataSchemaNode child : potential.getChildNodes()) {
+ if (identifier.getPossibleChildNames().contains(child.getQName())) {
+ return new DataNodeContainerModificationStrategy.AugmentationModificationStrategy(potential, resolvedTree);
}
}
-
- if (augSchema != null) {
- return new DataNodeContainerModificationStrategy.AugmentationModificationStrategy(augSchema, resolvedTree);
}
+
return null;
}
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
import com.google.common.base.Optional;
-import com.google.common.collect.Iterables;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version);
- if (Iterables.isEmpty(modification.getChildren())) {
+ if (modification.getChildren().isEmpty()) {
return newValueMeta;
}
final Optional<TreeNode> current) throws IncorrectDataStructureException {
throw new IncorrectDataStructureException(path, "Subtree modification is not allowed.");
}
-}
\ No newline at end of file
+}
--- /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;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ExtensionStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+/**
+ * Extension namespace
+ *
+ * All extension names defined in a module and its submodules share
+ * the same extension identifier namespace.
+ *
+ */
+public interface ExtensionNamespace extends StatementNamespace<QName, ExtensionStatement, EffectiveStatement<QName, ExtensionStatement>> {
+
+}
--- /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;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.FeatureStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+/**
+ *
+ * Feature namespace
+ *
+ * All feature names defined in a module and its submodules share the
+ * same feature identifier namespace.
+ *
+ */
+public interface FeatureNamespace extends StatementNamespace<QName, FeatureStatement, EffectiveStatement<QName,FeatureStatement>> {
+
+}
--- /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;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.GroupingStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+
+/**
+ * Grouping namespace
+ *
+ * All grouping names defined within a parent node or at the top level of the
+ * module or its submodules share the same grouping identifier namespace. This
+ * namespace is scoped to all descendant nodes of the parent node or module.
+ * This means that any descendant node may use that grouping, and it MUST NOT
+ * define a grouping with the same name.
+ */
+public interface GroupingNamespace extends StatementNamespace.TreeScoped<QName, GroupingStatement,EffectiveStatement<QName,GroupingStatement>> {
+
+}
--- /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;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.model.api.stmt.IdentityStatement;
+
+/**
+ *
+ * Identity namespace
+ *
+ * All identity names defined in a module and its submodules share the same
+ * identity identifier namespace.
+ *
+ */
+public interface IdentityNamespace extends IdentifierNamespace<QName, IdentityStatement> {
+
+}
--- /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;
+
+import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+
+public interface ModuleNamespace extends StatementNamespace<ModuleIdentifier, ModuleStatement, EffectiveStatement<String, ModuleStatement>> {
+
+}
--- /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;
+
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
+
+public interface NamespaceToModule extends StatementNamespace<QNameModule, ModuleStatement, EffectiveStatement<String, ModuleStatement>> {
+
+}
--- /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;
+
+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.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+
+/**
+ * Schema node identifier namespace
+ *
+ * All leafs, leaf-lists, lists, containers, choices, rpcs, notifications, and
+ * anyxmls defined (directly or through a uses statement) within a parent node
+ * or at the top level of the module or its submodules share the same identifier
+ * namespace. This namespace is scoped to the parent node or module, unless the
+ * parent node is a case node. In that case, the namespace is scoped to the
+ * closest ancestor node that is not a case or choice node.
+ */
+public interface SchemaNodeIdentifierNamespace extends StatementNamespace.TreeBased<SchemaNodeIdentifier, DeclaredStatement<?>,EffectiveStatement<?,DeclaredStatement<?>>> {
+
+}
--- /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;
+
+import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+
+public interface SubmoduleNamespace extends StatementNamespace<ModuleIdentifier, SubmoduleStatement, EffectiveStatement<String, SubmoduleStatement>> {
+
+}
--- /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;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+
+/**
+ * Derived types namespace
+ *
+ * All derived type names defined within a parent node or at the top level of
+ * the module or its submodules share the same type identifier namespace. This
+ * namespace is scoped to all descendant nodes of the parent node or module.
+ * This means that any descendant node may use that typedef, and it MUST NOT
+ * define a typedef with the same name.
+ *
+ */
+public interface TypeNamespace extends StatementNamespace.TreeScoped<QName, TypedefStatement, EffectiveStatement<QName,TypedefStatement>> {
+
+}
--- /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.reactor;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceNotAvailableException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.SourceSpecificContext.PhaseCompletionProgress;
+
+class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBehaviour.Registry {
+
+ private static final List<ModelProcessingPhase> PHASE_EXECUTION_ORDER = ImmutableList.<ModelProcessingPhase>builder()
+ .add(ModelProcessingPhase.SourceLinkage)
+ .add(ModelProcessingPhase.StatementDefinition)
+ .add(ModelProcessingPhase.FullDeclaration)
+ .add(ModelProcessingPhase.EffectiveModel)
+ .build();
+
+ private final Map<QName,StatementDefinitionContext<?,?,?>> definitions = new HashMap<>();
+ private final Map<Class<?>,NamespaceBehaviourWithListeners<?, ?, ?>> namespaces = new HashMap<>();
+
+
+ private final Map<ModelProcessingPhase,StatementSupportBundle> supports;
+ private final Set<SourceSpecificContext> sources = new HashSet<>();
+
+ private ModelProcessingPhase currentPhase;
+ private ModelProcessingPhase finishedPhase;
+
+ public BuildGlobalContext(Map<ModelProcessingPhase, StatementSupportBundle> supports) {
+ super();
+ this.supports = supports;
+ }
+
+ public void addSource(@Nonnull StatementStreamSource source) {
+ sources.add(new SourceSpecificContext(this,source));
+ }
+
+ @Override
+ public StorageNodeType getStorageNodeType() {
+ return StorageNodeType.Global;
+ }
+
+ @Override
+ public NamespaceStorageNode getParentNamespaceStorage() {
+ return null;
+ }
+
+ @Override
+ public NamespaceBehaviour.Registry getBehaviourRegistry() {
+ return this;
+ }
+
+ @Override
+ public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> getNamespaceBehaviour(Class<N> type) {
+ NamespaceBehaviourWithListeners<?, ?, ?> potential = namespaces.get(type);
+ if (potential == null) {
+ NamespaceBehaviour<K, V, N> potentialRaw = supports.get(currentPhase).getNamespaceBehaviour(type);
+ if(potentialRaw != null) {
+ potential = new NamespaceBehaviourWithListeners<>(potentialRaw);
+ namespaces.put(type, potential);
+ }
+ }
+ if (potential != null) {
+ Preconditions.checkState(type.equals(potential.getIdentifier()));
+
+ /*
+ * Safe cast, previous checkState checks equivalence of key from
+ * which type argument are derived
+ */
+ @SuppressWarnings("unchecked")
+ NamespaceBehaviourWithListeners<K, V, N> casted = (NamespaceBehaviourWithListeners<K, V, N>) potential;
+ return casted;
+ }
+ throw new NamespaceNotAvailableException("Namespace " + type + "is not available in phase " + currentPhase);
+ }
+
+ public StatementDefinitionContext<?, ?, ?> getStatementDefinition(QName name) {
+ StatementDefinitionContext<?, ?, ?> potential = definitions.get(name);
+ if(potential == null) {
+ StatementSupport<?, ?, ?> potentialRaw = supports.get(currentPhase).getStatementDefinition(name);
+ if(potentialRaw != null) {
+ potential = new StatementDefinitionContext<>(potentialRaw);
+ definitions.put(name, potential);
+ }
+ }
+ return potential;
+ }
+
+ public EffectiveModelContext build() throws SourceException, ReactorException {
+ for(ModelProcessingPhase phase : PHASE_EXECUTION_ORDER) {
+ startPhase(phase);
+ loadPhaseStatements();
+ completePhaseActions();
+ endPhase(phase);
+ }
+ return transform();
+ }
+
+ private EffectiveModelContext transform() {
+ Preconditions.checkState(finishedPhase == ModelProcessingPhase.EffectiveModel);
+ List<DeclaredStatement<?>> rootStatements = new ArrayList<>();
+ for(SourceSpecificContext source : sources) {
+ DeclaredStatement<?> root = source.getRoot().buildDeclared();
+ rootStatements.add(root);
+ }
+ return new EffectiveModelContext(rootStatements);
+ }
+
+ private void startPhase(ModelProcessingPhase phase) {
+ Preconditions.checkState(Objects.equals(finishedPhase, phase.getPreviousPhase()));
+ for(SourceSpecificContext source : sources) {
+ source.startPhase(phase);
+ }
+ currentPhase = phase;
+ }
+
+ private void loadPhaseStatements() throws SourceException {
+ Preconditions.checkState(currentPhase != null);
+ for(SourceSpecificContext source : sources) {
+ source.loadStatements();
+ }
+ }
+
+ private void completePhaseActions() throws ReactorException {
+ Preconditions.checkState(currentPhase != null);
+ ArrayList<SourceSpecificContext> sourcesToProgress = Lists.newArrayList(sources);
+ try {
+ boolean progressing = true;
+ while(progressing) {
+ // We reset progressing to false.
+ progressing = false;
+ Iterator<SourceSpecificContext> currentSource = sourcesToProgress.iterator();
+ while(currentSource.hasNext()) {
+ PhaseCompletionProgress sourceProgress = currentSource.next().tryToCompletePhase(currentPhase);
+ switch (sourceProgress) {
+ case FINISHED:
+ currentSource.remove();
+ case PROGRESS:
+ progressing = true;
+ case NO_PROGRESS:
+ // Noop;
+ }
+ }
+ }
+ } catch (SourceException e) {
+ throw Throwables.propagate(e);
+ }
+ if(!sourcesToProgress.isEmpty()) {
+ SomeModifiersUnresolvedException buildFailure = new SomeModifiersUnresolvedException(currentPhase);
+ for(SourceSpecificContext failedSource : sourcesToProgress) {
+ SourceException sourceEx = failedSource.failModifiers(currentPhase);
+ buildFailure.addSuppressed(sourceEx);
+ }
+ throw buildFailure;
+ }
+ }
+
+ private void endPhase(ModelProcessingPhase phase) {
+ Preconditions.checkState(currentPhase == phase);
+ finishedPhase = currentPhase;
+ }
+
+ public Set<SourceSpecificContext> getSources() {
+ return sources;
+ }
+
+}
--- /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.reactor;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.EnumMap;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
+
+public class CrossSourceStatementReactor {
+
+ private final Map<ModelProcessingPhase,StatementSupportBundle> supportedTerminology;
+
+ CrossSourceStatementReactor(Map<ModelProcessingPhase, StatementSupportBundle> supportedTerminology) {
+ this.supportedTerminology = ImmutableMap.copyOf(supportedTerminology);
+ }
+
+ public static final Builder builder() {
+ return new Builder();
+ }
+
+ public final BuildAction newBuild() {
+ return new BuildAction();
+ }
+
+ public static class Builder implements org.opendaylight.yangtools.concepts.Builder<CrossSourceStatementReactor>{
+
+ final Map<ModelProcessingPhase,StatementSupportBundle> bundles = new EnumMap<>(ModelProcessingPhase.class);
+
+ public Builder setBundle(ModelProcessingPhase phase,StatementSupportBundle bundle) {
+ bundles.put(phase, bundle);
+ return this;
+ }
+
+ @Override
+ public CrossSourceStatementReactor build() {
+ return new CrossSourceStatementReactor(bundles);
+ }
+
+ }
+
+ public class BuildAction {
+
+ private final BuildGlobalContext context;
+
+ public BuildAction() {
+ this.context = new BuildGlobalContext(supportedTerminology);
+ }
+
+ public void addSource(StatementStreamSource source) {
+ context.addSource(source);
+ }
+
+ public EffectiveModelContext build() throws SourceException, ReactorException {
+ return context.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.parser.stmt.reactor;
+
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+
+public class EffectiveModelContext implements Immutable {
+
+ private final ImmutableList<DeclaredStatement<?>> rootStatements;
+
+ public EffectiveModelContext(List<DeclaredStatement<?>> rootStatements) {
+ this.rootStatements = ImmutableList.copyOf(rootStatements);
+ }
+
+ public ImmutableList<DeclaredStatement<?>> getRootStatements() {
+ return rootStatements;
+ }
+
+}
--- /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.reactor;
+
+import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.EffectiveModel;
+import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.FullDeclaration;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+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.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+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.meta.StmtContextUtils;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.ContextMutation;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.OnNamespaceItemAdded;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.OnPhaseFinished;
+
+class ModifierImpl implements ModelActionBuilder {
+
+ private final ModelProcessingPhase phase;
+ private final Set<AbstractPrerequisite<?>> unsatisfied = new HashSet<>();
+ private final Set<AbstractPrerequisite<?>> mutations = new HashSet<>();
+
+ private InferenceAction action;
+ private boolean actionApplied = false;
+
+ ModifierImpl(ModelProcessingPhase phase) {
+ this.phase = Preconditions.checkNotNull(phase);
+ }
+
+ private <D> AbstractPrerequisite<D> addReq(AbstractPrerequisite<D> prereq) {
+ unsatisfied.add(prereq);
+ return prereq;
+ }
+
+ private <T> AbstractPrerequisite<T> addMutation(AbstractPrerequisite<T> mutation) {
+ mutations.add(mutation);
+ return mutation;
+ }
+
+
+
+ private void checkNotRegistered() {
+ Preconditions.checkState(action == null, "Action was already registered.");
+ }
+
+ private IllegalStateException shouldNotHappenProbablyBug(SourceException e) {
+ return new IllegalStateException("Source exception during registering prerequisite. This is probably bug.",e);
+ }
+
+ private void tryToResolve() throws InferenceException {
+ if(action == null) {
+ return; // Action was not yet defined
+ }
+ if(removeSatisfied()) {
+ applyAction();
+ }
+ }
+
+ private boolean removeSatisfied() {
+ Iterator<AbstractPrerequisite<?>> prereq = unsatisfied.iterator();
+ boolean allSatisfied = true;
+ while(prereq.hasNext()) {
+ if(prereq.next().isDone()) {
+ prereq.remove(); // We are removing current prerequisite from list.
+ } else {
+ allSatisfied = false;
+ }
+ }
+ return allSatisfied;
+ }
+
+ ModelProcessingPhase getPhase() {
+ return phase;
+ }
+
+ boolean isApplied() {
+
+ return actionApplied;
+ }
+
+ void failModifier() throws InferenceException {
+ removeSatisfied();
+ action.prerequisiteFailed(unsatisfied);
+ action = null;
+ }
+
+ private void applyAction() throws InferenceException {
+
+ action.apply();
+ //Â Mark all mutations as performed, so context node could move to next.
+ actionApplied = true;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private <K, C extends StmtContext<?,?,?>, N extends StatementNamespace<K, ?, ?>> AbstractPrerequisite<C> requiresCtxImpl(StmtContext<?, ?, ?> context, Class<N> namespace, K key,ModelProcessingPhase phase) {
+ checkNotRegistered();
+ try {
+ AddedToNamespace<C> addedToNs = new AddedToNamespace<C>(phase);
+ addReq(addedToNs);
+ contextImpl(context).onNamespaceItemAddedAction((Class) namespace,key,addedToNs);
+ return addedToNs;
+ } catch (SourceException e) {
+ throw shouldNotHappenProbablyBug(e);
+ }
+ }
+
+ private <C extends StmtContext<?, ?, ?>> AbstractPrerequisite<C> requiresCtxImpl(C context, ModelProcessingPhase phase) {
+ Preconditions.checkState(action == null, "Action was already registered.");
+ try {
+ PhaseFinished<C> phaseFin = new PhaseFinished<C>();
+ addReq(phaseFin);
+ contextImpl(context).addPhaseCompletedListener(FullDeclaration,phaseFin);
+ return phaseFin;
+ } catch (SourceException e) {
+ throw shouldNotHappenProbablyBug(e);
+ }
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private <K, C extends StmtContext.Mutable<?, ?, ?> , N extends StatementNamespace<K, ?, ? >> AbstractPrerequisite<C> mutatesCtxImpl(
+ StmtContext<?, ?, ?> context, Class<N> namespace, K key, ModelProcessingPhase phase) {
+ try {
+ PhaseModificationInNamespace<C> mod = new PhaseModificationInNamespace<C>(phase);
+ addMutation(mod);
+ contextImpl(context).onNamespaceItemAddedAction((Class) namespace,key,mod);
+ return mod;
+ } catch (SourceException e) {
+ throw shouldNotHappenProbablyBug(e);
+ }
+ }
+
+ private static StatementContextBase<?,?,?> contextImpl(StmtContext<?,?,?> context) {
+ Preconditions.checkArgument(context instanceof StatementContextBase,"Supplied context was not provided by this reactor.");
+ return StatementContextBase.class.cast(context);
+ }
+
+ @Override
+ public <C extends Mutable<?, ?, ?>, CT extends C> Prerequisite<C> mutatesCtx(CT context, ModelProcessingPhase phase) {
+ try {
+ return addMutation(new PhaseMutation<C>(contextImpl(context),phase));
+ } catch (InferenceException e) {
+ throw shouldNotHappenProbablyBug(e);
+ }
+ }
+
+ @Override
+ public <A,D extends DeclaredStatement<A>,E extends EffectiveStatement<A, D>> AbstractPrerequisite<StmtContext<A, D, E>> requiresCtx(StmtContext<A, D, E> context, ModelProcessingPhase phase) {
+ return requiresCtxImpl(context, phase);
+ }
+
+
+ @Override
+ public <K, N extends StatementNamespace<K, ?, ? >> Prerequisite<StmtContext<?,?,?>> requiresCtx(StmtContext<?, ?, ?> context, Class<N> namespace, K key, ModelProcessingPhase phase) {
+ return requiresCtxImpl(context, namespace, key, phase);
+ }
+
+ @Override
+ public <D extends DeclaredStatement<?>> Prerequisite<D> requiresDeclared(StmtContext<?, ? extends D, ?> context) {
+ return requiresCtxImpl(context,FullDeclaration).transform(StmtContextUtils.<D>buildDeclared());
+ }
+
+ @Override
+ public <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>> AbstractPrerequisite<StmtContext<?, D, ?>> requiresDeclaredCtx(
+ StmtContext<?, ?, ?> context, Class<N> namespace, K key) {
+ return requiresCtxImpl(context, namespace, key,FullDeclaration);
+ }
+
+ @Override
+ public <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>> Prerequisite<D> requiresDeclared(
+ StmtContext<?, ?, ?> context, Class<N> namespace, K key) {
+ final AbstractPrerequisite<StmtContext<?,D,?>> rawContext = requiresCtxImpl(context, namespace, key,FullDeclaration);
+ return rawContext.transform(StmtContextUtils.<D>buildDeclared());
+ }
+
+ @Override
+ public <E extends EffectiveStatement<?, ?>> Prerequisite<E> requiresEffective(StmtContext<?, ?, ? extends E> stmt) {
+ return requiresCtxImpl(stmt,EffectiveModel).transform(StmtContextUtils.<E>buildEffective());
+ }
+
+ @Override
+ public <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>> AbstractPrerequisite<StmtContext<?, ?, E>> requiresEffectiveCtx(
+ StmtContext<?, ?, ?> context, Class<N> namespace, K key) {
+ return requiresCtxImpl(contextImpl(context),namespace,key,EffectiveModel);
+ }
+
+ @Override
+ public <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>> Prerequisite<E> requiresEffective(
+ StmtContext<?, ?, ?> context, Class<N> namespace, K key) {
+ final AbstractPrerequisite<StmtContext<?,?,E>> rawContext = requiresCtxImpl(context, namespace, key,EffectiveModel);
+ return rawContext.transform(StmtContextUtils.<E>buildEffective());
+ }
+
+
+ @Override
+ public <N extends IdentifierNamespace<?, ?>> Prerequisite<Mutable<?, ?, ?>> mutatesNs(Mutable<?, ?, ?> context,
+ Class<N> namespace) {
+ try {
+ return addMutation(new NamespaceMutation<N>(contextImpl(context),namespace));
+ } catch (SourceException e) {
+ throw shouldNotHappenProbablyBug(e);
+ }
+ }
+
+ @Override
+ public <T extends Mutable<?, ?, ?>> Prerequisite<T> mutatesEffectiveCtx(T stmt) {
+ return mutatesCtx(stmt, EffectiveModel);
+ }
+
+
+ @Override
+ public <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>> AbstractPrerequisite<Mutable<?, ?, E>> mutatesEffectiveCtx(
+ StmtContext<?, ?, ?> context, Class<N> namespace, K key) {
+ return mutatesCtxImpl(context, namespace, key, EffectiveModel);
+ }
+
+
+
+ @Override
+ public void apply(InferenceAction action) throws InferenceException {
+ this.action = Preconditions.checkNotNull(action);
+ tryToResolve();
+ }
+
+ private abstract class AbstractPrerequisite<T> implements Prerequisite<T> {
+
+ private T value;
+ private boolean done = false;
+
+ @Override
+ public T get() {
+ Preconditions.checkState(isDone());
+ return value;
+ }
+
+ @Override
+ public boolean isDone() {
+ return done;
+ }
+
+ protected void resolvePrereq(T value) throws InferenceException {
+ Preconditions.checkState(!isDone());
+ this.value = value;
+ this.done = true;
+ tryToResolve();
+ }
+
+ protected <O> Prerequisite<O> transform(final Function<? super T,O> transformation) {
+
+ return new Prerequisite<O>() {
+
+ @Override
+ public O get() {
+ return transformation.apply(AbstractPrerequisite.this.get());
+ }
+
+ @Override
+ public boolean isDone() {
+ return AbstractPrerequisite.this.isDone();
+ }
+
+ };
+ }
+
+ }
+
+ private class PhaseMutation<C> extends AbstractPrerequisite<C> implements ContextMutation {
+
+ @SuppressWarnings("unchecked")
+ public PhaseMutation(StatementContextBase<?, ?, ?> context, ModelProcessingPhase phase) throws InferenceException {
+ context.addMutation(phase, this);
+ resolvePrereq((C) context);
+ }
+
+ @Override
+ public boolean isFinished() {
+ return isApplied();
+ }
+
+
+ }
+ private class PhaseFinished<C extends StmtContext<?, ?, ?>> extends AbstractPrerequisite<C> implements OnPhaseFinished {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void phaseFinished(StatementContextBase<?, ?, ?> context, ModelProcessingPhase phase) throws SourceException {
+ resolvePrereq((C) (context));
+ }
+ }
+
+ private class NamespaceMutation<N extends IdentifierNamespace<?,?>> extends AbstractPrerequisite<StmtContext.Mutable<?, ?, ?>> {
+
+ public NamespaceMutation(StatementContextBase<?, ?, ?> ctx, Class<N> namespace) throws InferenceException {
+ resolvePrereq(ctx);
+ }
+
+ }
+
+ private class AddedToNamespace<C extends StmtContext<?,?,?>> extends AbstractPrerequisite<C> implements OnNamespaceItemAdded,OnPhaseFinished {
+
+ private final ModelProcessingPhase phase;
+
+ public <K, N extends StatementNamespace<K, ?, ?>> AddedToNamespace(ModelProcessingPhase phase) {
+ this.phase = phase;
+ }
+
+ @Override
+ public void namespaceItemAdded(StatementContextBase<?, ?, ?> context, Class<?> namespace, Object key,
+ Object value) throws SourceException {
+ StatementContextBase<?, ?, ?> targetContext = (StatementContextBase<?, ?, ?>) value;
+ targetContext.addPhaseCompletedListener(phase, this);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void phaseFinished(StatementContextBase<?, ?, ?> context, ModelProcessingPhase phase) throws SourceException {
+ resolvePrereq((C) context);
+ }
+
+ }
+
+ private class PhaseModificationInNamespace<C extends Mutable<?,?,?>> extends AbstractPrerequisite<C> implements OnNamespaceItemAdded, ContextMutation {
+
+ private final ModelProcessingPhase modPhase;
+
+ public <K, N extends StatementNamespace<K, ?, ?>> PhaseModificationInNamespace(ModelProcessingPhase phase) throws SourceException {
+ Preconditions.checkArgument(phase != null, "Model processing phase must not be null");
+ this.modPhase = phase;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void namespaceItemAdded(StatementContextBase<?, ?, ?> context, Class<?> namespace, Object key,
+ Object value) throws SourceException {
+ context.addMutation(modPhase,this);
+ resolvePrereq((C) context);
+ }
+
+ @Override
+ public boolean isFinished() {
+ return isApplied();
+ }
+ }
+
+}
--- /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.reactor;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import java.util.Iterator;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
+
+final class NamespaceBehaviourWithListeners<K,V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
+
+ static abstract class ValueAddedListener {
+
+ private org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode ctxNode;
+
+ public ValueAddedListener(NamespaceStorageNode contextNode) {
+ this.ctxNode = contextNode;
+ }
+
+ abstract void onValueAdded(Object key, Object value);
+
+ }
+
+ private final NamespaceBehaviour<K, V, N> delegate;
+ private final Multimap<K, ValueAddedListener> listeners = HashMultimap.create();
+
+ protected NamespaceBehaviourWithListeners(NamespaceBehaviour<K, V, N> delegate) {
+ super(delegate.getIdentifier());
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void addTo(NamespaceBehaviour.NamespaceStorageNode storage,
+ K key, V value) {
+ delegate.addTo(storage, key, value);
+
+ Iterator<ValueAddedListener> keyListeners = listeners.get(key).iterator();
+ while(keyListeners.hasNext()) {
+ ValueAddedListener listener = keyListeners.next();
+ if(listener.ctxNode == storage || hasIdentiticalValue(listener.ctxNode,key,value)) {
+ keyListeners.remove();
+ listener.onValueAdded(key, value);
+ }
+ }
+ }
+
+ private boolean hasIdentiticalValue(NamespaceBehaviour.NamespaceStorageNode ctxNode, K key, V value) {
+ return getFrom(ctxNode, key) == value;
+ }
+
+ void addValueListener(K key, ValueAddedListener listener) {
+ listeners.put(key, listener);
+ }
+
+ @Override
+ public V getFrom(NamespaceBehaviour.NamespaceStorageNode storage,
+ K key) {
+ return delegate.getFrom(storage, key);
+ }
+}
--- /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.reactor;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceNotAvailableException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+
+abstract class NamespaceStorageSupport implements NamespaceStorageNode {
+
+ private final Map<Class<?>,Map<?,?>> namespaces = new HashMap<>();
+
+
+ @Override
+ public abstract NamespaceStorageNode getParentNamespaceStorage();
+
+ public abstract NamespaceBehaviour.Registry getBehaviourRegistry();
+
+ protected void checkLocalNamespaceAllowed(Class<? extends IdentifierNamespace<?, ?>> type) {
+ // NOOP
+ }
+
+ protected <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceElementAdded(Class<N> type, K key, V value) {
+ // NOOP
+ }
+
+ public final <K, VT, V extends VT ,N extends IdentifierNamespace<K, V>> VT getFromNamespace(Class<N> type, K key)
+ throws NamespaceNotAvailableException {
+ return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this,key);
+ }
+
+ public final <K,V,VT extends V,N extends IdentifierNamespace<K, V>> void addToNs(Class<N> type, K key, VT value)
+ throws NamespaceNotAvailableException {
+ getBehaviourRegistry().getNamespaceBehaviour(type).addTo(this,key,value);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public final <K, N extends StatementNamespace<K, ?,?>> void addContextToNamespace(Class<N> type, K key, StmtContext<?, ?, ?> value)
+ throws NamespaceNotAvailableException {
+ getBehaviourRegistry().getNamespaceBehaviour((Class)type).addTo(this, key, value);
+ }
+
+ @Override
+ public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(Class<N> type, K key) {
+ @SuppressWarnings("unchecked")
+ Map<K, V> localNamespace = (Map<K,V>) namespaces.get(type);
+ if(localNamespace != null) {
+ return localNamespace.get(key);
+ }
+ return null;
+ }
+
+
+
+ @Override
+ public <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(Class<N> type, K key, V value) {
+ @SuppressWarnings("unchecked")
+ Map<K, V> localNamespace = (Map<K,V>) namespaces.get(type);
+ if(localNamespace == null) {
+ checkLocalNamespaceAllowed(type);
+ localNamespace = new HashMap<>();
+ namespaces.put(type, localNamespace);
+ }
+ localNamespace.put(key,value);
+ onNamespaceElementAdded(type,key,value);
+ }
+
+}
--- /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.reactor;
+
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+
+
+class RootStatementContext<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
+ extends StatementContextBase<A, D,E> {
+
+
+ private final SourceSpecificContext sourceContext;
+
+ RootStatementContext(ContextBuilder<A, D,E> builder, SourceSpecificContext sourceContext) throws SourceException {
+ super(builder);
+ this.sourceContext = sourceContext;
+ }
+
+ @Override
+ public StatementContextBase<?,?, ?> getParentContext() {
+ return null;
+ }
+
+ @Override
+ public NamespaceStorageNode getParentNamespaceStorage() {
+ return sourceContext;
+ }
+
+ @Override
+ public Registry getBehaviourRegistry() {
+ return sourceContext;
+ }
+
+ @Override
+ public RootStatementContext<?,?,?> getRoot() {
+ return this;
+ }
+
+ SourceSpecificContext getSourceContext() {
+ return sourceContext;
+ }
+
+
+
+}
--- /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.reactor;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Objects;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.Mutable;
+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.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ImportedNamespaceContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
+import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
+import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.ContextBuilder;
+
+public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBehaviour.Registry, Mutable {
+
+ public enum PhaseCompletionProgress {
+ NO_PROGRESS,
+ PROGRESS,
+ FINISHED
+ }
+
+ private final StatementStreamSource source;
+ private final BuildGlobalContext currentContext;
+ private final Collection<NamespaceStorageNode> importedNamespaces = new ArrayList<>();
+ private final Multimap<ModelProcessingPhase, ModifierImpl> modifiers = HashMultimap.create();
+
+ private RootStatementContext<?,?, ?> root;
+
+ private ModelProcessingPhase inProgressPhase;
+ private ModelProcessingPhase finishedPhase;
+
+
+ SourceSpecificContext(BuildGlobalContext currentContext,StatementStreamSource source) {
+ this.source = source;
+ this.currentContext = currentContext;
+ }
+
+ StatementDefinitionContext<?,?,?> getDefinition(QName name) {
+ return currentContext.getStatementDefinition(name);
+ }
+
+ ContextBuilder<?, ?, ?> createDeclaredChild(StatementContextBase<?, ?, ?> current, QName name, StatementSourceReference ref) {
+ StatementDefinitionContext<?,?,?> def = getDefinition(name);
+ Preconditions.checkArgument(def != null, "Statement %s does not have type mapping defined.",name);
+ if(current == null) {
+ return createDeclaredRoot(def,ref);
+ }
+ return current.substatementBuilder(def,ref);
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private ContextBuilder<?,?, ?> createDeclaredRoot(StatementDefinitionContext<?,?,?> def, StatementSourceReference ref) {
+ return new ContextBuilder(def,ref) {
+
+ @Override
+ public StatementContextBase build() throws SourceException {
+ if(root == null) {
+ root = new RootStatementContext(this, SourceSpecificContext.this);
+ } else {
+ Preconditions.checkState(root.getIdentifier().equals(getIdentifier()), "Root statement was already defined.");
+ }
+ root.resetLists();
+ return root;
+ }
+
+ };
+ }
+
+ RootStatementContext<?,?,?> getRoot() {
+ return root;
+ }
+
+ DeclaredStatement<?> buildDeclared() {
+ return root.buildDeclared();
+ }
+
+ EffectiveStatement<?,?> build() {
+ return root.buildEffective();
+ }
+
+ void startPhase(ModelProcessingPhase phase) {
+ @Nullable ModelProcessingPhase previousPhase = phase.getPreviousPhase();
+ Preconditions.checkState(Objects.equals(previousPhase, finishedPhase));
+ Preconditions.checkState(modifiers.get(previousPhase).isEmpty());
+ inProgressPhase = phase;
+ }
+
+ @Override
+ public <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(Class<N> type, K key, V value) {
+ if(ImportedNamespaceContext.class.isAssignableFrom(type)) {
+ importedNamespaces.add((NamespaceStorageNode) value);
+ }
+ getRoot().addToLocalStorage(type, key, value);
+ }
+
+ @Override
+ public StorageNodeType getStorageNodeType() {
+ return StorageNodeType.SourceLocalSpecial;
+ }
+
+ @Override
+ public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(Class<N> type, K key) {
+ final V potentialLocal = getRoot().getFromLocalStorage(type, key);
+ if(potentialLocal != null) {
+ return potentialLocal;
+ }
+ for(NamespaceStorageNode importedSource : importedNamespaces) {
+ V potential = importedSource.getFromLocalStorage(type, key);
+ if(potential != null) {
+ return potential;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(Class<N> type) {
+ return currentContext.getNamespaceBehaviour(type);
+ }
+
+ @Override
+ public NamespaceStorageNode getParentNamespaceStorage() {
+ return currentContext;
+ }
+
+ PhaseCompletionProgress tryToCompletePhase(ModelProcessingPhase phase) throws SourceException {
+ Collection<ModifierImpl> currentPhaseModifiers = modifiers.get(phase);
+ Iterator<ModifierImpl> modifier = currentPhaseModifiers.iterator();
+ boolean hasProgressed = false;
+ while(modifier.hasNext()) {
+ if(modifier.next().isApplied()) {
+ modifier.remove();
+ hasProgressed = true;
+ }
+ }
+ if(root.tryToCompletePhase(phase) && currentPhaseModifiers.isEmpty()) {
+ finishedPhase = phase;
+ return PhaseCompletionProgress.FINISHED;
+
+ }
+ if(hasProgressed) {
+ return PhaseCompletionProgress.PROGRESS;
+ }
+ return PhaseCompletionProgress.NO_PROGRESS;
+ }
+
+ ModelActionBuilder newInferenceAction(ModelProcessingPhase phase) {
+ ModifierImpl action = new ModifierImpl(phase);
+ modifiers.put(phase, action);
+ return action;
+ }
+
+ @Override
+ public String toString() {
+ return "SourceSpecificContext [source=" + source + ", current=" + inProgressPhase + ", finished="
+ + finishedPhase + "]";
+ }
+
+ SourceException failModifiers(ModelProcessingPhase identifier) {
+ InferenceException sourceEx = new InferenceException("Fail to infer source relationships", root.getStatementSourceReference());
+
+
+ for(ModifierImpl mod : modifiers.get(identifier)) {
+ try {
+ mod.failModifier();
+ } catch (SourceException e) {
+ sourceEx.addSuppressed(e);
+ }
+ }
+ return sourceEx;
+ }
+
+ void loadStatements() throws SourceException {
+ switch (inProgressPhase) {
+ case SourceLinkage:
+ source.writeLinkage(new StatementContextWriter(this, inProgressPhase),stmtDef());
+ break;
+ case StatementDefinition:
+ source.writeLinkageAndStatementDefinitions(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes());
+ case FullDeclaration:
+ source.writeFull(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes());
+
+ default:
+ break;
+ }
+ }
+
+ private PrefixToModule prefixes() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ private QNameToStatementDefinition stmtDef() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
--- /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.reactor;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.concepts.Identifiable;
+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.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWithListeners.ValueAddedListener;
+
+abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> extends
+ NamespaceStorageSupport implements StmtContext.Mutable<A, D, E>, Identifiable<StatementIdentifier> {
+
+ interface OnNamespaceItemAdded extends EventListener{
+
+ void namespaceItemAdded(StatementContextBase<?,?,?> context, Class<?> namespace, Object key, Object value) throws SourceException;
+
+ }
+
+ interface OnPhaseFinished extends EventListener{
+
+ void phaseFinished(StatementContextBase<?,?,?> context, ModelProcessingPhase phase) throws SourceException;
+
+ }
+
+ interface ContextMutation {
+
+ boolean isFinished();
+
+ }
+
+ abstract static class ContextBuilder<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> {
+
+ private final StatementDefinitionContext<A, D, E> definition;
+ private final StatementSourceReference stmtRef;
+ private String rawArg;
+ private StatementSourceReference argRef;
+
+ public ContextBuilder(StatementDefinitionContext<A, D, E> def, StatementSourceReference sourceRef) {
+ this.definition = def;
+ this.stmtRef = sourceRef;
+ }
+
+ public void setArgument(@Nonnull String argument, @Nonnull StatementSourceReference argumentSource) {
+ Preconditions.checkArgument(definition.hasArgument(), "Statement does not take argument.");
+ this.rawArg = Preconditions.checkNotNull(argument);
+ this.argRef = Preconditions.checkNotNull(argumentSource);
+ }
+
+ public String getRawArgument() {
+ return rawArg;
+ }
+
+ public StatementSourceReference getStamementSource() {
+ return stmtRef;
+ }
+
+ public StatementSourceReference getArgumentSource() {
+ return argRef;
+ }
+
+ public StatementDefinitionContext<A, D, E> getDefinition() {
+ return definition;
+ }
+
+ public StatementIdentifier getIdentifier() {
+ return new StatementIdentifier(definition.getStatementName(), rawArg);
+ }
+
+ public abstract StatementContextBase<A, D, E> build() throws SourceException;
+
+ }
+
+ private final StatementDefinitionContext<A, D, E> definition;
+ private final StatementIdentifier identifier;
+ private final StatementSourceReference statementDeclSource;
+ private final A argument;
+
+ private LinkedHashMap<StatementIdentifier, StatementContextBase<?, ?, ?> > substatements = new LinkedHashMap<>();
+
+ private Collection<StatementContextBase<?, ?, ?>> declared = new ArrayList<>();
+ private Collection<StatementContextBase<?, ?, ?>> effective = new ArrayList<>();
+
+ private ModelProcessingPhase completedPhase;
+
+ private Multimap<ModelProcessingPhase,OnPhaseFinished> phaseListeners = HashMultimap.create();
+ private Multimap<ModelProcessingPhase, ContextMutation> phaseMutation = HashMultimap.create();
+
+ private D declaredInstance;
+ private E effectiveInstance;
+
+
+ StatementContextBase(@Nonnull ContextBuilder<A, D, E> builder) throws SourceException {
+ this.definition = builder.getDefinition();
+ this.identifier = builder.getIdentifier();
+ this.statementDeclSource = builder.getStamementSource();
+ this.argument = definition.parseArgumentValue(this, this.rawStatementArgument());
+ this.completedPhase = null;
+ }
+
+ @Override
+ public abstract StatementContextBase<?, ?, ?> getParentContext();
+
+ @Override
+ public abstract RootStatementContext<?, ?, ?> getRoot();
+
+
+ @Override
+ public StatementIdentifier getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public StatementSource getStatementSource() {
+ return statementDeclSource.getStatementSource();
+ }
+
+ @Override
+ public StatementSourceReference getStatementSourceReference() {
+ return statementDeclSource;
+ }
+
+ @Override
+ public String rawStatementArgument() {
+ return identifier.getArgument();
+ }
+
+ @Override
+ public A getStatementArgument() {
+ return argument;
+ }
+
+ @Override
+ public Collection<? extends StmtContext<?, ?, ?>> declaredSubstatements() {
+ return Collections.unmodifiableCollection(declared);
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public ContextBuilder<?, ?, ?> substatementBuilder(StatementDefinitionContext<?, ?, ?> def,
+ StatementSourceReference ref) {
+ return new ContextBuilder(def, ref) {
+
+ @Override
+ public StatementContextBase build() throws SourceException {
+ StatementContextBase<?, ?, ?> potential = substatements.get(getIdentifier());
+ if(potential == null) {
+ potential = new SubstatementContext(StatementContextBase.this, this);
+ substatements.put(getIdentifier(), potential);
+ }
+ potential.resetLists();
+ switch (this.getStamementSource().getStatementSource()) {
+ case DECLARATION:
+ declared.add(potential);
+ break;
+ case CONTEXT:
+ effective.add(potential);
+ break;
+ }
+ return potential;
+ }
+ };
+ }
+
+ @Override
+ public StorageNodeType getStorageNodeType() {
+ return StorageNodeType.StatementLocal;
+ }
+
+ @Override
+ public D buildDeclared() {
+ Preconditions.checkArgument(completedPhase == ModelProcessingPhase.FullDeclaration || completedPhase == ModelProcessingPhase.EffectiveModel);
+ if (declaredInstance == null) {
+ declaredInstance = definition().getFactory().createDeclared(this);
+ }
+ return declaredInstance;
+ }
+
+ @Override
+ public E buildEffective() {
+ Preconditions.checkArgument(completedPhase == ModelProcessingPhase.EffectiveModel);
+ if (effectiveInstance == null) {
+ effectiveInstance = definition().getFactory().createEffective(this);
+ }
+ return effectiveInstance;
+ }
+
+
+ void resetLists() {
+ declared.clear();
+ }
+
+ boolean tryToCompletePhase(ModelProcessingPhase phase) throws SourceException {
+ if(phase.equals(completedPhase)) {
+ return true;
+ }
+ Iterator<ContextMutation> openMutations = phaseMutation.get(phase).iterator();
+ boolean finished = true;
+ while(openMutations.hasNext()) {
+ ContextMutation current = openMutations.next();
+ if(current.isFinished()) {
+ openMutations.remove();
+ } else {
+ finished = false;
+ }
+ }
+ for(StatementContextBase<?, ?, ?> child: declared) {
+ finished &= child.tryToCompletePhase(phase);
+ }
+ if(finished) {
+ onPhaseCompleted(phase);
+ return true;
+ }
+ return false;
+ }
+
+
+ private void onPhaseCompleted(ModelProcessingPhase phase) throws SourceException {
+ completedPhase = phase;
+ Iterator<OnPhaseFinished> listener = phaseListeners.get(completedPhase).iterator();
+ while(listener.hasNext()) {
+ listener.next().phaseFinished(this, phase);
+ listener.remove();
+ }
+ }
+
+ /**
+ *
+ * Ends declared section of current node.
+ *
+ * @param ref
+ * @throws SourceException
+ *
+ */
+ void endDeclared(StatementSourceReference ref,ModelProcessingPhase phase) throws SourceException {
+ definition().onDeclarationFinished(this,phase);
+ }
+
+ protected final StatementDefinitionContext<A, D, E> definition() {
+ return definition;
+ }
+
+ @Override
+ protected void checkLocalNamespaceAllowed(Class<? extends IdentifierNamespace<?, ?>> type) {
+ definition().checkNamespaceAllowed(type);
+ }
+
+ @Override
+ protected <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceElementAdded(Class<N> type, K key, V value) {
+ //definition().onNamespaceElementAdded(this, type, key, value);
+ }
+
+ <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceItemAddedAction(final Class<N> type, K key, final OnNamespaceItemAdded listener) throws SourceException {
+ Object potential = getFromNamespace(type, key);
+ if(potential != null) {
+ listener.namespaceItemAdded(this, type, key, potential);
+ return;
+ }
+ NamespaceBehaviour<K,V,N> behaviour = getBehaviourRegistry().getNamespaceBehaviour(type);
+ if(behaviour instanceof NamespaceBehaviourWithListeners) {
+ NamespaceBehaviourWithListeners<K, V, N> casted = (NamespaceBehaviourWithListeners<K,V,N>) behaviour;
+ casted.addValueListener(key, new ValueAddedListener(this) {
+ @Override
+ void onValueAdded(Object key, Object value) {
+ try {
+ listener.namespaceItemAdded(StatementContextBase.this, type, key, value);
+ } catch (SourceException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+ });
+ }
+ }
+
+ @Override
+ public StatementDefinition getPublicDefinition() {
+ return definition().getPublicView();
+ }
+
+ @Override
+ public ModelActionBuilder newInferenceAction(ModelProcessingPhase phase) {
+ return getRoot().getSourceContext().newInferenceAction(phase);
+ }
+
+ void addPhaseCompletedListener(ModelProcessingPhase phase, OnPhaseFinished listener) throws SourceException {
+ ModelProcessingPhase finishedPhase = completedPhase;
+ while (finishedPhase != null) {
+ if(phase.equals(finishedPhase)) {
+ listener.phaseFinished(this, finishedPhase);
+ return;
+ }
+ finishedPhase = finishedPhase.getPreviousPhase();
+ }
+ phaseListeners.put(phase, listener);
+ }
+
+ void addMutation(ModelProcessingPhase phase, ContextMutation mutation) {
+ ModelProcessingPhase finishedPhase = completedPhase;
+ while (finishedPhase != null) {
+ if(phase.equals(finishedPhase)) {
+ throw new IllegalStateException("Mutation registered after phase was completed.");
+ }
+ finishedPhase = finishedPhase.getPreviousPhase();
+ }
+ phaseMutation.put(phase, mutation);
+ }
+
+ @Override
+ public <K,KT extends K, N extends StatementNamespace<K, ?, ?>> void addContext(
+ Class<N> namepsace, KT key, StmtContext<?, ?, ?> stmt) {
+ addContextToNamespace(namepsace,(K) key, stmt);
+ }
+}
--- /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.reactor;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase.ContextBuilder;
+
+class StatementContextWriter implements StatementWriter {
+
+ private final SourceSpecificContext ctx;
+ private StatementContextBase<?, ?, ?> parent;
+ private ContextBuilder<?, ?, ?> current;
+ private ModelProcessingPhase phase;
+
+ public StatementContextWriter(SourceSpecificContext ctx, ModelProcessingPhase phase) {
+ this.ctx = Preconditions.checkNotNull(ctx);
+ this.phase = Preconditions.checkNotNull(phase);
+ }
+
+ @Override
+ public void startStatement(QName name, StatementSourceReference ref) throws SourceException {
+ defferedCreate();
+ current = ctx.createDeclaredChild(parent, name, ref);
+
+ }
+
+ @Override
+ public void argumentValue(String value, StatementSourceReference ref) {
+ Preconditions.checkState(current != null, "Could not two arguments for one statement.");
+ current.setArgument(value, ref);
+ }
+
+ void defferedCreate() throws SourceException {
+ if(current != null) {
+ parent = current.build();
+ current = null;
+ }
+ }
+
+ @Override
+ public void endStatement(StatementSourceReference ref) throws SourceException {
+ defferedCreate();
+ Preconditions.checkState(parent != null);
+ parent.endDeclared(ref,phase);
+ parent = parent.getParentContext();
+ }
+
+}
--- /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.reactor;
+
+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.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceNotAvailableException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementFactory;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
+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.SourceException;
+
+class StatementDefinitionContext<A,D extends DeclaredStatement<A>,E extends EffectiveStatement<A,D>> {
+ private final StatementSupport<A,D,E> support;
+ public StatementDefinitionContext(StatementSupport<A,D,E> support) {
+ this.support= support;
+ }
+
+
+ public StatementFactory<A,D,E> getFactory() {
+ return support;
+ }
+
+ public A parseArgumentValue(StmtContext<A,D,E> context, String value) throws SourceException {
+ return support.parseArgumentValue(context,value);
+ }
+
+
+ public void checkNamespaceAllowed(Class<? extends IdentifierNamespace<?,?>> namespace) throws NamespaceNotAvailableException {
+ // Noop
+ }
+
+ public StatementDefinition getPublicView() {
+ return support.getPublicView();
+ }
+
+ public boolean onStatementAdded(Mutable<A,D,E> stmt) {
+ return false;
+ }
+
+
+ public void onDeclarationFinished(Mutable<A,D,E> statement, ModelProcessingPhase phase) throws SourceException {
+ switch (phase) {
+ case SourceLinkage:
+ support.onLinkageDeclared(statement);
+ break;
+ case StatementDefinition:
+ support.onStatementDefinitionDeclared(statement);
+ case FullDeclaration:
+ support.onFullDefinitionDeclared(statement);
+ default:
+ break;
+ }
+ }
+
+
+
+ public Class<?> getRepresentingClass() {
+ return support.getDeclaredRepresentationClass();
+ }
+
+
+ public boolean hasArgument() {
+ return support.getArgumentName() != null;
+ }
+
+
+ public QName getStatementName() {
+ return support.getStatementName();
+ }
+
+}
--- /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.reactor;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QName;
+
+class StatementIdentifier {
+
+ private final @Nonnull QName name;
+ private final @Nullable String argument;
+
+ StatementIdentifier(QName name, String argument) {
+ this.name = Preconditions.checkNotNull(name);
+ this.argument = argument;
+ }
+
+ QName getName() {
+ return name;
+ }
+
+ String getArgument() {
+ return argument;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + name.hashCode();
+ result = prime * result + ((argument == null) ? 0 : argument.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ StatementIdentifier other = (StatementIdentifier) obj;
+ if (!name.equals(other.name)) {
+ return false;
+ }
+ if (!Objects.equal(argument, other.argument)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "StatementIdentifier [name=" + name + ", argument=" + argument + "]";
+ }
+
+
+}
--- /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.reactor;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+
+class SubstatementContext<A,D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
+ extends StatementContextBase<A,D,E> {
+
+ private final StatementContextBase<?,?,?> parent;
+
+ SubstatementContext(StatementContextBase<?,?,?> parent,ContextBuilder<A,D,E> builder) throws SourceException {
+ super(builder);
+ this.parent = Preconditions.checkNotNull(parent, "Parent must not be null");
+ }
+
+ @Override
+ public StatementContextBase<?,?,?> getParentContext() {
+ return parent;
+ }
+
+ @Override
+ public NamespaceStorageNode getParentNamespaceStorage() {
+ return parent;
+ }
+
+ @Override
+ public Registry getBehaviourRegistry() {
+ return parent.getBehaviourRegistry();
+ }
+
+ @Override
+ public RootStatementContext<?, ?, ?> getRoot() {
+ return parent.getRoot();
+ }
+
+}
--- /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 java.util.Collection;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.BodyGroup;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContactStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataDefinitionStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DeviationStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ExtensionStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.FeatureStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.GroupingStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.IdentityStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ImportStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.IncludeStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.LinkageGroup;
+import org.opendaylight.yangtools.yang.model.api.stmt.MetaGroup;
+import org.opendaylight.yangtools.yang.model.api.stmt.NotificationStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.OrganizationStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.RevisionGroup;
+import org.opendaylight.yangtools.yang.model.api.stmt.RevisionStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.RpcStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+
+public abstract class AbstractRootStatement<T extends DeclaredStatement<String>> extends AbstractDeclaredStatement<String>
+ implements LinkageGroup, MetaGroup, RevisionGroup, BodyGroup {
+
+ protected AbstractRootStatement(StmtContext<String, T,?> context) {
+ super(context);
+ }
+
+ @Override
+ public final Collection<? extends ImportStatement> getImports() {
+ return allDeclared(ImportStatement.class);
+ }
+
+ @Override
+ public final Collection<? extends IncludeStatement> getIncludes() {
+ return allDeclared(IncludeStatement.class);
+ }
+
+ @Override
+ public DescriptionStatement getDescription() {
+ return firstDeclared(DescriptionStatement.class);
+ }
+
+ @Override
+ public ReferenceStatement getReference() {
+ return firstDeclared(ReferenceStatement.class);
+ }
+
+ @Override
+ public final OrganizationStatement getOrganization() {
+ return firstDeclared(OrganizationStatement.class);
+ }
+
+ @Override
+ public final ContactStatement getContact() {
+ return firstDeclared(ContactStatement.class);
+ }
+
+ @Override
+ public final Collection<? extends RevisionStatement> getRevisions() {
+ return allDeclared(RevisionStatement.class);
+ }
+
+ @Override
+ public final Collection<? extends ExtensionStatement> getExtensions() {
+ return allDeclared(ExtensionStatement.class);
+ }
+
+ @Override
+ public final Collection<? extends FeatureStatement> getFeatures() {
+ return allDeclared(FeatureStatement.class);
+ }
+
+ @Override
+ public final Collection<? extends IdentityStatement> getIdentities() {
+ return allDeclared(IdentityStatement.class);
+ }
+
+ @Override
+ public Collection<? extends TypedefStatement> getTypedefs() {
+ return allDeclared(TypedefStatement.class);
+ }
+
+ @Override
+ public Collection<? extends GroupingStatement> getGroupings() {
+ return allDeclared(GroupingStatement.class);
+ }
+
+ @Override
+ public Collection<? extends DataDefinitionStatement> getDataDefinitions() {
+ return allDeclared(DataDefinitionStatement.class);
+ }
+
+ @Override
+ public final Collection<? extends AugmentStatement> getAugments() {
+ return allDeclared(AugmentStatement.class);
+ }
+
+ @Override
+ public final Collection<? extends RpcStatement> getRpcs() {
+ return allDeclared(RpcStatement.class);
+ }
+
+ @Override
+ public final Collection<? extends NotificationStatement> getNotifications() {
+ return allDeclared(NotificationStatement.class);
+ }
+
+ @Override
+ public final Collection<? extends DeviationStatement> getDeviations() {
+ return allDeclared(DeviationStatement.class);
+ }
+}
--- /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 java.util.Collection;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ConfigStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataDefinitionStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.GroupingStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.IfFeatureStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.MustStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.PresenceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement;
+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;
+
+public class ContainerStatementImpl extends AbstractDeclaredStatement<QName> implements ContainerStatement {
+
+ protected ContainerStatementImpl(StmtContext<QName, ContainerStatement,?> context) {
+ super(context);
+ }
+
+ public static class Definition extends AbstractStatementSupport<QName,ContainerStatement,EffectiveStatement<QName,ContainerStatement>> {
+
+ public Definition() {
+ super(Rfc6020Mapping.Container);
+ }
+
+ @Override
+ public QName parseArgumentValue(StmtContext<?,?,?> ctx, String value) {
+ return Utils.qNameFromArgument(ctx,value);
+ }
+
+ @Override
+ public ContainerStatement createDeclared(StmtContext<QName, ContainerStatement,?> ctx) {
+ return new ContainerStatementImpl(ctx);
+ }
+
+ @Override
+ public EffectiveStatement<QName,ContainerStatement> createEffective(StmtContext<QName,ContainerStatement,EffectiveStatement<QName,ContainerStatement>> ctx) {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ @Override
+ public QName getName() {
+ return argument();
+ }
+
+ @Override
+ public WhenStatement getWhenStatement() {
+ return firstDeclared(WhenStatement.class);
+ }
+
+ @Override
+ public Collection<? extends IfFeatureStatement> getIfFeatures() {
+ return allDeclared(IfFeatureStatement.class);
+ }
+
+ @Override
+ public Collection<? extends MustStatement> getMusts() {
+ return allDeclared(MustStatement.class);
+ }
+
+ @Override
+ public PresenceStatement getPresence() {
+ return firstDeclared(PresenceStatement.class);
+ }
+
+ @Override
+ public ConfigStatement getConfig() {
+ return firstDeclared(ConfigStatement.class);
+ }
+
+ @Override
+ public StatusStatement getStatus() {
+ return firstDeclared(StatusStatement.class);
+ }
+
+ @Override
+ public DescriptionStatement getDescription() {
+ return firstDeclared(DescriptionStatement.class);
+ }
+
+ @Override
+ public ReferenceStatement getReference() {
+ return firstDeclared(ReferenceStatement.class);
+ }
+
+ @Override
+ public Collection<? extends TypedefStatement> getTypedefs() {
+ return allDeclared(TypedefStatement.class);
+ }
+
+ @Override
+ public Collection<? extends GroupingStatement> getGroupings() {
+ return allDeclared(GroupingStatement.class);
+ }
+
+ @Override
+ public Collection<? extends DataDefinitionStatement> getDataDefinitions() {
+ return allDeclared(DataDefinitionStatement.class);
+ }
+
+}
--- /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 static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.SourceLinkage;
+import static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.firstAttributeOf;
+
+import com.google.common.base.Optional;
+import java.net.URI;
+import java.text.ParseException;
+import java.util.Collection;
+import java.util.Date;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
+import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ImportStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.RevisionDateStatement;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleIdentifierImpl;
+import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
+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.SourceException;
+
+public class ImportStatementDefinition extends
+ AbstractStatementSupport<String, ImportStatement, EffectiveStatement<String, ImportStatement>> {
+
+ public ImportStatementDefinition() {
+ super(Rfc6020Mapping.Import);
+ }
+
+ @Override
+ public String parseArgumentValue(StmtContext<?, ?, ?> ctx, String value) {
+ return value;
+ }
+
+ @Override
+ public ImportStatement createDeclared(StmtContext<String, ImportStatement, ?> ctx) {
+ return new ImportStatementImpl(ctx);
+ }
+
+ @Override
+ public EffectiveStatement<String, ImportStatement> createEffective(
+ StmtContext<String, ImportStatement, EffectiveStatement<String, ImportStatement>> ctx) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void onLinkageDeclared(final Mutable<String, ImportStatement, EffectiveStatement<String, ImportStatement>> stmt)
+ throws InferenceException, SourceException {
+ final ModuleIdentifier impIdentifier = getImportedModuleIdentifier(stmt);
+ ModelActionBuilder importAction = stmt.newInferenceAction(SourceLinkage);
+ final Prerequisite<StmtContext<?, ?, ?>> imported;
+ final Prerequisite<Mutable<?, ?, ?>> linkageTarget;
+ imported = importAction.requiresCtx(stmt, ModuleNamespace.class, impIdentifier, SourceLinkage);
+ linkageTarget = importAction.mutatesCtx(stmt.getRoot(),SourceLinkage);
+
+ importAction.apply(new InferenceAction() {
+
+ @Override
+ public void apply() throws InferenceException {
+ StmtContext<?, ?, ?> importedModule = imported.get();
+ // URI importedNs =
+ // importedModule.firstSubstatement(NamespaceStatement.class).argument();
+ // String prefix =
+ // stmt.firstSubstatement(PrefixStatement.class).argument();
+ linkageTarget.get().addToNs(ImportedModuleContext.class, impIdentifier, importedModule);
+ // prefixTarget.get().addToNs(PrefixToModule.class, prefix,
+ // QNameModule.create(importedNs, null));
+ }
+
+ @Override
+ public void prerequisiteFailed(Collection<? extends Prerequisite<?>> failed) throws InferenceException {
+ if (failed.contains(imported)) {
+ throw new InferenceException("Imported module was not found.", stmt.getStatementSourceReference());
+ }
+ }
+ });
+ }
+
+ private static ModuleIdentifier getImportedModuleIdentifier(Mutable<String, ImportStatement, ?> stmt) throws SourceException {
+ String moduleName = stmt.getStatementArgument();
+ String revisionArg = firstAttributeOf(stmt.declaredSubstatements(), RevisionDateStatement.class);
+ final Optional<Date> revision;
+ if (revisionArg != null) {
+ try {
+ revision = Optional.of(SimpleDateFormatUtil.getRevisionFormat().parse(revisionArg));
+ } catch (ParseException e) {
+ throw new SourceException(
+ String.format("Revision value %s is not in required format yyyy-MM-dd", revisionArg),
+ stmt.getStatementSourceReference(), e);
+ }
+ } else {
+ revision = Optional.absent();
+ }
+ return new ModuleIdentifierImpl(moduleName, Optional.<URI> absent(), revision);
+ }
+
+}
\ No newline at end of file
--- /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 org.opendaylight.yangtools.yang.model.api.stmt.ImportStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.RevisionDateStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+
+public class ImportStatementImpl extends AbstractDeclaredStatement<String> implements ImportStatement {
+
+ ImportStatementImpl(StmtContext<String, ImportStatement,?> context) {
+ super(context);
+ }
+
+ @Override
+ public String getModule() {
+ return rawArgument();
+ }
+
+ @Override
+ public PrefixStatement getPrefix() {
+ return firstDeclared(PrefixStatement.class);
+ }
+
+ @Override
+ public RevisionDateStatement getRevisionDate() {
+ return firstDeclared(RevisionDateStatement.class);
+ }
+}
--- /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 org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ImportedNamespaceContext;
+
+public interface ImportedModuleContext extends ImportedNamespaceContext<ModuleIdentifier> {
+
+}
--- /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 org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.NamespaceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.YangVersionStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+
+public class ModuleStatementImpl extends AbstractRootStatement<ModuleStatement> implements ModuleStatement {
+
+ protected ModuleStatementImpl(StmtContext<String, ModuleStatement,?> context) {
+ super(context);
+ }
+
+ @Override
+ public String getName() {
+ return rawArgument();
+ }
+
+ @Override
+ public YangVersionStatement getYangVersion() {
+ return firstDeclared(YangVersionStatement.class);
+ }
+
+ @Override
+ public NamespaceStatement getNamespace() {
+ return firstDeclared(NamespaceStatement.class);
+ }
+
+ @Override
+ public PrefixStatement getPrefix() {
+ return firstDeclared(PrefixStatement.class);
+ }
+
+}
--- /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 static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.firstAttributeOf;
+
+import com.google.common.base.Optional;
+import java.net.URI;
+import java.util.Date;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.NamespaceStatement;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleIdentifierImpl;
+import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
+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.SourceException;
+
+public class ModuleStatementSupport extends AbstractStatementSupport<String, ModuleStatement, EffectiveStatement<String,ModuleStatement>> {
+
+ public ModuleStatementSupport() {
+ super(Rfc6020Mapping.Module);
+ }
+
+ @Override
+ public String parseArgumentValue(StmtContext<?,?,?> ctx, String value) {
+ return value;
+ }
+
+ @Override
+ public ModuleStatement createDeclared(StmtContext<String, ModuleStatement,?> ctx) {
+ return new ModuleStatementImpl(ctx);
+ }
+
+ @Override
+ public EffectiveStatement<String,ModuleStatement> createEffective(StmtContext<String, ModuleStatement,EffectiveStatement<String,ModuleStatement>> ctx) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void onLinkageDeclared(Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt)
+ throws InferenceException, SourceException {
+ URI moduleNs = firstAttributeOf(stmt.declaredSubstatements(),NamespaceStatement.class);
+
+ QNameModule qnameNamespace = QNameModule.create(moduleNs, null);
+ ModuleIdentifierImpl moduleIdentifier = new ModuleIdentifierImpl(stmt.getStatementArgument(), Optional.<URI>absent(), Optional.<Date>absent());
+
+ stmt.addContext(ModuleNamespace.class,moduleIdentifier ,stmt);
+ stmt.addContext(NamespaceToModule.class, qnameNamespace, stmt);
+ }
+
+}
\ No newline at end of file
--- /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 java.net.URI;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.NamespaceStatement;
+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;
+
+public class NamespaceStatementImpl extends AbstractDeclaredStatement<URI> implements NamespaceStatement {
+
+ public static class Definition extends AbstractStatementSupport<URI,NamespaceStatement,EffectiveStatement<URI,NamespaceStatement>> {
+
+ public Definition() {
+ super(org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping.Namespace);
+ }
+
+ @Override
+ public URI parseArgumentValue(StmtContext<?, ?,?> ctx, String value) {
+ return URI.create(value);
+ }
+
+ @Override
+ public NamespaceStatement createDeclared(StmtContext<URI, NamespaceStatement,?> ctx) {
+ return new NamespaceStatementImpl(ctx);
+ }
+
+ @Override
+ public EffectiveStatement<URI,NamespaceStatement> createEffective(StmtContext<URI, NamespaceStatement,EffectiveStatement<URI,NamespaceStatement>> ctx) {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ NamespaceStatementImpl(StmtContext<URI, NamespaceStatement,?> context) {
+ super(context);
+ }
+
+ @Override
+ public URI getUri() {
+ return argument();
+ }
+}
--- /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 org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
+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;
+
+public class PrefixStatementImpl extends AbstractDeclaredStatement<String> implements PrefixStatement {
+
+ public static class Definition extends AbstractStatementSupport<String,PrefixStatement,EffectiveStatement<String,PrefixStatement>> {
+
+ public Definition() {
+ super(Rfc6020Mapping.Prefix);
+ }
+
+ @Override
+ public String parseArgumentValue(StmtContext<?, ?,?> ctx, String value) {
+ return (value);
+ }
+
+ @Override
+ public PrefixStatement createDeclared(StmtContext<String, PrefixStatement,?> ctx) {
+ return new PrefixStatementImpl(ctx);
+ }
+
+ @Override
+ public EffectiveStatement<String,PrefixStatement> createEffective(StmtContext<String, PrefixStatement,EffectiveStatement<String,PrefixStatement>> ctx) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ PrefixStatementImpl(StmtContext<String, PrefixStatement,?> context) {
+ super(context);
+ }
+
+ @Override
+ public String getValue() {
+ return rawArgument();
+ }
+}
--- /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 java.util.Collection;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
+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.model.api.meta.StatementSource;
+import org.opendaylight.yangtools.yang.model.api.stmt.AugmentStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.GroupingStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.IfFeatureStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.RefineStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.UsesStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement;
+import org.opendaylight.yangtools.yang.parser.spi.GroupingNamespace;
+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.InferenceException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+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.StatementSourceReference;
+
+public class UsesStatementImpl extends AbstractDeclaredStatement<QName> implements UsesStatement {
+
+ protected UsesStatementImpl(StmtContext<QName, UsesStatement, ?> context) {
+ super(context);
+ }
+
+ public static class Definition extends
+ AbstractStatementSupport<QName, UsesStatement, EffectiveStatement<QName, UsesStatement>> {
+
+ public Definition() {
+ super(Rfc6020Mapping.Uses);
+ }
+
+ @Override
+ public QName parseArgumentValue(StmtContext<?, ?, ?> ctx, String value) {
+ return Utils.qNameFromArgument(ctx, value);
+ }
+
+ public void onStatementDeclared(Mutable<QName, UsesStatement, ?> usesNode) throws InferenceException {
+ ModelActionBuilder modifier = usesNode.newInferenceAction(ModelProcessingPhase.EffectiveModel);
+ final QName groupingName = usesNode.getStatementArgument();
+ final StatementSourceReference usesSource = usesNode.getStatementSourceReference();
+ final Prerequisite<?> targetPre = modifier.mutatesEffectiveCtx(usesNode.getParentContext());
+ final Prerequisite<EffectiveStatement<QName, GroupingStatement>> sourcePre = modifier.requiresEffective(
+ usesNode, GroupingNamespace.class, groupingName);
+
+ modifier.apply(new InferenceAction() {
+
+ @Override
+ public void apply() throws InferenceException {
+ Mutable<?, ?, ?> targetCtx = (Mutable<?, ?, ?>) targetPre.get();
+ EffectiveStatement<QName, GroupingStatement> source = sourcePre.get();
+
+ throw new UnsupportedOperationException("Copy of not not yet implemented.");
+ }
+
+ @Override
+ public void prerequisiteFailed(Collection<? extends Prerequisite<?>> failed) throws InferenceException {
+ if(failed.contains(sourcePre)) {
+ throw new InferenceException("Grouping " + groupingName + "was not found.", usesSource);
+ }
+ throw new InferenceException("Unknown error occured.", usesSource);
+ }
+
+ });
+
+ }
+
+ @Override
+ public UsesStatement createDeclared(StmtContext<QName, UsesStatement, ?> ctx) {
+ return new UsesStatementImpl(ctx);
+ }
+
+ @Override
+ public EffectiveStatement<QName, UsesStatement> createEffective(
+ StmtContext<QName, UsesStatement, EffectiveStatement<QName, UsesStatement>> ctx) {
+ throw new UnsupportedOperationException("Not implemented yet.");
+ }
+
+ }
+
+ @Override
+ public QName getName() {
+ return argument();
+ }
+
+ @Override
+ public WhenStatement getWhenStatement() {
+ return firstDeclared(WhenStatement.class);
+ }
+
+ @Override
+ public Collection<? extends IfFeatureStatement> getIfFeatures() {
+ return allDeclared(IfFeatureStatement.class);
+ }
+
+ @Override
+ public StatusStatement getStatus() {
+ return firstDeclared(StatusStatement.class);
+ }
+
+ @Override
+ public DescriptionStatement getDescription() {
+ return firstDeclared(DescriptionStatement.class);
+ }
+
+ @Override
+ public ReferenceStatement getReference() {
+ return firstDeclared(ReferenceStatement.class);
+ }
+
+ @Override
+ public Collection<? extends AugmentStatement> getAugments() {
+ return allDeclared(AugmentStatement.class);
+ }
+
+ @Override
+ public Collection<? extends RefineStatement> getRefines() {
+ return allDeclared(RefineStatement.class);
+ }
+
+ @Override
+ public QName argument() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String rawArgument() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Collection<? extends DeclaredStatement<?>> declaredSubstatements() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public StatementDefinition statementDefinition() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public StatementSource getStatementSource() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
--- /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 org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
+
+public class Utils {
+
+
+ public static QName qNameFromArgument(StmtContext<?,?,?> ctx, String value) {
+ // TODO: Implement real parsing
+ String prefix = "";
+ ctx.getFromNamespace(PrefixToModule.class, prefix);
+
+ return QName.create(value);
+ }
+
+
+}
--- /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 static org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.global;
+import static org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.sourceLocal;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+
+public final class YangInferencePipeline {
+
+ public static final StatementSupportBundle LINKAGE_BUNDLE = StatementSupportBundle.builder()
+ .addSupport(new ModuleStatementSupport())
+ .addSupport(new NamespaceStatementImpl.Definition())
+ .addSupport(new ImportStatementDefinition())
+ .addSupport(new PrefixStatementImpl.Definition())
+ .addSupport(global(ModuleNamespace.class))
+ .addSupport(global(NamespaceToModule.class))
+ .addSupport(sourceLocal(ImportedModuleContext.class))
+ .build();
+
+ private static final StatementSupportBundle STMT_DEF_BUNDLE = StatementSupportBundle.derivedFrom(LINKAGE_BUNDLE).build();
+
+ private static final StatementSupportBundle FULL_DECL_BUNDLE = StatementSupportBundle.derivedFrom(STMT_DEF_BUNDLE).build();
+
+ public static final Map<ModelProcessingPhase, StatementSupportBundle> RFC6020_BUNDLES = ImmutableMap
+ .<ModelProcessingPhase, StatementSupportBundle> builder()
+ .put(ModelProcessingPhase.SourceLinkage, LINKAGE_BUNDLE)
+ .put(ModelProcessingPhase.StatementDefinition,STMT_DEF_BUNDLE)
+ .put(ModelProcessingPhase.FullDeclaration,FULL_DECL_BUNDLE)
+ .put(ModelProcessingPhase.EffectiveModel,FULL_DECL_BUNDLE)
+ .build();
+
+ public static final CrossSourceStatementReactor RFC6020_REACTOR = CrossSourceStatementReactor.builder()
+ .setBundle(ModelProcessingPhase.SourceLinkage, LINKAGE_BUNDLE)
+ .setBundle(ModelProcessingPhase.StatementDefinition,STMT_DEF_BUNDLE)
+ .setBundle(ModelProcessingPhase.FullDeclaration,FULL_DECL_BUNDLE)
+ .setBundle(ModelProcessingPhase.EffectiveModel,FULL_DECL_BUNDLE)
+ .build();
+
+ private YangInferencePipeline() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+}
package org.opendaylight.yangtools.yang.parser.impl.util;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-
+import static org.junit.Assert.assertTrue;
import java.io.InputStream;
import org.junit.Test;
assertEquals("ietf-inet-types", info.getName());
assertEquals("2010-09-24", info.getFormattedRevision());
assertNotNull(info.getDependencies());
+
+ assertTrue(info.equals(info));
}
@Test
assertEquals("module-without-revision", info.getName());
assertNull(info.getFormattedRevision());
}
+
+ @Test
+ public void testEquals() {
+ InputStream stream1 = getClass().getResourceAsStream("/ietf/ietf-inet-types@2010-09-24.yang");
+ YangModelDependencyInfo info1 = YangModelDependencyInfo.fromInputStream(stream1);
+ InputStream stream2 = getClass().getResourceAsStream("/no-revision/module-without-revision.yang");
+ YangModelDependencyInfo info2 = YangModelDependencyInfo.fromInputStream(stream2);
+
+ assertTrue(info1.equals(info1));
+ assertFalse(info1.equals(null));
+ assertFalse(info1.equals(stream1));
+ assertFalse(info1.equals(info2));
+ }
+
+ @Test
+ public void testHashcode() {
+ InputStream stream = getClass().getResourceAsStream("/no-revision/module-without-revision.yang");
+ YangModelDependencyInfo info = YangModelDependencyInfo.fromInputStream(stream);
+
+ assertNotEquals("hashcode", 31, info.hashCode());
+ }
}
--- /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.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor.BuildAction;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
+
+public class ImportResolutionTest {
+
+ private static final TestStatementSource ROOT_WITHOUT_IMPORT = new TestStatementSource("nature");
+ private static final TestStatementSource IMPORT_ROOT = new TestStatementSource("mammal","nature");
+ private static final TestStatementSource IMPORT_DERIVED = new TestStatementSource("human", "mammal");
+ private static final TestStatementSource IMPORT_SELF = new TestStatementSource("egocentric", "egocentric");
+ private static final TestStatementSource CICLE_YIN = new TestStatementSource("cycle-yin", "cycle-yang");
+ private static final TestStatementSource CICLE_YANG = new TestStatementSource("cycle-yang", "cycle-yin");
+
+
+ @Test
+ public void inImportOrderTest() throws SourceException, ReactorException {
+ BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
+ addSources(reactor,ROOT_WITHOUT_IMPORT,IMPORT_ROOT,IMPORT_DERIVED);
+ EffectiveModelContext result = reactor.build();
+ assertNotNull(result);
+ }
+
+ @Test
+ public void inInverseOfImportOrderTest() throws SourceException, ReactorException {
+ BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
+ addSources(reactor,IMPORT_DERIVED,IMPORT_ROOT,ROOT_WITHOUT_IMPORT);
+ EffectiveModelContext result = reactor.build();
+ assertNotNull(result);
+ }
+
+ @Test
+ public void missingImportedSourceTest() throws SourceException {
+ BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
+ addSources(reactor,IMPORT_DERIVED,ROOT_WITHOUT_IMPORT);
+ try {
+ reactor.build();
+ fail("reactor.process should fail doe to misssing imported source");
+ } catch (ReactorException e) {
+ assertTrue(e instanceof SomeModifiersUnresolvedException);
+ assertEquals(ModelProcessingPhase.SourceLinkage,e.getPhase());
+ }
+
+ }
+
+ @Test
+ public void circularImportsTest() throws SourceException {
+ BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
+ addSources(reactor,CICLE_YIN,CICLE_YANG);
+ try {
+ reactor.build();
+ fail("reactor.process should fail doe to circular import");
+ } catch (ReactorException e) {
+ assertTrue(e instanceof SomeModifiersUnresolvedException);
+ assertEquals(ModelProcessingPhase.SourceLinkage,e.getPhase());
+ }
+ }
+
+ @Test
+ public void selfImportTest() throws SourceException {
+ BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
+ addSources(reactor,IMPORT_SELF,IMPORT_ROOT,ROOT_WITHOUT_IMPORT);
+ try {
+ reactor.build();
+ fail("reactor.process should fail doe to self import");
+ } catch (ReactorException e) {
+ assertTrue(e instanceof SomeModifiersUnresolvedException);
+ assertEquals(ModelProcessingPhase.SourceLinkage,e.getPhase());
+ }
+ }
+
+
+ private void addSources(BuildAction reactor, TestStatementSource... sources) {
+ for(TestStatementSource source : sources) {
+ reactor.addSource(source);
+ }
+ }
+
+}
--- /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.opendaylight.yangtools.yang.model.api.Rfc6020Mapping.Import;
+import static org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping.Module;
+import static org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping.Namespace;
+import static org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping.Prefix;
+
+import java.util.Arrays;
+import java.util.List;
+import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
+import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
+import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
+
+class TestStatementSource implements StatementStreamSource {
+
+ private static final String NS_PREFIX = "urn:org:opendaylight:yangtools:test:";
+
+ private final String name;
+ private final List<String> imports;
+ private StatementWriter writer;
+ private StatementSourceReference REF = new StatementSourceReference() {
+
+ @Override
+ public StatementSource getStatementSource() {
+ return StatementSource.DECLARATION;
+ }
+ };
+
+
+ public TestStatementSource(String name, String... imports) {
+ this.name = name;
+ this.imports = Arrays.asList(imports);
+ }
+
+ @Override
+ public void writeFull(StatementWriter writer, QNameToStatementDefinition stmtDef, PrefixToModule prefixes)
+ throws SourceException {
+ this.writer = writer;
+ header();
+ extensions();
+ body();
+ end();
+
+ }
+
+
+
+ @Override
+ public void writeLinkage(StatementWriter writer, QNameToStatementDefinition stmtDef) throws SourceException {
+ this.writer = writer;
+ header().end();
+ }
+
+ @Override
+ public void writeLinkageAndStatementDefinitions(StatementWriter writer, QNameToStatementDefinition stmtDef,
+ PrefixToModule prefixes) throws SourceException {
+ this.writer = writer;
+ header();
+ extensions();
+ end();
+
+ }
+
+ protected void extensions() {
+ // TODO Auto-generated method stub
+
+ }
+
+ protected void body() {
+
+ }
+
+ TestStatementSource header() throws SourceException {
+ stmt(Module).arg(name); {
+ stmt(Namespace).arg(getNamespace()).end();
+ stmt(Prefix).arg(name).end();
+ for(String imp : imports) {
+ stmt(Import).arg(imp);
+ stmt(Prefix).arg(imp).end();
+ end();
+ }
+ }
+ return this;
+ }
+
+ private String getNamespace() {
+ return NS_PREFIX + name;
+ }
+
+ protected TestStatementSource arg(String arg) throws SourceException {
+ writer.argumentValue(arg, REF);
+ return this;
+ }
+
+ protected TestStatementSource stmt(Rfc6020Mapping stmt) throws SourceException {
+ writer.startStatement(stmt.getStatementName(), REF);
+ return this;
+ }
+
+ protected TestStatementSource end() throws SourceException {
+ writer.endStatement(REF);
+ return this;
+ }
+
+
+}