Merge "BUG-2159: update karaf version to 3.0.2"
authorTony Tkacik <ttkacik@cisco.com>
Wed, 7 Jan 2015 16:15:43 +0000 (16:15 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 7 Jan 2015 16:15:43 +0000 (16:15 +0000)
26 files changed:
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingToNormalizedStreamWriter.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataContainerCodecPrototype.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/KeyedListNodeCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ListNodeCodecContext.java
code-generator/binding-parent/pom.xml
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodes.java [moved from yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedNodeUtils.java with 53% similarity]
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/StoreTreeNodes.java [moved from yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/TreeNodeUtils.java with 90% similarity]
yang/yang-data-impl/pom.xml
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/NodeUtils.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedValueAttrNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/DataTreeState.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTree.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeModification.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/InMemoryDataTreeSnapshot.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModifiedNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/NormalizedNodeContainerModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/SchemaAwareApplyOperation.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/StoreUtils.java [deleted file]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnkeyedListModificationStrategy.java [new file with mode: 0644]
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/NodeHelper.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/test/NormalizedNodeUtilsTest.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/StoreTreeNodesTest.java [moved from yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/TreeNodeUtilsTest.java with 87% similarity]
yang/yang-parser-impl/src/main/antlr/YangParser.g4
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/YangParserTest.java
yang/yang-parser-impl/src/test/resources/yang-grammar-test/revisions-extension.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/yang-grammar-test/submodule-header-extension.yang [new file with mode: 0644]

index 9c12bbd42a2a022ee321c97b4c7848c20001e1b5..a110ff8347bb2e5d7ba82fbb2c75b8e14a7c40fe 100644 (file)
@@ -8,14 +8,12 @@
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.base.Preconditions;
-
 import java.io.IOException;
 import java.util.AbstractMap;
 import java.util.ArrayDeque;
 import java.util.Deque;
 import java.util.Map;
 import java.util.Map.Entry;
-
 import org.opendaylight.yangtools.concepts.Delegator;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
@@ -158,7 +156,7 @@ class BindingToNormalizedStreamWriter implements BindingStreamEventWriter, Deleg
     @Override
     public void startMapEntryNode(final Identifier<?> key, final int childSizeHint) throws IOException, IllegalArgumentException {
         duplicateSchemaEnter();
-        NodeIdentifierWithPredicates identifier = ((ListNodeCodecContext) current()).serialize(key);
+        NodeIdentifierWithPredicates identifier = ((KeyedListNodeCodecContext) current()).serialize(key);
         getDelegate().startMapEntryNode(identifier, childSizeHint);
     };
 
index 4fae734ef6f981a7706eabccf7cf1cece6ac58c0..353fedaa54c6155a5c81404c2e313e89ecf880c9 100644 (file)
@@ -8,11 +8,10 @@
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.collect.Iterables;
-
 import javax.annotation.concurrent.GuardedBy;
-
 import org.opendaylight.yangtools.binding.data.codec.impl.NodeCodecContext.CodecContextFactory;
 import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -130,7 +129,11 @@ class DataContainerCodecPrototype<T> implements NodeContextSupplier {
         if (schema instanceof ContainerSchemaNode) {
             return new ContainerNodeCodecContext((DataContainerCodecPrototype) this);
         } else if (schema instanceof ListSchemaNode) {
-            return new ListNodeCodecContext((DataContainerCodecPrototype) this);
+            if (Identifiable.class.isAssignableFrom(getBindingClass())) {
+                return new KeyedListNodeCodecContext((DataContainerCodecPrototype) this);
+            } else {
+                return new ListNodeCodecContext((DataContainerCodecPrototype) this);
+            }
         } else if (schema instanceof ChoiceNode) {
             return new ChoiceNodeCodecContext((DataContainerCodecPrototype) this);
         } else if (schema instanceof AugmentationSchema) {
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/KeyedListNodeCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/KeyedListNodeCodecContext.java
new file mode 100644 (file)
index 0000000..e577c93
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class KeyedListNodeCodecContext extends ListNodeCodecContext {
+    private final Codec<NodeIdentifierWithPredicates, IdentifiableItem<?, ?>> codec;
+    private final Method keyGetter;
+
+    KeyedListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
+        super(prototype);
+
+        this.codec = factory().getPathArgumentCodec(bindingClass(), schema());
+        try {
+            this.keyGetter = bindingClass().getMethod("getKey");
+        } catch (NoSuchMethodException e) {
+            throw new IllegalStateException("Required method not available", e);
+        }
+    }
+
+    @Override
+    protected void addYangPathArgument(final InstanceIdentifier.PathArgument arg, final List<YangInstanceIdentifier.PathArgument> builder) {
+        /*
+         * DOM Instance Identifier for list is always represent by two
+         * entries one for map and one for children. This is also true for
+         * wildcarded instance identifiers
+         */
+        if (builder == null) {
+            return;
+        }
+
+        super.addYangPathArgument(arg, builder);
+        if (arg instanceof IdentifiableItem<?, ?>) {
+            builder.add(codec.serialize((IdentifiableItem<?, ?>) arg));
+        } else {
+            // Adding wildcarded
+            super.addYangPathArgument(arg, builder);
+        }
+    }
+
+    @Override
+    @SuppressWarnings("rawtypes")
+    Object getBindingChildValue(final Method method, final NormalizedNodeContainer dom) {
+        if (dom instanceof MapEntryNode && keyGetter.equals(method)) {
+            NodeIdentifierWithPredicates identifier = ((MapEntryNode) dom).getIdentifier();
+            return codec.deserialize(identifier).getKey();
+        } else {
+            return super.getBindingChildValue(method, dom);
+        }
+    }
+
+    @Override
+    protected InstanceIdentifier.PathArgument getBindingPathArgument(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument domArg) {
+        if (domArg instanceof NodeIdentifierWithPredicates) {
+            return codec.deserialize((NodeIdentifierWithPredicates) domArg);
+        }
+        return super.getBindingPathArgument(domArg);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    NodeIdentifierWithPredicates serialize(final Identifier<?> key) {
+        return codec.serialize(new IdentifiableItem(bindingClass(), key));
+    }
+}
index da174b0ab687a48ef397bb9b61ee66951e16e6e3..d9acc2c3423a3913e6358e034d17f51e8c5f45a9 100644 (file)
@@ -8,76 +8,19 @@
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.collect.Iterables;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
-import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.Identifiable;
-import org.opendaylight.yangtools.yang.binding.Identifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
-final class ListNodeCodecContext extends DataObjectCodecContext<ListSchemaNode> {
-    private final Codec<NodeIdentifierWithPredicates, IdentifiableItem<?, ?>> codec;
-    private final Method keyGetter;
-
-    ListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
+class ListNodeCodecContext extends DataObjectCodecContext<ListSchemaNode> {
+    protected ListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
         super(prototype);
-        if (Identifiable.class.isAssignableFrom(bindingClass())) {
-            this.codec = factory().getPathArgumentCodec(bindingClass(),schema());
-            try {
-                this.keyGetter = bindingClass().getMethod("getKey");
-            } catch (NoSuchMethodException e) {
-                throw new IllegalStateException("Required method not available");
-            }
-        } else {
-            this.codec = null;
-            this.keyGetter = null;
-        }
-    }
-
-    @Override
-    public void addYangPathArgument(final InstanceIdentifier.PathArgument arg, final List<YangInstanceIdentifier.PathArgument> builder) {
-
-        /*
-         * DOM Instance Identifier for list is always represent by two
-         * entries one for map and one for children. This is also true for
-         * wildcarded instance identifiers
-         */
-        if (builder == null) {
-            return;
-        }
-        super.addYangPathArgument(arg, builder);
-        if (arg instanceof IdentifiableItem<?, ?>) {
-            builder.add(codec.serialize((IdentifiableItem<?, ?>) arg));
-        } else {
-            // Adding wildcarded
-            super.addYangPathArgument(arg, builder);
-        }
-    }
-
-    @Override
-    public InstanceIdentifier.PathArgument getBindingPathArgument(
-            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument domArg) {
-        if (domArg instanceof NodeIdentifierWithPredicates) {
-            return codec.deserialize((NodeIdentifierWithPredicates) domArg);
-        }
-        return super.getBindingPathArgument(domArg);
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    public NodeIdentifierWithPredicates serialize(final Identifier<?> key) {
-        return codec.serialize(new IdentifiableItem(bindingClass(), key));
     }
 
     @Override
@@ -119,14 +62,4 @@ final class ListNodeCodecContext extends DataObjectCodecContext<ListSchemaNode>
         }
         return ret;
     }
-
-    @Override
-    @SuppressWarnings("rawtypes")
-    Object getBindingChildValue(final Method method, final NormalizedNodeContainer dom) {
-        if (dom instanceof MapEntryNode && method.equals(keyGetter)) {
-            NodeIdentifierWithPredicates identifier = ((MapEntryNode) dom).getIdentifier();
-            return codec.deserialize(identifier).getKey();
-        }
-        return super.getBindingChildValue(method, dom);
-    }
 }
\ No newline at end of file
index d274762ca989790e94fdc23364e8163dfeb36ccc..0723bc8416a016545b50de5fd2502a4440afc884 100644 (file)
@@ -1,13 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
 <!--
-Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ 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
+ 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">
+<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">
 
     <parent>
         <groupId>org.opendaylight.odlparent</groupId>
@@ -26,6 +26,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         <yangtools.version>0.7.0-SNAPSHOT</yangtools.version>
         <salGeneratorPath>src/main/yang-gen-sal</salGeneratorPath>
     </properties>
+
     <profiles>
         <profile>
             <activation>
similarity index 53%
rename from yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedNodeUtils.java
rename to yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/NormalizedNodes.java
index 997db8eab762ac73c0cdb8dabdcee91d1440decc..5f305d988c02e5d691e00405bff98775596ff950 100644 (file)
@@ -5,28 +5,28 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.yangtools.yang.data.impl.schema;
+package org.opendaylight.yangtools.yang.data.api.schema;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-
+import com.google.common.annotations.Beta;
 import com.google.common.base.Optional;
-
+import com.google.common.base.Strings;
 import java.util.Iterator;
-
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
-public final class NormalizedNodeUtils {
-    private NormalizedNodeUtils() {
-        throw new UnsupportedOperationException("Utilities class should not be instantiated");
+/**
+ * A set of utility methods for interacting with {@link NormalizedNode} objects.
+ */
+@Beta
+public final class NormalizedNodes {
+    private static final int STRINGTREE_INDENT = 4;
+
+    private NormalizedNodes() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
     }
 
     public static Optional<NormalizedNode<?, ?>> findNode(final YangInstanceIdentifier rootPath, final NormalizedNode<?, ?> rootNode, final YangInstanceIdentifier childPath) {
@@ -63,4 +63,48 @@ public final class NormalizedNodeUtils {
         }
         return Optional.absent();
     }
+
+    /**
+     * Convert a data subtree under a node into a human-readable string format.
+     *
+     * @param node Data subtree root
+     * @return String containing a human-readable form of the subtree.
+     */
+    public static String toStringTree(final NormalizedNode<?, ?> node) {
+        final StringBuilder builder = new StringBuilder();
+        toStringTree(builder, node, 0);
+        return builder.toString();
+    }
+
+    private static void toStringTree(final StringBuilder builder, final NormalizedNode<?, ?> node, final int offset) {
+        final String prefix = Strings.repeat(" ", offset);
+
+        builder.append(prefix).append(toStringTree(node.getIdentifier()));
+        if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
+            final NormalizedNodeContainer<?, ?, ?> container = (NormalizedNodeContainer<?, ?, ?>) node;
+
+            builder.append(" {\n");
+            for (NormalizedNode<?, ?> child : container.getValue()) {
+                toStringTree(builder, child, offset + STRINGTREE_INDENT);
+            }
+
+            builder.append(prefix).append('}');
+        } else {
+            builder.append(' ').append(node.getValue());
+        }
+        builder.append('\n');
+    }
+
+    private static String toStringTree(final PathArgument identifier) {
+        if (identifier instanceof NodeIdentifierWithPredicates) {
+            StringBuilder builder = new StringBuilder();
+            builder.append(identifier.getNodeType().getLocalName());
+            builder.append(((NodeIdentifierWithPredicates) identifier).getKeyValues().values());
+            return builder.toString();
+        } else if (identifier instanceof AugmentationIdentifier) {
+            return "augmentation";
+        } else {
+            return identifier.getNodeType().getLocalName();
+        }
+    }
 }
similarity index 90%
rename from yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/TreeNodeUtils.java
rename to yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/StoreTreeNodes.java
index 491594d1c4649c7370f74b5be036fb1bb60a14e6..50f3766536feab6af3ee4fc34f7a7e0c36a1615c 100644 (file)
@@ -5,8 +5,9 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+package org.opendaylight.yangtools.yang.data.api.schema.tree;
 
+import com.google.common.annotations.Beta;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
@@ -17,13 +18,13 @@ import java.util.Iterator;
 import java.util.Map;
 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.tree.StoreTreeNode;
 
 /**
- * A set of utility methods for interacting with {@link org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode} objects.
+ * A set of utility methods for interacting with {@link StoreTreeNode} objects.
  */
-public final class TreeNodeUtils {
-    private TreeNodeUtils() {
+@Beta
+public final class StoreTreeNodes {
+    private StoreTreeNodes() {
         throw new UnsupportedOperationException("Utility class should not be instantiated");
     }
 
@@ -82,7 +83,7 @@ public final class TreeNodeUtils {
             current = current.get().getChild(pathIter.next());
             nesting++;
         }
-        if(current.isPresent()) {
+        if (current.isPresent()) {
             final YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(Iterables.limit(path.getPathArguments(), nesting));
             return new SimpleEntry<YangInstanceIdentifier,T>(currentPath,current.get());
         }
@@ -98,11 +99,10 @@ public final class TreeNodeUtils {
         return new SimpleEntry<YangInstanceIdentifier,T>(parentPath,parent.get());
     }
 
-    public static <T extends StoreTreeNode<T>> Optional<T> getChild(final Optional<T> parent,final PathArgument child) {
-        if(parent.isPresent()) {
+    public static <T extends StoreTreeNode<T>> Optional<T> getChild(final Optional<T> parent, final PathArgument child) {
+        if (parent.isPresent()) {
             return parent.get().getChild(child);
         }
         return Optional.absent();
     }
-
 }
index a7b14062170bab6c7896c49dcdacbb2d1922adac..4ae9186ca42e614a63d5c569d4be34b15edc6470 100644 (file)
@@ -25,7 +25,6 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
-                <version>${maven.surefire.version}</version>
                 <configuration>
                 <argLine>-Dlog4j.configuration=log4j-test.xml
                     -Xmx1500m ${jacoco.agent.ut.arg}</argLine>
index b1ff225026b543affbbc2ef432f5a776b9fab0e1..10e79e2bf3d91ec9cf476967064a94cbf966a37c 100644 (file)
@@ -13,7 +13,6 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-
 import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
@@ -21,7 +20,6 @@ import java.util.Deque;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import javax.annotation.Nonnull;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -31,14 +29,13 @@ import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.NodeModification;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -50,7 +47,7 @@ import org.w3c.dom.Element;
 /**
  * @author michal.rehak
  *
- * @deprecated Use {@link NormalizedNodeUtils} instead.
+ * @deprecated Use {@link NormalizedNodes} instead.
  */
 @Deprecated
 public abstract class NodeUtils {
index 8f9e1019e5c118ce33efd08cf18dd9d9ac982a45..ad951f3333e938fafc6adbdfffd9173786924794 100644 (file)
@@ -9,9 +9,7 @@ package org.opendaylight.yangtools.yang.data.impl.schema.nodes;
 
 import com.google.common.base.Objects.ToStringHelper;
 import com.google.common.collect.ImmutableMap;
-
 import java.util.Map;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
index 9419d08f67566b36643348972afcbb6da2b8bef0..9790fc2d87f994ca1516bd98927e6f86614ca751 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -59,6 +60,6 @@ final class DataTreeState {
     @Override
     public String toString() {
         final TreeNode r = root;
-        return Objects.toStringHelper(this).add("data", StoreUtils.toStringTree(r.getData())).toString();
+        return Objects.toStringHelper(this).add("data", NormalizedNodes.toStringTree(r.getData())).toString();
     }
 }
\ No newline at end of file
index 9d60ed0a9b022f40e53384f60b6a0b9c06f85de5..38e884c0969de9b356d40ba861d5314221b526a7 100644 (file)
@@ -14,6 +14,7 @@ import java.util.Collections;
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
 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.NormalizedNodes;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
@@ -106,7 +107,7 @@ final class InMemoryDataTree implements DataTree {
         final InMemoryDataTreeCandidate c = (InMemoryDataTreeCandidate)candidate;
 
         if (LOG.isTraceEnabled()) {
-            LOG.trace("Data Tree is {}", StoreUtils.toStringTree(c.getAfterRoot().getData()));
+            LOG.trace("Data Tree is {}", NormalizedNodes.toStringTree(c.getAfterRoot().getData()));
         }
 
         final TreeNode newRoot = c.getAfterRoot();
index f23cadcf0d2d57b55de1eca7cd975d94c9622bc1..0b0c8516d84969e262b2b9878574b14bbc073620 100644 (file)
@@ -14,11 +14,12 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 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.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.StoreTreeNodes;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -87,14 +88,14 @@ final class InMemoryDataTreeModification implements DataTreeModification {
          * the requested path which has been modified. If no such node exists,
          * we use the node itself.
          */
-        final Entry<YangInstanceIdentifier, ModifiedNode> entry = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, ModifiedNode.IS_TERMINAL_PREDICATE);
+        final Entry<YangInstanceIdentifier, ModifiedNode> entry = StoreTreeNodes.findClosestsOrFirstMatch(rootNode, path, ModifiedNode.IS_TERMINAL_PREDICATE);
         final YangInstanceIdentifier key = entry.getKey();
         final ModifiedNode mod = entry.getValue();
 
         final Optional<TreeNode> result = resolveSnapshot(key, mod);
         if (result.isPresent()) {
             NormalizedNode<?, ?> data = result.get().getData();
-            return NormalizedNodeUtils.findNode(key, data, path);
+            return NormalizedNodes.findNode(key, data, path);
         } else {
             return Optional.absent();
         }
@@ -121,7 +122,7 @@ final class InMemoryDataTreeModification implements DataTreeModification {
             strategyTree.upgradeIfPossible();
         }
 
-        return TreeNodeUtils.<ModificationApplyOperation>findNodeChecked(strategyTree, path);
+        return StoreTreeNodes.<ModificationApplyOperation>findNodeChecked(strategyTree, path);
     }
 
     private OperationWithModification resolveModificationFor(final YangInstanceIdentifier path) {
index 0e61cd4031605bb221f5abd22eadedb95079168a..6d3f9a3cbfe02f07621e1999ca783985f8d66c25 100644 (file)
@@ -1,16 +1,15 @@
 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
 final class InMemoryDataTreeSnapshot implements DataTreeSnapshot {
     private final RootModificationApplyOperation applyOper;
     private final SchemaContext schemaContext;
@@ -33,7 +32,7 @@ final class InMemoryDataTreeSnapshot implements DataTreeSnapshot {
 
     @Override
     public Optional<NormalizedNode<?, ?>> readNode(final YangInstanceIdentifier path) {
-        return NormalizedNodeUtils.findNode(rootNode.getData(), path);
+        return NormalizedNodes.findNode(rootNode.getData(), path);
     }
 
     @Override
index 5e9c0eb268f933ad7b7eccee3cd8b62c0a6ab3ba..da21aa52619af5a241b7a60851b84acd60f04831 100644 (file)
@@ -30,12 +30,11 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
  * to the data store tree.
  *
  * This tree is lazily created and populated via {@link #modifyChild(PathArgument)}
- * and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}.
+ * and {@link TreeNode} which represents original state as tracked by {@link #getOriginal()}.
  */
 @NotThreadSafe
 final class ModifiedNode extends NodeModification implements StoreTreeNode<ModifiedNode> {
-
-    public static final Predicate<ModifiedNode> IS_TERMINAL_PREDICATE = new Predicate<ModifiedNode>() {
+    static final Predicate<ModifiedNode> IS_TERMINAL_PREDICATE = new Predicate<ModifiedNode>() {
         @Override
         public boolean apply(final @Nonnull ModifiedNode input) {
             Preconditions.checkNotNull(input);
@@ -72,9 +71,9 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode<Modif
     }
 
     /**
+     * Return the value which was written to this node.
      *
-     *
-     * @return
+     * @return Currently-written value
      */
     public NormalizedNode<?, ?> getWrittenValue() {
         return value;
@@ -120,17 +119,17 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode<Modif
 
     /**
      *
-     * Returns child modification if child was modified, creates {@link org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ModifiedNode}
+     * Returns child modification if child was modified, creates {@link ModifiedNode}
      * for child otherwise.
      *
      * If this node's {@link ModificationType} is {@link ModificationType#UNMODIFIED}
      * changes modification type to {@link ModificationType#SUBTREE_MODIFIED}
      *
      * @param child
-     * @return {@link org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ModifiedNode} for specified child, with {@link #getOriginal()}
+     * @return {@link ModifiedNode} for specified child, with {@link #getOriginal()}
      *         containing child metadata if child was present in original data.
      */
-    public ModifiedNode modifyChild(final PathArgument child, final boolean isOrdered) {
+    ModifiedNode modifyChild(final PathArgument child, final boolean isOrdered) {
         clearSnapshot();
         if (modificationType == ModificationType.UNMODIFIED) {
             updateModificationType(ModificationType.SUBTREE_MODIFIED);
@@ -154,7 +153,6 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode<Modif
     }
 
     /**
-     *
      * Returns all recorded direct child modification
      *
      * @return all recorded direct child modifications
@@ -165,11 +163,9 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode<Modif
     }
 
     /**
-     *
      * Records a delete for associated node.
-     *
      */
-    public void delete() {
+    void delete() {
         final ModificationType newType;
 
         switch (modificationType) {
@@ -202,23 +198,37 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode<Modif
     }
 
     /**
-     *
      * Records a write for associated node.
      *
      * @param value
      */
-    public void write(final NormalizedNode<?, ?> value) {
+    void write(final NormalizedNode<?, ?> value) {
         clearSnapshot();
         updateModificationType(ModificationType.WRITE);
         children.clear();
         this.value = value;
     }
 
-    public void merge(final NormalizedNode<?, ?> data) {
+    void merge(final NormalizedNode<?, ?> value) {
         clearSnapshot();
         updateModificationType(ModificationType.MERGE);
-        // FIXME: Probably merge with previous value.
-        this.value = data;
+
+        /*
+         * Blind overwrite of any previous data is okay, no matter whether the node
+         * is simple or complex type.
+         *
+         * If this is a simple or complex type with unkeyed children, this merge will
+         * be turned into a write operation, overwriting whatever was there before.
+         *
+         * If this is a container with keyed children, there are two possibilities:
+         * - if it existed before, this value will never be consulted and the children
+         *   will get explicitly merged onto the original data.
+         * - if it did not exist before, this value will be used as a seed write and
+         *   children will be merged into it.
+         * In either case we rely on OperationWithModification to manipulate the children
+         * before calling this method, so unlike a write we do not want to clear them.
+         */
+        this.value = value;
     }
 
     /**
index cd27513ba036d9261990de4c133bc83a140100c9..47e2e85e3e2e66817ecedd17f0014ade2050ad00 100644 (file)
@@ -56,7 +56,7 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
     @SuppressWarnings("rawtypes")
     @Override
     protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
-        checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
+        checkArgument(nodeClass.isInstance(writtenValue), "Node %s is not of type %s", writtenValue, nodeClass);
         checkArgument(writtenValue instanceof NormalizedNodeContainer);
 
         NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
@@ -92,6 +92,11 @@ abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareAp
          * As it turns out, once we materialize the written data, we can share the
          * code path with the subtree change. So let's create an unsealed TreeNode
          * and run the common parts on it -- which end with the node being sealed.
+         *
+         * FIXME: this code needs to be moved out from the prepare() path and into
+         *        the read() and seal() paths. Merging of writes needs to be charged
+         *        to the code which originated this, not to the code which is
+         *        attempting to make it visible.
          */
         final MutableTreeNode mutable = newValueMeta.mutable();
         mutable.setSubtreeVersion(version);
index c2eebed882f810d7c8a47efdd0339e318ff2891a..e721221ee9249db083d16bb9c0fffdd4c1ede5a7 100644 (file)
@@ -9,25 +9,18 @@ package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
 import java.util.List;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.IncorrectDataStructureException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.MutableTreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
@@ -250,113 +243,4 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
             final Optional<TreeNode> current) throws DataValidationFailedException;
 
     protected abstract void verifyWrittenStructure(NormalizedNode<?, ?> writtenValue);
-
-    public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
-
-        private final Optional<ModificationApplyOperation> entryStrategy;
-
-        protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
-            entryStrategy = Optional.<ModificationApplyOperation> of(new DataNodeContainerModificationStrategy.UnkeyedListItemModificationStrategy(schema));
-        }
-
-        @Override
-        boolean isOrdered() {
-            return true;
-        }
-
-        @Override
-        protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
-                final Version version) {
-            return applyWrite(modification, Optional.of(currentMeta), version);
-        }
-
-        @Override
-        protected TreeNode applySubtreeChange(final ModifiedNode modification,
-                final TreeNode currentMeta, final Version version) {
-            throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
-        }
-
-        @Override
-        protected TreeNode applyWrite(final ModifiedNode modification,
-                final Optional<TreeNode> currentMeta, final Version version) {
-            final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
-            final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version);
-
-            if (Iterables.isEmpty(modification.getChildren())) {
-                return newValueMeta;
-            }
-
-            /*
-             * This is where things get interesting. The user has performed a write and
-             * then she applied some more modifications to it. So we need to make sense
-             * of that an apply the operations on top of the written value. We could have
-             * done it during the write, but this operation is potentially expensive, so
-             * we have left it out of the fast path.
-             *
-             * As it turns out, once we materialize the written data, we can share the
-             * code path with the subtree change. So let's create an unsealed TreeNode
-             * and run the common parts on it -- which end with the node being sealed.
-             */
-            final MutableTreeNode mutable = newValueMeta.mutable();
-            mutable.setSubtreeVersion(version);
-
-            @SuppressWarnings("rawtypes")
-            final NormalizedNodeContainerBuilder dataBuilder = ImmutableUnkeyedListEntryNodeBuilder
-                .create((UnkeyedListEntryNode) newValue);
-
-            return mutateChildren(mutable, dataBuilder, version, modification.getChildren());
-        }
-
-        /**
-         * Applies write/remove diff operation for each modification child in modification subtree.
-         * Operation also sets the Data tree references for each Tree Node (Index Node) in meta (MutableTreeNode) structure.
-         *
-         * @param meta MutableTreeNode (IndexTreeNode)
-         * @param data DataBuilder
-         * @param nodeVersion Version of TreeNode
-         * @param modifications modification operations to apply
-         * @return Sealed immutable copy of TreeNode structure with all Data Node references set.
-         */
-        @SuppressWarnings({ "rawtypes", "unchecked" })
-        private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
-            final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
-
-            for (ModifiedNode mod : modifications) {
-                final PathArgument id = mod.getIdentifier();
-                final Optional<TreeNode> cm = meta.getChild(id);
-
-                Optional<TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
-                if (result.isPresent()) {
-                    final TreeNode tn = result.get();
-                    meta.addChild(tn);
-                    data.addChild(tn.getData());
-                } else {
-                    meta.removeChild(id);
-                    data.removeChild(id);
-                }
-            }
-
-            meta.setData(data.build());
-            return meta.seal();
-        }
-
-        @Override
-        public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
-            if (child instanceof NodeIdentifier) {
-                return entryStrategy;
-            }
-            return Optional.absent();
-        }
-
-        @Override
-        protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
-
-        }
-
-        @Override
-        protected void checkSubtreeModificationApplicable(final YangInstanceIdentifier path, final NodeModification modification,
-                final Optional<TreeNode> current) throws IncorrectDataStructureException {
-            throw new IncorrectDataStructureException(path, "Subtree modification is not allowed.");
-        }
-    }
 }
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/StoreUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/StoreUtils.java
deleted file mode 100644 (file)
index 66dd68f..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.data.impl.schema.tree;
-
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-
-import com.google.common.base.Strings;
-
-/**
- * Data store tree manipulation utilities.
- */
-public final class StoreUtils {
-    private static final int STRINGTREE_INDENT = 4;
-
-    private StoreUtils() {
-        throw new UnsupportedOperationException("Utility class should not be instantiated");
-    }
-
-    /**
-     * Convert a data subtree under a node into a human-readable string format.
-     *
-     * @param node Data subtree root
-     * @return String containing a human-readable form of the subtree.
-     */
-    public static String toStringTree(final NormalizedNode<?, ?> node) {
-        final StringBuilder builder = new StringBuilder();
-        toStringTree(builder, node, 0);
-        return builder.toString();
-    }
-
-    private static void toStringTree(final StringBuilder builder, final NormalizedNode<?, ?> node, final int offset) {
-        final String prefix = Strings.repeat(" ", offset);
-
-        builder.append(prefix).append(toStringTree(node.getIdentifier()));
-        if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
-            final NormalizedNodeContainer<?, ?, ?> container = (NormalizedNodeContainer<?, ?, ?>) node;
-
-            builder.append(" {\n");
-            for (NormalizedNode<?, ?> child : container.getValue()) {
-                toStringTree(builder, child, offset + STRINGTREE_INDENT);
-            }
-
-            builder.append(prefix).append('}');
-        } else {
-            builder.append(' ').append(node.getValue());
-        }
-        builder.append('\n');
-    }
-
-    private static String toStringTree(final PathArgument identifier) {
-        if (identifier instanceof NodeIdentifierWithPredicates) {
-            StringBuilder builder = new StringBuilder();
-            builder.append(identifier.getNodeType().getLocalName());
-            builder.append(((NodeIdentifierWithPredicates) identifier).getKeyValues().values());
-            return builder.toString();
-        } else if (identifier instanceof AugmentationIdentifier) {
-            return "augmentation";
-        }
-        return identifier.getNodeType().getLocalName();
-    }
-}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnkeyedListModificationStrategy.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnkeyedListModificationStrategy.java
new file mode 100644 (file)
index 0000000..ace568f
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * 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.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;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.IncorrectDataStructureException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.MutableTreeNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
+
+    private final Optional<ModificationApplyOperation> entryStrategy;
+
+    protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
+        entryStrategy = Optional.<ModificationApplyOperation> of(new DataNodeContainerModificationStrategy.UnkeyedListItemModificationStrategy(schema));
+    }
+
+    @Override
+    boolean isOrdered() {
+        return true;
+    }
+
+    @Override
+    protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
+            final Version version) {
+        return applyWrite(modification, Optional.of(currentMeta), version);
+    }
+
+    @Override
+    protected TreeNode applySubtreeChange(final ModifiedNode modification,
+            final TreeNode currentMeta, final Version version) {
+        throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
+    }
+
+    @Override
+    protected TreeNode applyWrite(final ModifiedNode modification,
+            final Optional<TreeNode> currentMeta, final Version version) {
+        final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
+        final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version);
+
+        if (Iterables.isEmpty(modification.getChildren())) {
+            return newValueMeta;
+        }
+
+        /*
+         * This is where things get interesting. The user has performed a write and
+         * then she applied some more modifications to it. So we need to make sense
+         * of that an apply the operations on top of the written value. We could have
+         * done it during the write, but this operation is potentially expensive, so
+         * we have left it out of the fast path.
+         *
+         * As it turns out, once we materialize the written data, we can share the
+         * code path with the subtree change. So let's create an unsealed TreeNode
+         * and run the common parts on it -- which end with the node being sealed.
+         */
+        final MutableTreeNode mutable = newValueMeta.mutable();
+        mutable.setSubtreeVersion(version);
+
+        @SuppressWarnings("rawtypes")
+        final NormalizedNodeContainerBuilder dataBuilder = ImmutableUnkeyedListEntryNodeBuilder
+            .create((UnkeyedListEntryNode) newValue);
+
+        return mutateChildren(mutable, dataBuilder, version, modification.getChildren());
+    }
+
+    /**
+     * Applies write/remove diff operation for each modification child in modification subtree.
+     * Operation also sets the Data tree references for each Tree Node (Index Node) in meta (MutableTreeNode) structure.
+     *
+     * @param meta MutableTreeNode (IndexTreeNode)
+     * @param data DataBuilder
+     * @param nodeVersion Version of TreeNode
+     * @param modifications modification operations to apply
+     * @return Sealed immutable copy of TreeNode structure with all Data Node references set.
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
+        final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
+
+        for (ModifiedNode mod : modifications) {
+            final PathArgument id = mod.getIdentifier();
+            final Optional<TreeNode> cm = meta.getChild(id);
+
+            Optional<TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
+            if (result.isPresent()) {
+                final TreeNode tn = result.get();
+                meta.addChild(tn);
+                data.addChild(tn.getData());
+            } else {
+                meta.removeChild(id);
+                data.removeChild(id);
+            }
+        }
+
+        meta.setData(data.build());
+        return meta.seal();
+    }
+
+    @Override
+    public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+        if (child instanceof NodeIdentifier) {
+            return entryStrategy;
+        }
+        return Optional.absent();
+    }
+
+    @Override
+    protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+
+    }
+
+    @Override
+    protected void checkSubtreeModificationApplicable(final YangInstanceIdentifier path, final NodeModification modification,
+            final Optional<TreeNode> current) throws IncorrectDataStructureException {
+        throw new IncorrectDataStructureException(path, "Subtree modification is not allowed.");
+    }
+}
\ No newline at end of file
index 65ec09204be9f30e59aca16ad6705e3712413d5a..901750b6d1093bbc108b4cb56db3b3152f054164 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.yangtools.yang.data.impl;
 import groovy.lang.Binding;
 import groovy.lang.GroovyShell;
 import groovy.lang.Script;
-
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -24,20 +23,18 @@ import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
-
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
-
 import org.custommonkey.xmlunit.Diff;
 import org.junit.Assert;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
@@ -50,7 +47,7 @@ import org.xml.sax.SAXException;
 /**
  * @author michal.rehak
  *
- * @deprecated Use {@link NormalizedNodeUtils} instead.
+ * @deprecated Use {@link NormalizedNodes} instead.
  */
 @Deprecated
 public abstract class NodeHelper {
index 0b21ea01df59f34dec986632ff1a710efdc68fe3..ff2e18a8efc1061dad4c7b1017361a980b82aae5 100644 (file)
@@ -5,17 +5,15 @@ import static org.junit.Assert.assertTrue;
 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
-
+import com.google.common.base.Optional;
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
 
-import com.google.common.base.Optional;
-
 /**
  *
  * Schema structure of document is
@@ -108,10 +106,10 @@ public class NormalizedNodeUtilsTest {
         NormalizedNode<?, ?> tree = createDocumentOne();
         assertNotNull(tree);
 
-        Optional<NormalizedNode<?, ?>> listFooResult = NormalizedNodeUtils.findNode(tree, LIST_A_FOO_PATH);
+        Optional<NormalizedNode<?, ?>> listFooResult = NormalizedNodes.findNode(tree, LIST_A_FOO_PATH);
         assertTrue(listFooResult.isPresent());
 
-        Optional<NormalizedNode<?, ?>> listTwoResult = NormalizedNodeUtils.findNode(tree, LIST_B_TWO_PATH);
+        Optional<NormalizedNode<?, ?>> listTwoResult = NormalizedNodes.findNode(tree, LIST_B_TWO_PATH);
         assertTrue(listTwoResult.isPresent());
     }
 
similarity index 87%
rename from yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/TreeNodeUtilsTest.java
rename to yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/StoreTreeNodesTest.java
index 509037fbccc05915712c3fcd141f5658d079bd2e..20b35b34698e0fcdb6b010d21ab20a9338f35cee 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * 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.data.impl.schema.tree;
 
 import static org.junit.Assert.assertEquals;
@@ -8,17 +15,15 @@ import static org.junit.Assert.fail;
 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
-
 import com.google.common.base.Optional;
-
 import java.util.Map;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.StoreTreeNodes;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
@@ -27,9 +32,8 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
-public class TreeNodeUtilsTest {
-    private static final Logger LOG = LoggerFactory.getLogger(TreeNodeUtilsTest.class);
+public class StoreTreeNodesTest {
+    private static final Logger LOG = LoggerFactory.getLogger(StoreTreeNodesTest.class);
 
     private static final Short ONE_ID = 1;
     private static final Short TWO_ID = 2;
@@ -96,7 +100,7 @@ public class TreeNodeUtilsTest {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
                 TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
-        Optional<TreeNode> node = TreeNodeUtils.findNode(rootNode, OUTER_LIST_1_PATH);
+        Optional<TreeNode> node = StoreTreeNodes.findNode(rootNode, OUTER_LIST_1_PATH);
         assertPresentAndType(node, TreeNode.class);
     }
 
@@ -108,7 +112,7 @@ public class TreeNodeUtilsTest {
         final YangInstanceIdentifier outerList1InvalidPath = YangInstanceIdentifier.builder(TestModel.OUTER_LIST_PATH)
                 .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 3) //
                 .build();
-        Optional<TreeNode> node = TreeNodeUtils.findNode(rootNode, outerList1InvalidPath);
+        Optional<TreeNode> node = StoreTreeNodes.findNode(rootNode, outerList1InvalidPath);
         assertFalse(node.isPresent());
     }
 
@@ -119,7 +123,7 @@ public class TreeNodeUtilsTest {
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
         TreeNode foundNode = null;
         try {
-            foundNode = TreeNodeUtils.findNodeChecked(rootNode, OUTER_LIST_1_PATH);
+            foundNode = StoreTreeNodes.findNodeChecked(rootNode, OUTER_LIST_1_PATH);
         } catch (IllegalArgumentException e) {
             fail("Illegal argument exception was thrown and should not have been" + e.getMessage());
         }
@@ -135,7 +139,7 @@ public class TreeNodeUtilsTest {
                 .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 3) //
                 .build();
         try {
-            TreeNodeUtils.findNodeChecked(rootNode, outerList1InvalidPath);
+            StoreTreeNodes.findNodeChecked(rootNode, outerList1InvalidPath);
             fail("Illegal argument exception should have been thrown");
         } catch (IllegalArgumentException e) {
             LOG.debug("Illegal argument exception was thrown as expected: '{}' - '{}'", e.getClass(), e.getMessage());
@@ -147,9 +151,9 @@ public class TreeNodeUtilsTest {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
                 TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
-        Optional<TreeNode> expectedNode = TreeNodeUtils.findNode(rootNode, TWO_TWO_PATH);
+        Optional<TreeNode> expectedNode = StoreTreeNodes.findNode(rootNode, TWO_TWO_PATH);
         assertPresentAndType(expectedNode, TreeNode.class);
-        Map.Entry<YangInstanceIdentifier, TreeNode> actualNode = TreeNodeUtils.findClosest(rootNode, TWO_TWO_PATH);
+        Map.Entry<YangInstanceIdentifier, TreeNode> actualNode = StoreTreeNodes.findClosest(rootNode, TWO_TWO_PATH);
         assertEquals("Expected node and actual node are not the same", expectedNode.get(), actualNode.getValue());
     }
 
@@ -165,9 +169,9 @@ public class TreeNodeUtilsTest {
                 .node(TestModel.INNER_LIST_QNAME) //
                 .nodeWithKey(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "three") //
                 .build();
-        Optional<TreeNode> expectedNode = TreeNodeUtils.findNode(rootNode, outerListInnerListPath);
+        Optional<TreeNode> expectedNode = StoreTreeNodes.findNode(rootNode, outerListInnerListPath);
         assertPresentAndType(expectedNode, TreeNode.class);
-        Map.Entry<YangInstanceIdentifier, TreeNode> actualNode = TreeNodeUtils.findClosest(rootNode, twoTwoInvalidPath);
+        Map.Entry<YangInstanceIdentifier, TreeNode> actualNode = StoreTreeNodes.findClosest(rootNode, twoTwoInvalidPath);
         assertEquals("Expected node and actual node are not the same", expectedNode.get(), actualNode.getValue());
     }
 
@@ -176,7 +180,7 @@ public class TreeNodeUtilsTest {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
                 TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
-        Optional<TreeNode> node = TreeNodeUtils.getChild(Optional.fromNullable(rootNode),
+        Optional<TreeNode> node = StoreTreeNodes.getChild(Optional.fromNullable(rootNode),
                 TestModel.TEST_PATH.getLastPathArgument());
         assertPresentAndType(node, TreeNode.class);
     }
@@ -186,7 +190,7 @@ public class TreeNodeUtilsTest {
         InMemoryDataTreeSnapshot inMemoryDataTreeSnapshot = new InMemoryDataTreeSnapshot(schemaContext,
                 TreeNodeFactory.createTreeNodeRecursively(createDocumentOne(), Version.initial()), rootOper);
         TreeNode rootNode = inMemoryDataTreeSnapshot.getRootNode();
-        Optional<TreeNode> node = TreeNodeUtils.getChild(Optional.fromNullable(rootNode),
+        Optional<TreeNode> node = StoreTreeNodes.getChild(Optional.fromNullable(rootNode),
                 TestModel.OUTER_LIST_PATH.getLastPathArgument());
         assertFalse(node.isPresent());
     }
index 3484b79fc342ad072c911e170fd1aed653c7a15e..9a26c172f3ec4bcbe42d22bb0bd37ceff3d1e122 100644 (file)
@@ -139,10 +139,10 @@ import_stmt : IMPORT_KEYWORD string LEFT_BRACE  prefix_stmt  (revision_date_stmt
 yang_version_stmt : YANG_VERSION_KEYWORD string stmtend;
 data_def_stmt : container_stmt | leaf_stmt | leaf_list_stmt | list_stmt | choice_stmt | anyxml_stmt | uses_stmt;
 body_stmts : (( identifier_stmt| extension_stmt | feature_stmt | identity_stmt | typedef_stmt | grouping_stmt | data_def_stmt | augment_stmt | rpc_stmt | notification_stmt | deviation_stmt) )*;
-revision_stmts :  (revision_stmt )* (stmtsep)*;
+revision_stmts :  (revision_stmt stmtsep)*;
 linkage_stmts : (import_stmt stmtsep* | include_stmt stmtsep*)*;
 meta_stmts : (organization_stmt stmtsep* | contact_stmt stmtsep* | description_stmt stmtsep* | reference_stmt stmtsep*)*;
 submodule_header_stmts : (yang_version_stmt stmtsep* | belongs_to_stmt stmtsep*)+ ;
 module_header_stmts :  (yang_version_stmt stmtsep* | namespace_stmt stmtsep* | prefix_stmt stmtsep*)+ ;
-submodule_stmt : SUBMODULE_KEYWORD string LEFT_BRACE  submodule_header_stmts linkage_stmts meta_stmts revision_stmts body_stmts RIGHT_BRACE;
+submodule_stmt : SUBMODULE_KEYWORD string LEFT_BRACE stmtsep* submodule_header_stmts linkage_stmts meta_stmts revision_stmts body_stmts RIGHT_BRACE;
 module_stmt : MODULE_KEYWORD string LEFT_BRACE stmtsep* module_header_stmts linkage_stmts meta_stmts revision_stmts body_stmts RIGHT_BRACE;
\ No newline at end of file
index adab3c93a3c12a1364d5bf4fee313c3fee99b309..b3f408ef4e6771bb5e171405afdb0971c8f199a5 100644 (file)
@@ -12,13 +12,16 @@ 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 static org.junit.Assert.fail;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigInteger;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
@@ -31,6 +34,7 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -60,6 +64,7 @@ import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
 import org.opendaylight.yangtools.yang.model.util.Decimal64;
 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
 import org.opendaylight.yangtools.yang.model.util.Int16;
@@ -68,6 +73,7 @@ import org.opendaylight.yangtools.yang.model.util.StringType;
 import org.opendaylight.yangtools.yang.model.util.Uint32;
 import org.opendaylight.yangtools.yang.model.util.UnionType;
 import org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils;
+import org.opendaylight.yangtools.yang.parser.util.YangParseException;
 
 public class YangParserTest {
     public static final String FS = File.separator;
@@ -923,4 +929,36 @@ public class YangParserTest {
         assertEquals(2, foo.getAugmentations().size());
     }
 
+    @Test
+    public void unknownStatementInSubmoduleHeaderTest() throws IOException, URISyntaxException {
+
+        File yang = new File(getClass().getResource("/yang-grammar-test/submodule-header-extension.yang").toURI());
+
+        try {
+            YangParserImpl.getInstance().parseFile(yang, yang.getParentFile());
+        } catch (YangSyntaxErrorException | YangParseException e) {
+            e.printStackTrace();
+            fail("YangSyntaxErrorException or YangParseException should not be thrown");
+        }
+
+    }
+
+    @Test
+    public void unknownStatementBetweenRevisionsTest() throws IOException, URISyntaxException {
+
+        File yangModul = new File(getClass().getResource("/yang-grammar-test/revisions-extension.yang").toURI());
+        File yangSubmodul = new File(getClass().getResource("/yang-grammar-test/submodule-header-extension.yang")
+                .toURI());
+
+        List<File> yangs = new ArrayList<File>();
+        yangs.add(yangModul);
+        yangs.add(yangSubmodul);
+
+        try {
+            YangParserImpl.getInstance().parseFiles(yangs);
+        } catch (YangParseException e) {
+            e.printStackTrace();
+            fail("YangParseException should not be thrown");
+        }
+    }
 }
diff --git a/yang/yang-parser-impl/src/test/resources/yang-grammar-test/revisions-extension.yang b/yang/yang-parser-impl/src/test/resources/yang-grammar-test/revisions-extension.yang
new file mode 100644 (file)
index 0000000..3527eff
--- /dev/null
@@ -0,0 +1,24 @@
+module revisions-extension {
+    namespace "my-namespace";
+    prefix pre;
+
+    include submodule-header-extension {
+        revision-date 2007-06-09;
+    }
+
+    revision "2007-06-09" {
+        description "Initial revision.";
+    }
+
+    pre:my-extension 1;
+
+    revision "2008-06-09" {
+        description "Revision 2.";
+    }
+
+    extension my-extension {
+        description "my description ...";
+        argument "number";
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/yang-grammar-test/submodule-header-extension.yang b/yang/yang-parser-impl/src/test/resources/yang-grammar-test/submodule-header-extension.yang
new file mode 100644 (file)
index 0000000..cfda3cb
--- /dev/null
@@ -0,0 +1,18 @@
+submodule submodule-header-extension {
+
+    pre:my-extension2 2;
+
+    belongs-to revisions-extension {
+        prefix pre;
+    }
+
+    revision "2007-06-09" {
+        description "Initial revision.";
+    }
+
+    extension my-extension2 {
+        description "my description ...";
+        argument "number";
+    }
+
+}