Bug 6134: Introducing of DataTreeConfiguration concept 38/41138/4
authorPeter Kajsa <pkajsa@cisco.com>
Thu, 30 Jun 2016 11:55:10 +0000 (13:55 +0200)
committerRobert Varga <nite@hq.sk>
Mon, 11 Jul 2016 11:03:51 +0000 (11:03 +0000)
Introducing of DataTreeConfiguration concept which allows to set up appropriate
configuration of data tree (e.g. enable/disable some validations etc.)

This can be useful when some type of strict validation is not required or useful for some
reasons.

Change-Id: I913dec079e8e2617ef4d0f4954f2b1c332fa7e3b
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
25 files changed:
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/DataTreeConfiguration.java [new file with mode: 0644]
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/DataTreeFactory.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractDataNodeContainerModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AbstractNodeContainerModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/AugmentationModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/CaseEnforcer.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ChoiceModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ContainerModificationStrategy.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/InMemoryDataTreeFactory.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/LeafModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ListEntryModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MandatoryLeafEnforcer.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/OrderedLeafSetModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/OrderedMapModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/PresenceContainerModificationStrategy.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/StructuralContainerModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnkeyedListItemModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnkeyedListModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnorderedLeafSetModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/UnorderedMapModificationStrategy.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MandatoryLeafTest.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModificationMetadataTreeTest.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/StoreTreeNodesTest.java

diff --git a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/DataTreeConfiguration.java b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/tree/DataTreeConfiguration.java
new file mode 100644 (file)
index 0000000..b54c86f
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.api.schema.tree;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.concepts.Immutable;
+
+/**
+ * DataTree configuration class.
+ *
+ * TreeConfig supports currently the following options:
+ * <ul>
+ * <li>treeType</li>
+ * <li>enable/disable unique indexes and unique constraint validation</li>
+ * <li>enable/disable mandatory nodes validation</li>
+ * </ul>
+ *
+ * TreeConfig can be easily extended in order to support further data tree
+ * configuration options, like following:
+ * <ul>
+ * <li>enable/disable case exclusion validation</li>
+ * <li>enable/disable other indexes</li>
+ * <li>other schema aware validation options</li>
+ * </ul>
+ *
+ * This can be useful when strict validation is not required or useful for some
+ * reasons.
+ *
+ */
+@Beta
+public class DataTreeConfiguration implements Immutable {
+    public static final DataTreeConfiguration DEFAULT_CONFIGURATION = new DataTreeConfiguration(TreeType.CONFIGURATION,
+            false, true);
+    public static final DataTreeConfiguration DEFAULT_OPERATIONAL = new DataTreeConfiguration(TreeType.OPERATIONAL,
+            false, true);
+
+    private final TreeType treeType;
+    private final boolean uniqueIndexes;
+    private final boolean mandatoryNodesValidation;
+
+    private DataTreeConfiguration(final TreeType treeType, final boolean uniqueIndexes,
+            final boolean mandatoryNodesValidation) {
+        this.treeType = Preconditions.checkNotNull(treeType);
+        this.uniqueIndexes = uniqueIndexes;
+        this.mandatoryNodesValidation = mandatoryNodesValidation;
+    }
+
+    public TreeType getTreeType() {
+        return treeType;
+    }
+
+    public boolean isUniqueIndexEnabled() {
+        return uniqueIndexes;
+    }
+
+    public boolean isMandatoryNodesValidationEnabled() {
+        return mandatoryNodesValidation;
+    }
+
+    public static DataTreeConfiguration getDefault(final TreeType treeType) {
+        Preconditions.checkNotNull(treeType);
+        switch (treeType) {
+        case CONFIGURATION:
+            return DEFAULT_CONFIGURATION;
+        case OPERATIONAL:
+            return DEFAULT_OPERATIONAL;
+        default:
+            return new DataTreeConfiguration(treeType, false, true);
+        }
+    }
+
+    public static class Builder {
+        private final TreeType treeType;
+        private boolean uniqueIndexes;
+        private boolean mandatoryNodesValidation;
+
+        public Builder(final TreeType treeType) {
+            this.treeType = Preconditions.checkNotNull(treeType);
+        }
+
+        public Builder setUniqueIndexes(final boolean uniqueIndexes) {
+            this.uniqueIndexes = uniqueIndexes;
+            return this;
+        }
+
+        public Builder setMandatoryNodesValidation(final boolean mandatoryNodesValidation) {
+            this.mandatoryNodesValidation = mandatoryNodesValidation;
+            return this;
+        }
+
+        public DataTreeConfiguration build() {
+            return new DataTreeConfiguration(treeType, uniqueIndexes, mandatoryNodesValidation);
+        }
+    }
+}
\ No newline at end of file
index b555e320cb00dbb363dc6ebb151981b2d3168a88..5db699e20fbfbdde7260d0147226e5068729018b 100644 (file)
@@ -32,6 +32,15 @@ public interface DataTreeFactory {
      */
     DataTree create(TreeType type);
 
+    /**
+     * Create a new data tree.
+     * @param treeConfig
+     *          Tree config.
+     *
+     * @return A data tree instance.
+     */
+    DataTree create(DataTreeConfiguration treeConfig);
+
     /**
      * Create a new data tree rooted at a particular node.
      * @param treeType
index 84a7b23c27da6da9d64eb527974dfdf9f301014f..53d6d2fae1511e19bb634eacce5dc90c4afed756 100644 (file)
@@ -18,7 +18,7 @@ import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 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.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -39,21 +39,21 @@ abstract class AbstractDataNodeContainerModificationStrategy<T extends DataNodeC
                 @Override
                 public ModificationApplyOperation load(@Nonnull final PathArgument key) {
                     if (key instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
-                        return SchemaAwareApplyOperation.from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) key, treeType);
+                        return SchemaAwareApplyOperation.from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) key, treeConfig);
                     }
 
                     final DataSchemaNode child = schema.getDataChildByName(key.getNodeType());
                     Preconditions.checkArgument(child != null, "Schema %s does not have a node for child %s", schema, key.getNodeType());
-                    return SchemaAwareApplyOperation.from(child, treeType);
+                    return SchemaAwareApplyOperation.from(child, treeConfig);
                 }
             });
     private final T schema;
-    private final TreeType treeType;
+    private final DataTreeConfiguration treeConfig;
 
-    protected AbstractDataNodeContainerModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass, final TreeType treeType) {
-        super(nodeClass, treeType);
+    protected AbstractDataNodeContainerModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass, final DataTreeConfiguration treeConfig) {
+        super(nodeClass, treeConfig);
         this.schema = Preconditions.checkNotNull(schema,"schema");
-        this.treeType = Preconditions.checkNotNull(treeType,"treeType");
+        this.treeConfig = Preconditions.checkNotNull(treeConfig,"treeConfig");
     }
 
     protected final T getSchema() {
index 4a1e598e42bb0a3fefc71387017c09f5ccfabd03..f908483b409a22cb54f0a0476c4b90873322316b 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
 import static com.google.common.base.Preconditions.checkArgument;
+
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Verify;
@@ -20,6 +21,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificat
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModifiedNodeDoesNotExistException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.MutableTreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
@@ -33,9 +35,9 @@ abstract class AbstractNodeContainerModificationStrategy extends SchemaAwareAppl
     private final boolean verifyChildrenStructure;
 
     protected AbstractNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass,
-            final TreeType treeType) {
+            final DataTreeConfiguration treeConfig) {
         this.nodeClass = Preconditions.checkNotNull(nodeClass , "nodeClass");
-        this.verifyChildrenStructure = (treeType == TreeType.CONFIGURATION);
+        this.verifyChildrenStructure = (treeConfig.getTreeType() == TreeType.CONFIGURATION);
     }
 
     @SuppressWarnings("rawtypes")
@@ -61,7 +63,7 @@ abstract class AbstractNodeContainerModificationStrategy extends SchemaAwareAppl
     }
 
     @Override
-    protected void recursivelyVerifyStructure(NormalizedNode<?, ?> value) {
+    protected void recursivelyVerifyStructure(final NormalizedNode<?, ?> value) {
         final NormalizedNodeContainer container = (NormalizedNodeContainer) value;
         for (final Object child : container.getValue()) {
             checkArgument(child instanceof NormalizedNode);
@@ -161,7 +163,7 @@ abstract class AbstractNodeContainerModificationStrategy extends SchemaAwareAppl
         Verify.verify(value instanceof NormalizedNodeContainer, "Attempted to merge non-container %s", value);
         @SuppressWarnings({"unchecked", "rawtypes"})
         final Collection<NormalizedNode<?, ?>> children = ((NormalizedNodeContainer) value).getValue();
-        for (NormalizedNode<?, ?> c : children) {
+        for (final NormalizedNode<?, ?> c : children) {
             final PathArgument id = c.getIdentifier();
             modification.modifyChild(id, resolveChildOperation(id), version);
         }
@@ -170,7 +172,7 @@ abstract class AbstractNodeContainerModificationStrategy extends SchemaAwareAppl
 
     private void mergeChildrenIntoModification(final ModifiedNode modification,
             final Collection<NormalizedNode<?, ?>> children, final Version version) {
-        for (NormalizedNode<?, ?> c : children) {
+        for (final NormalizedNode<?, ?> c : children) {
             final ModificationApplyOperation childOp = resolveChildOperation(c.getIdentifier());
             final ModifiedNode childNode = modification.modifyChild(c.getIdentifier(), childOp, version);
             childOp.mergeIntoModifiedNode(childNode, c, version);
index 211473f92b92296cbf82058f9bcb5db31fb5980f..de3e4eaad3227f5dabef01098efa0368866f8ed4 100644 (file)
@@ -13,7 +13,7 @@ import java.util.HashSet;
 import java.util.Set;
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
@@ -22,8 +22,8 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
 
 final class AugmentationModificationStrategy extends AbstractDataNodeContainerModificationStrategy<AugmentationSchema> {
-    AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved, final TreeType treeType) {
-        super(createAugmentProxy(schema,resolved), AugmentationNode.class, treeType);
+    AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved, final DataTreeConfiguration treeConfig) {
+        super(createAugmentProxy(schema,resolved), AugmentationNode.class, treeConfig);
     }
 
     @Override
@@ -34,7 +34,7 @@ final class AugmentationModificationStrategy extends AbstractDataNodeContainerMo
     }
 
     @Override
-    protected NormalizedNode<?, ?> createEmptyValue(NormalizedNode<?, ?> original) {
+    protected NormalizedNode<?, ?> createEmptyValue(final NormalizedNode<?, ?> original) {
         checkArgument(original instanceof AugmentationNode);
         return ImmutableAugmentationNodeBuilder.create()
                 .withNodeIdentifier(((AugmentationNode) original).getIdentifier()).build();
index e0e3b6443660b5fad65ec0aa566fd28cdb9110ea..9d168e12b70ddfc64cc7175bf7fc7cf622fdeacf 100644 (file)
@@ -16,6 +16,7 @@ import java.util.Set;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -29,10 +30,11 @@ final class CaseEnforcer implements Immutable {
         this.enforcer = Preconditions.checkNotNull(enforcer);
     }
 
-    static CaseEnforcer forTree(final ChoiceCaseNode schema, final TreeType type) {
+    static CaseEnforcer forTree(final ChoiceCaseNode schema, final DataTreeConfiguration treeConfig) {
+        final TreeType type = treeConfig.getTreeType();
         final Builder<NodeIdentifier, DataSchemaNode> builder = ImmutableMap.builder();
         if (SchemaAwareApplyOperation.belongsToTree(type, schema)) {
-            for (DataSchemaNode child : schema.getChildNodes()) {
+            for (final DataSchemaNode child : schema.getChildNodes()) {
                 if (SchemaAwareApplyOperation.belongsToTree(type, child)) {
                     builder.put(NodeIdentifier.create(child.getQName()), child);
                 }
@@ -40,7 +42,8 @@ final class CaseEnforcer implements Immutable {
         }
 
         final Map<NodeIdentifier, DataSchemaNode> children = builder.build();
-        return children.isEmpty() ? null : new CaseEnforcer(children, MandatoryLeafEnforcer.forContainer(schema, type));
+        return children.isEmpty() ? null : new CaseEnforcer(children, MandatoryLeafEnforcer.forContainer(schema,
+                treeConfig));
     }
 
     Set<Entry<NodeIdentifier, DataSchemaNode>> getChildEntries() {
index aa65d3188c1001c5fdcea3ff15f2a6533cb5e4f0..c991f71a767683d8b3a2ae4c39594294b3c2697f 100644 (file)
@@ -27,7 +27,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 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.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 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.builder.api.DataContainerNodeBuilder;
@@ -42,16 +42,16 @@ final class ChoiceModificationStrategy extends AbstractNodeContainerModification
     private final Map<CaseEnforcer, Collection<CaseEnforcer>> exclusions;
     private final Map<PathArgument, CaseEnforcer> caseEnforcers;
 
-    ChoiceModificationStrategy(final ChoiceSchemaNode schemaNode, final TreeType treeType) {
-        super(ChoiceNode.class, treeType);
+    ChoiceModificationStrategy(final ChoiceSchemaNode schemaNode, final DataTreeConfiguration treeConfig) {
+        super(ChoiceNode.class, treeConfig);
 
         final Builder<PathArgument, ModificationApplyOperation> childBuilder = ImmutableMap.builder();
         final Builder<PathArgument, CaseEnforcer> enforcerBuilder = ImmutableMap.builder();
         for (final ChoiceCaseNode caze : schemaNode.getCases()) {
-            final CaseEnforcer enforcer = CaseEnforcer.forTree(caze, treeType);
+            final CaseEnforcer enforcer = CaseEnforcer.forTree(caze, treeConfig);
             if (enforcer != null) {
                 for (final Entry<NodeIdentifier, DataSchemaNode> e : enforcer.getChildEntries()) {
-                    childBuilder.put(e.getKey(), SchemaAwareApplyOperation.from(e.getValue(), treeType));
+                    childBuilder.put(e.getKey(), SchemaAwareApplyOperation.from(e.getValue(), treeConfig));
                     enforcerBuilder.put(e.getKey(), enforcer);
                 }
             }
@@ -60,7 +60,7 @@ final class ChoiceModificationStrategy extends AbstractNodeContainerModification
         caseEnforcers = enforcerBuilder.build();
 
         final Map<CaseEnforcer, Collection<CaseEnforcer>> exclusionsBuilder = new HashMap<>();
-        for (CaseEnforcer e : caseEnforcers.values()) {
+        for (final CaseEnforcer e : caseEnforcers.values()) {
             exclusionsBuilder.put(e, ImmutableList.copyOf(
                 Collections2.filter(caseEnforcers.values(), Predicates.not(Predicates.equalTo(e)))));
         }
@@ -100,8 +100,8 @@ final class ChoiceModificationStrategy extends AbstractNodeContainerModification
             Verify.verifyNotNull(enforcer, "Case enforcer cannot be null. Most probably, child node %s of choice node %s does not belong in current tree type.", firstChild.getIdentifier(), normalizedNode.getIdentifier());
 
             // Make sure no leaves from other cases are present
-            for (CaseEnforcer other : exclusions.get(enforcer)) {
-                for (NodeIdentifier id : other.getChildIdentifiers()) {
+            for (final CaseEnforcer other : exclusions.get(enforcer)) {
+                for (final NodeIdentifier id : other.getChildIdentifiers()) {
                     final Optional<NormalizedNode<?, ?>> maybeChild = NormalizedNodes.getDirectChild(normalizedNode, id);
                     Preconditions.checkArgument(!maybeChild.isPresent(),
                         "Child %s (from case %s) implies non-presence of child %s (from case %s), which is %s",
@@ -137,7 +137,7 @@ final class ChoiceModificationStrategy extends AbstractNodeContainerModification
     }
 
     @Override
-    protected NormalizedNode<?, ?> createEmptyValue(NormalizedNode<?, ?> original) {
+    protected NormalizedNode<?, ?> createEmptyValue(final NormalizedNode<?, ?> original) {
         checkArgument(original instanceof ChoiceNode);
         return ImmutableChoiceNodeBuilder.create().withNodeIdentifier(((ChoiceNode) original).getIdentifier()).build();
     }
index 8e28fdd86810222fd84dd49893c7dc163d04127b..5b988ed169423231630e4550033c4d8f15c07f9b 100644 (file)
@@ -12,7 +12,7 @@ import static com.google.common.base.Preconditions.checkArgument;
 import com.google.common.base.Preconditions;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
@@ -22,8 +22,8 @@ import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
  * and by {@link StructuralContainerModificationStrategy} as a delegate.
  */
 class ContainerModificationStrategy extends AbstractDataNodeContainerModificationStrategy<ContainerSchemaNode> {
-    ContainerModificationStrategy(final ContainerSchemaNode schemaNode, final TreeType treeType) {
-        super(schemaNode, ContainerNode.class, treeType);
+    ContainerModificationStrategy(final ContainerSchemaNode schemaNode, final DataTreeConfiguration treeConfig) {
+        super(schemaNode, ContainerNode.class, treeConfig);
     }
 
     @Override
@@ -34,7 +34,7 @@ class ContainerModificationStrategy extends AbstractDataNodeContainerModificatio
     }
 
     @Override
-    protected NormalizedNode<?, ?> createEmptyValue(NormalizedNode<?, ?> original) {
+    protected NormalizedNode<?, ?> createEmptyValue(final NormalizedNode<?, ?> original) {
         Preconditions.checkArgument(original instanceof ContainerNode);
         return ImmutableContainerNodeBuilder.create().withNodeIdentifier(((ContainerNode) original).getIdentifier())
                 .build();
index f7bce41d6b60dbb1443dd978de5778008ba055d4..df2dac7abb0cbaf5eb7ec622511d732c73c58027 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.TipProducingDataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
@@ -35,7 +36,7 @@ final class InMemoryDataTree extends AbstractDataTreeTip implements TipProducing
     private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTree.class);
 
     private final YangInstanceIdentifier rootPath;
-    private final TreeType treeType;
+    private final DataTreeConfiguration treeConfig;
 
     /**
      * Current data store state generation.
@@ -43,7 +44,11 @@ final class InMemoryDataTree extends AbstractDataTreeTip implements TipProducing
     private volatile DataTreeState state;
 
     public InMemoryDataTree(final TreeNode rootNode, final TreeType treeType, final YangInstanceIdentifier rootPath, final SchemaContext schemaContext) {
-        this.treeType = Preconditions.checkNotNull(treeType, "treeType");
+        this(rootNode, DataTreeConfiguration.getDefault(treeType), rootPath, schemaContext);
+    }
+
+    public InMemoryDataTree(final TreeNode rootNode, final DataTreeConfiguration treeConfig, final YangInstanceIdentifier rootPath, final SchemaContext schemaContext) {
+        this.treeConfig = Preconditions.checkNotNull(treeConfig, "treeConfig");
         this.rootPath = Preconditions.checkNotNull(rootPath, "rootPath");
         state = DataTreeState.createInitial(rootNode);
         if (schemaContext != null) {
@@ -77,9 +82,9 @@ final class InMemoryDataTree extends AbstractDataTreeTip implements TipProducing
         final ModificationApplyOperation rootNode;
         if (rootSchemaNode instanceof ContainerSchemaNode) {
             // FIXME: real root needs to enfore presence, but that require pre-population
-            rootNode = new ContainerModificationStrategy((ContainerSchemaNode) rootSchemaNode, treeType);
+            rootNode = new ContainerModificationStrategy((ContainerSchemaNode) rootSchemaNode, treeConfig);
         } else {
-            rootNode = SchemaAwareApplyOperation.from(rootSchemaNode, treeType);
+            rootNode = SchemaAwareApplyOperation.from(rootSchemaNode, treeConfig);
         }
 
         DataTreeState currentState, newState;
index a60497fd448117d9e14a4f9652062b8fd85a5f36..46c3a112d12b472cbdb37105f92785ace4934031 100644 (file)
@@ -15,6 +15,7 @@ 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.DataTreeFactory;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.TipProducingDataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
@@ -45,6 +46,12 @@ public final class InMemoryDataTreeFactory implements DataTreeFactory {
             treeType, YangInstanceIdentifier.EMPTY, null);
     }
 
+    @Override
+    public TipProducingDataTree create(final DataTreeConfiguration treeConfig) {
+        return new InMemoryDataTree(TreeNodeFactory.createTreeNode(rootContainer, Version.initial()),
+                treeConfig, YangInstanceIdentifier.EMPTY, null);
+    }
+
     @Override
     public TipProducingDataTree create(final TreeType treeType, final YangInstanceIdentifier rootPath) {
         if (rootPath.isEmpty()) {
index 250991154dd22543ea8726b161c3e930cb80dcf0..e5f07c65b0f29a5c5781e6b2055c4d6e99fe1118 100644 (file)
@@ -8,12 +8,11 @@
 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 
 final class LeafModificationStrategy extends AbstractValueNodeModificationStrategy<LeafSchemaNode> {
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    LeafModificationStrategy(final LeafSchemaNode schema, final TreeType treeType) {
+    LeafModificationStrategy(final LeafSchemaNode schema) {
         super(schema, (Class) LeafNode.class);
     }
 }
\ No newline at end of file
index f2ba17be3717a081f975c04d915d064d8a43e928..599ef01ae68e26a031e2649814202789b03c37f7 100644 (file)
@@ -8,10 +8,11 @@
 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
 import static com.google.common.base.Preconditions.checkArgument;
+
 import com.google.common.base.Optional;
 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.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 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.builder.api.DataContainerNodeBuilder;
@@ -21,9 +22,9 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 final class ListEntryModificationStrategy extends AbstractDataNodeContainerModificationStrategy<ListSchemaNode> {
     private final MandatoryLeafEnforcer enforcer;
 
-    ListEntryModificationStrategy(final ListSchemaNode schema, final TreeType treeType) {
-        super(schema, MapEntryNode.class, treeType);
-        enforcer = MandatoryLeafEnforcer.forContainer(schema, treeType);
+    ListEntryModificationStrategy(final ListSchemaNode schema, final DataTreeConfiguration treeConfig) {
+        super(schema, MapEntryNode.class, treeConfig);
+        enforcer = MandatoryLeafEnforcer.forContainer(schema, treeConfig);
     }
 
     @Override
@@ -56,7 +57,7 @@ final class ListEntryModificationStrategy extends AbstractDataNodeContainerModif
     }
 
     @Override
-    protected NormalizedNode<?, ?> createEmptyValue(NormalizedNode<?, ?> original) {
+    protected NormalizedNode<?, ?> createEmptyValue(final NormalizedNode<?, ?> original) {
         checkArgument(original instanceof MapEntryNode);
         return ImmutableMapEntryNodeBuilder.create().withNodeIdentifier(((MapEntryNode) original).getIdentifier())
                 .build();
index 5bce99c4cb2f892aa393d50c6a6626aab8b1e59d..c0b33e473cb3285c845e57ddc45f7fcfdb7178b6 100644 (file)
@@ -17,6 +17,7 @@ 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.api.schema.NormalizedNodes;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
@@ -54,7 +55,7 @@ abstract class MandatoryLeafEnforcer implements Immutable {
 
         @Override
         protected void enforceOnTreeNode(final NormalizedNode<?, ?> data) {
-            for (YangInstanceIdentifier id : mandatoryNodes) {
+            for (final YangInstanceIdentifier id : mandatoryNodes) {
                 final Optional<NormalizedNode<?, ?>> descandant = NormalizedNodes.findNode(data, id);
                 Preconditions.checkArgument(descandant.isPresent(), "Node %s is missing mandatory descendant %s",
                         data.getIdentifier(), id);
@@ -71,7 +72,7 @@ abstract class MandatoryLeafEnforcer implements Immutable {
 
     private static void findMandatoryNodes(final Builder<YangInstanceIdentifier> builder,
             final YangInstanceIdentifier id, final DataNodeContainer schema, final TreeType type) {
-        for (DataSchemaNode child : schema.getChildNodes()) {
+        for (final DataSchemaNode child : schema.getChildNodes()) {
             if (SchemaAwareApplyOperation.belongsToTree(type, child)) {
                 if (child instanceof ContainerSchemaNode) {
                     final ContainerSchemaNode container = (ContainerSchemaNode) child;
@@ -91,17 +92,21 @@ abstract class MandatoryLeafEnforcer implements Immutable {
         }
     }
 
-    static MandatoryLeafEnforcer forContainer(final DataNodeContainer schema, final TreeType type) {
-        switch (type) {
+    static MandatoryLeafEnforcer forContainer(final DataNodeContainer schema, final DataTreeConfiguration treeConfig) {
+        if (!treeConfig.isMandatoryNodesValidationEnabled()) {
+            return NOOP_ENFORCER;
+        }
+        final TreeType treeType = treeConfig.getTreeType();
+        switch (treeType) {
         case CONFIGURATION:
             final Builder<YangInstanceIdentifier> builder = ImmutableList.builder();
-            findMandatoryNodes(builder, YangInstanceIdentifier.EMPTY, schema, type);
+            findMandatoryNodes(builder, YangInstanceIdentifier.EMPTY, schema, treeType);
             final Collection<YangInstanceIdentifier> mandatoryNodes = builder.build();
             return mandatoryNodes.isEmpty() ? NOOP_ENFORCER : new Strict(mandatoryNodes);
         case OPERATIONAL:
             return NOOP_ENFORCER;
         default:
-            throw new UnsupportedOperationException(String.format("Not supported tree type %s", type));
+            throw new UnsupportedOperationException(String.format("Not supported tree type %s", treeType));
         }
     }
 }
index f1e545b0cf1d5521ac2172dce339f2b20876df0f..f58cf4b672de6cfdda102be6abfa409e6e4949f7 100644 (file)
@@ -14,7 +14,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
@@ -23,8 +23,8 @@ final class OrderedLeafSetModificationStrategy extends AbstractNodeContainerModi
     private final Optional<ModificationApplyOperation> entryStrategy;
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema, final TreeType treeType) {
-        super((Class) LeafSetNode.class, treeType);
+    OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema, final DataTreeConfiguration treeConfig) {
+        super((Class) LeafSetNode.class, treeConfig);
         entryStrategy = Optional.of(new LeafSetEntryModificationStrategy(schema));
     }
 
@@ -41,7 +41,7 @@ final class OrderedLeafSetModificationStrategy extends AbstractNodeContainerModi
     }
 
     @Override
-    protected NormalizedNode<?, ?> createEmptyValue(NormalizedNode<?, ?> original) {
+    protected NormalizedNode<?, ?> createEmptyValue(final NormalizedNode<?, ?> original) {
         checkArgument(original instanceof OrderedLeafSetNode<?>);
         return ImmutableOrderedLeafSetNodeBuilder.create()
                 .withNodeIdentifier(((OrderedLeafSetNode<?>) original).getIdentifier()).build();
index 4143fb83ec98d98faaa88ba6ea8b13ab681ad3e6..d3e262e619a91d043717d2660abce191ef5b47a5 100644 (file)
@@ -14,7 +14,7 @@ import com.google.common.base.Optional;
 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.OrderedMapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -22,9 +22,9 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 final class OrderedMapModificationStrategy extends AbstractNodeContainerModificationStrategy {
     private final Optional<ModificationApplyOperation> entryStrategy;
 
-    OrderedMapModificationStrategy(final ListSchemaNode schema, final TreeType treeType) {
-        super(OrderedMapNode.class, treeType);
-        entryStrategy = Optional.of(new ListEntryModificationStrategy(schema, treeType));
+    OrderedMapModificationStrategy(final ListSchemaNode schema, final DataTreeConfiguration treeConfig) {
+        super(OrderedMapNode.class, treeConfig);
+        entryStrategy = Optional.of(new ListEntryModificationStrategy(schema, treeConfig));
     }
 
     @Override
@@ -40,7 +40,7 @@ final class OrderedMapModificationStrategy extends AbstractNodeContainerModifica
     }
 
     @Override
-    protected NormalizedNode<?, ?> createEmptyValue(NormalizedNode<?, ?> original) {
+    protected NormalizedNode<?, ?> createEmptyValue(final NormalizedNode<?, ?> original) {
         checkArgument(original instanceof OrderedMapNode);
         return ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier(((OrderedMapNode) original).getIdentifier())
                 .build();
index 25246eb521a77efe15921060ead62bbe6e62f091..e653f5a8483e2e33f3251e58a159b1e85db6aab1 100644 (file)
@@ -10,7 +10,7 @@ package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
 import com.google.common.base.Optional;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 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.model.api.ContainerSchemaNode;
@@ -22,9 +22,9 @@ import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 final class PresenceContainerModificationStrategy extends ContainerModificationStrategy {
     private final MandatoryLeafEnforcer enforcer;
 
-    PresenceContainerModificationStrategy(final ContainerSchemaNode schemaNode, final TreeType treeType) {
-        super(schemaNode, treeType);
-        enforcer = MandatoryLeafEnforcer.forContainer(schemaNode, treeType);
+    PresenceContainerModificationStrategy(final ContainerSchemaNode schemaNode, final DataTreeConfiguration treeConfig) {
+        super(schemaNode, treeConfig);
+        enforcer = MandatoryLeafEnforcer.forContainer(schemaNode, treeConfig);
     }
 
     @Override
index 29fa6070fa3b33acc47efb87ff6bd17efa42f08e..d94c572e513123065a52e1c4d4b2436981179243 100644 (file)
@@ -17,6 +17,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgum
 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.ModificationType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
@@ -35,35 +36,35 @@ import org.slf4j.LoggerFactory;
 abstract class SchemaAwareApplyOperation extends ModificationApplyOperation {
     private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareApplyOperation.class);
 
-    public static ModificationApplyOperation from(final DataSchemaNode schemaNode, final TreeType treeType) {
-        if (treeType == TreeType.CONFIGURATION) {
+    public static ModificationApplyOperation from(final DataSchemaNode schemaNode, final DataTreeConfiguration treeConfig) {
+        if (treeConfig.getTreeType() == TreeType.CONFIGURATION) {
             Preconditions.checkArgument(schemaNode.isConfiguration(), "Supplied %s does not belongs to configuration tree.", schemaNode.getPath());
         }
         if (schemaNode instanceof ContainerSchemaNode) {
             final ContainerSchemaNode containerSchema = (ContainerSchemaNode) schemaNode;
             if (containerSchema.isPresenceContainer()) {
-                return new PresenceContainerModificationStrategy(containerSchema, treeType);
+                return new PresenceContainerModificationStrategy(containerSchema, treeConfig);
             } else {
-                return new StructuralContainerModificationStrategy(containerSchema, treeType);
+                return new StructuralContainerModificationStrategy(containerSchema, treeConfig);
             }
         } else if (schemaNode instanceof ListSchemaNode) {
-            return fromListSchemaNode((ListSchemaNode) schemaNode, treeType);
+            return fromListSchemaNode((ListSchemaNode) schemaNode, treeConfig);
         } else if (schemaNode instanceof ChoiceSchemaNode) {
-            return new ChoiceModificationStrategy((ChoiceSchemaNode) schemaNode, treeType);
+            return new ChoiceModificationStrategy((ChoiceSchemaNode) schemaNode, treeConfig);
         } else if (schemaNode instanceof LeafListSchemaNode) {
-            return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode, treeType);
+            return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode, treeConfig);
         } else if (schemaNode instanceof LeafSchemaNode) {
-            return new LeafModificationStrategy((LeafSchemaNode) schemaNode, treeType);
+            return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
         }
         throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
     }
 
     public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
-            final AugmentationTarget augSchemas, final AugmentationIdentifier identifier, final TreeType treeType) {
+            final AugmentationTarget augSchemas, final AugmentationIdentifier identifier, final DataTreeConfiguration treeConfig) {
         for (final AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
             for (final DataSchemaNode child : potential.getChildNodes()) {
                 if (identifier.getPossibleChildNames().contains(child.getQName())) {
-                    return new AugmentationModificationStrategy(potential, resolvedTree, treeType);
+                    return new AugmentationModificationStrategy(potential, resolvedTree, treeConfig);
                 }
             }
         }
@@ -78,25 +79,25 @@ abstract class SchemaAwareApplyOperation extends ModificationApplyOperation {
         }
     }
 
-    private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode, final TreeType treeType) {
+    private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode, final DataTreeConfiguration treeConfig) {
         final List<QName> keyDefinition = schemaNode.getKeyDefinition();
         final SchemaAwareApplyOperation op;
         if (keyDefinition == null || keyDefinition.isEmpty()) {
-            op = new UnkeyedListModificationStrategy(schemaNode, treeType);
+            op = new UnkeyedListModificationStrategy(schemaNode, treeConfig);
         } else if (schemaNode.isUserOrdered()) {
-            op =  new OrderedMapModificationStrategy(schemaNode, treeType);
+            op =  new OrderedMapModificationStrategy(schemaNode, treeConfig);
         } else {
-            op = new UnorderedMapModificationStrategy(schemaNode, treeType);
+            op = new UnorderedMapModificationStrategy(schemaNode, treeConfig);
         }
         return MinMaxElementsValidation.from(op, schemaNode);
     }
 
-    private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode, final TreeType treeType) {
+    private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode, final DataTreeConfiguration treeConfig) {
         final SchemaAwareApplyOperation op;
         if (schemaNode.isUserOrdered()) {
-            op =  new OrderedLeafSetModificationStrategy(schemaNode, treeType);
+            op =  new OrderedLeafSetModificationStrategy(schemaNode, treeConfig);
         } else {
-            op = new UnorderedLeafSetModificationStrategy(schemaNode, treeType);
+            op = new UnorderedLeafSetModificationStrategy(schemaNode, treeConfig);
         }
         return MinMaxElementsValidation.from(op, schemaNode);
     }
index f13c25b7cf0137f162a48ccaa9181a7360679e1a..b5e5c265e4bce25ede41f9cb756e88e3f85aa5c4 100644 (file)
@@ -15,7 +15,7 @@ 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.tree.DataValidationFailedException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 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;
@@ -40,8 +40,8 @@ final class StructuralContainerModificationStrategy extends ModificationApplyOpe
     private static final Version FAKE_VERSION = Version.initial();
     private final ContainerModificationStrategy delegate;
 
-    StructuralContainerModificationStrategy(final ContainerSchemaNode schemaNode, final TreeType treeType) {
-        this.delegate = new ContainerModificationStrategy(schemaNode, treeType);
+    StructuralContainerModificationStrategy(final ContainerSchemaNode schemaNode, final DataTreeConfiguration treeConfig) {
+        this.delegate = new ContainerModificationStrategy(schemaNode, treeConfig);
     }
 
     private Optional<TreeNode> fakeMeta(final Version version) {
@@ -106,7 +106,7 @@ final class StructuralContainerModificationStrategy extends ModificationApplyOpe
     }
 
     @Override
-    void recursivelyVerifyStructure(NormalizedNode<?, ?> value) {
+    void recursivelyVerifyStructure(final NormalizedNode<?, ?> value) {
         delegate.recursivelyVerifyStructure(value);
     }
 
@@ -116,7 +116,7 @@ final class StructuralContainerModificationStrategy extends ModificationApplyOpe
     }
 
     @Override
-    void mergeIntoModifiedNode(ModifiedNode modification, NormalizedNode<?, ?> value, Version version) {
+    void mergeIntoModifiedNode(final ModifiedNode modification, final NormalizedNode<?, ?> value, final Version version) {
         delegate.mergeIntoModifiedNode(modification, value, version);
     }
 
index 1e270900582951b8c8f4cc1dc7b46ce87f73d974..80a14938a28e7d253ac713f4a8bebe8f62adc366 100644 (file)
@@ -11,14 +11,14 @@ import static com.google.common.base.Preconditions.checkArgument;
 
 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.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
 final class UnkeyedListItemModificationStrategy extends AbstractDataNodeContainerModificationStrategy<ListSchemaNode> {
-    UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode, final TreeType treeType) {
-        super(schemaNode, UnkeyedListEntryNode.class, treeType);
+    UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode, final DataTreeConfiguration treeConfig) {
+        super(schemaNode, UnkeyedListEntryNode.class, treeConfig);
     }
 
     @Override
@@ -29,7 +29,7 @@ final class UnkeyedListItemModificationStrategy extends AbstractDataNodeContaine
     }
 
     @Override
-    protected NormalizedNode<?, ?> createEmptyValue(NormalizedNode<?, ?> original) {
+    protected NormalizedNode<?, ?> createEmptyValue(final NormalizedNode<?, ?> original) {
         checkArgument(original instanceof UnkeyedListEntryNode);
         return ImmutableUnkeyedListEntryNodeBuilder.create()
                 .withNodeIdentifier(((UnkeyedListEntryNode) original).getIdentifier()).build();
index fd538cb0f1c50958a361dc4d3cd6bbb623e3103e..6916059defcbcc1a34743474062bfe3f6a2815f5 100644 (file)
@@ -14,7 +14,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgum
 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.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 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;
@@ -27,8 +27,8 @@ final class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
 
     private final Optional<ModificationApplyOperation> entryStrategy;
 
-    UnkeyedListModificationStrategy(final ListSchemaNode schema, final TreeType treeType) {
-        entryStrategy = Optional.of(new UnkeyedListItemModificationStrategy(schema, treeType));
+    UnkeyedListModificationStrategy(final ListSchemaNode schema, final DataTreeConfiguration treeConfig) {
+        entryStrategy = Optional.of(new UnkeyedListItemModificationStrategy(schema, treeConfig));
     }
 
     @Override
@@ -126,7 +126,7 @@ final class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
     }
 
     @Override
-    void recursivelyVerifyStructure(NormalizedNode<?, ?> value) {
+    void recursivelyVerifyStructure(final NormalizedNode<?, ?> value) {
         // NOOP
     }
 
index 709a4a9a0df4ccd3792a27b79667825028ea0d45..734433a58f543fbd5251a3b8211562964e696afa 100644 (file)
@@ -13,7 +13,7 @@ import com.google.common.base.Optional;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
@@ -22,8 +22,8 @@ final class UnorderedLeafSetModificationStrategy extends AbstractNodeContainerMo
     private final Optional<ModificationApplyOperation> entryStrategy;
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema, final TreeType treeType) {
-        super((Class) LeafSetNode.class, treeType);
+    UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema, final DataTreeConfiguration treeConfig) {
+        super((Class) LeafSetNode.class, treeConfig);
         entryStrategy = Optional.of(new LeafSetEntryModificationStrategy(schema));
     }
 
@@ -35,7 +35,7 @@ final class UnorderedLeafSetModificationStrategy extends AbstractNodeContainerMo
     }
 
     @Override
-    protected NormalizedNode<?, ?> createEmptyValue(NormalizedNode<?, ?> original) {
+    protected NormalizedNode<?, ?> createEmptyValue(final NormalizedNode<?, ?> original) {
         checkArgument(original instanceof LeafSetNode<?>);
         return ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(((LeafSetNode<?>) original).getIdentifier())
                 .build();
index 1e66f4a24c46569515cee1aa9836ae66445b1a02..22f0a7954d802c1af4ae2d83ffb6e2c48a504f99 100644 (file)
@@ -14,7 +14,7 @@ import com.google.common.base.Optional;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 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.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -22,9 +22,9 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 final class UnorderedMapModificationStrategy extends AbstractNodeContainerModificationStrategy {
     private final Optional<ModificationApplyOperation> entryStrategy;
 
-    UnorderedMapModificationStrategy(final ListSchemaNode schema, final TreeType treeType) {
-        super(MapNode.class, treeType);
-        entryStrategy = Optional.of(new ListEntryModificationStrategy(schema, treeType));
+    UnorderedMapModificationStrategy(final ListSchemaNode schema, final DataTreeConfiguration treeConfig) {
+        super(MapNode.class, treeConfig);
+        entryStrategy = Optional.of(new ListEntryModificationStrategy(schema, treeConfig));
     }
 
     @SuppressWarnings("rawtypes")
index 6346167d7198812d2320954ee5854d0ec3b43800..b26420eefd29b09eb80def913ebfed7e6ec3668f 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent
 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
@@ -34,16 +35,17 @@ public class MandatoryLeafTest {
         assertNotNull("Schema context must not be null.", schemaContext);
     }
 
-    private InMemoryDataTree initDataTree() {
-        InMemoryDataTree inMemoryDataTree = (InMemoryDataTree) InMemoryDataTreeFactory.getInstance().create(
-                TreeType.CONFIGURATION);
+    private InMemoryDataTree initDataTree(final boolean enableValidation) {
+        final InMemoryDataTree inMemoryDataTree = (InMemoryDataTree) InMemoryDataTreeFactory.getInstance().create(
+                new DataTreeConfiguration.Builder(TreeType.CONFIGURATION).setMandatoryNodesValidation(enableValidation)
+                        .build());
         inMemoryDataTree.setSchemaContext(schemaContext);
         return inMemoryDataTree;
     }
 
     @Test
     public void testCorrectMandatoryLeafWrite() throws DataValidationFailedException {
-        final InMemoryDataTree inMemoryDataTree = initDataTree();
+        final InMemoryDataTree inMemoryDataTree = initDataTree(true);
         final NodeIdentifier choice1Id = new NodeIdentifier(QName.create(TestModel.TEST_QNAME, "choice1"));
 
         final ContainerNode container = Builders
@@ -75,7 +77,7 @@ public class MandatoryLeafTest {
 
     @Test
     public void testCorrectMandatoryLeafChoiceWrite() throws DataValidationFailedException {
-        final InMemoryDataTree inMemoryDataTree = initDataTree();
+        final InMemoryDataTree inMemoryDataTree = initDataTree(true);
         // Container write
         final ContainerNode container = Builders.containerBuilder()
                 .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME)).build();
@@ -112,7 +114,7 @@ public class MandatoryLeafTest {
 
     @Test(expected = IllegalArgumentException.class)
     public void testMandatoryLeafViolation() throws DataValidationFailedException {
-        final InMemoryDataTree inMemoryDataTree = initDataTree();
+        final InMemoryDataTree inMemoryDataTree = initDataTree(true);
         final NodeIdentifier choice1Id = new NodeIdentifier(QName.create(TestModel.TEST_QNAME, "choice1"));
 
         final ContainerNode container = Builders
@@ -137,7 +139,7 @@ public class MandatoryLeafTest {
             inMemoryDataTree.validate(modificationTree);
             final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
             inMemoryDataTree.commit(prepare);
-        } catch (IllegalArgumentException e) {
+        } catch (final IllegalArgumentException e) {
             assertEquals(
                     "Node (urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)choice1 is missing mandatory descendant /(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)case2-cont/case2-leaf1",
                     e.getMessage());
@@ -145,9 +147,37 @@ public class MandatoryLeafTest {
         }
     }
 
+    @Test
+    public void testDisabledValidation() throws DataValidationFailedException {
+        final InMemoryDataTree inMemoryDataTree = initDataTree(false);
+        final NodeIdentifier choice1Id = new NodeIdentifier(QName.create(TestModel.TEST_QNAME, "choice1"));
+
+        final ContainerNode container = Builders
+                .containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME))
+                .withChild(
+                        Builders.choiceBuilder()
+                                .withNodeIdentifier(choice1Id)
+                                .withChild(
+                                        Builders.containerBuilder()
+                                                .withNodeIdentifier(
+                                                        new NodeIdentifier(QName.create(TestModel.TEST_QNAME,
+                                                                "case2-cont")))
+                                                .withChild(
+                                                        leafNode(QName.create(TestModel.TEST_QNAME, "case2-leaf2"),
+                                                                "leaf-value2")).build()).build()).build();
+        final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
+        modificationTree.write(TestModel.TEST_PATH, container);
+        modificationTree.ready();
+
+        inMemoryDataTree.validate(modificationTree);
+        final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
+        inMemoryDataTree.commit(prepare);
+    }
+
     @Test(expected = IllegalArgumentException.class)
     public void testMandatoryLeafViolationChoiceWrite() throws DataValidationFailedException {
-        final InMemoryDataTree inMemoryDataTree = initDataTree();
+        final InMemoryDataTree inMemoryDataTree = initDataTree(true);
         // Container write
         final ContainerNode container = Builders.containerBuilder()
                 .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME)).build();
@@ -179,11 +209,46 @@ public class MandatoryLeafTest {
             inMemoryDataTree.validate(modificationTree2);
             final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
             inMemoryDataTree.commit(prepare2);
-        } catch (IllegalArgumentException e) {
+        } catch (final IllegalArgumentException e) {
             assertEquals(
                     "Node (urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)choice1 is missing mandatory descendant /(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)case2-cont/case2-leaf1",
                     e.getMessage());
             throw e;
         }
     }
+
+    @Test
+    public void testDisabledValidationChoiceWrite() throws DataValidationFailedException {
+        final InMemoryDataTree inMemoryDataTree = initDataTree(false);
+        // Container write
+        final ContainerNode container = Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME)).build();
+
+        final InMemoryDataTreeModification modificationTree1 = inMemoryDataTree.takeSnapshot().newModification();
+        modificationTree1.write(TestModel.TEST_PATH, container);
+        modificationTree1.ready();
+
+        inMemoryDataTree.validate(modificationTree1);
+        final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree1);
+        inMemoryDataTree.commit(prepare1);
+
+        // Choice write
+        final NodeIdentifier choice1Id = new NodeIdentifier(QName.create(TestModel.TEST_QNAME, "choice1"));
+        final ChoiceNode choice = Builders
+                .choiceBuilder()
+                .withNodeIdentifier(choice1Id)
+                .withChild(
+                        Builders.containerBuilder()
+                                .withNodeIdentifier(
+                                        new NodeIdentifier(QName.create(TestModel.TEST_QNAME, "case2-cont")))
+                                .withChild(leafNode(QName.create(TestModel.TEST_QNAME, "case2-leaf2"), "leaf-value2"))
+                                .build()).build();
+
+        final InMemoryDataTreeModification modificationTree2 = inMemoryDataTree.takeSnapshot().newModification();
+        modificationTree2.write(TestModel.TEST_PATH.node(choice1Id), choice);
+        modificationTree2.ready();
+        inMemoryDataTree.validate(modificationTree2);
+        final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(modificationTree2);
+        inMemoryDataTree.commit(prepare2);
+    }
 }
index 0c8052610fc618a0b879a51b51efd7ddd9a90690..a74bad4c3a75492869c3c463b1815ea6746eb2f4 100644 (file)
@@ -15,6 +15,7 @@ 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.Before;
 import org.junit.Test;
@@ -26,6 +27,7 @@ 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.tree.DataTree;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
@@ -99,7 +101,7 @@ public class ModificationMetadataTreeTest {
     public void prepare() throws ReactorException {
         schemaContext = TestModel.createTestContext();
         assertNotNull("Schema context must not be null.", schemaContext);
-        rootOper = RootModificationApplyOperation.from(SchemaAwareApplyOperation.from(schemaContext, TreeType.OPERATIONAL));
+        rootOper = RootModificationApplyOperation.from(SchemaAwareApplyOperation.from(schemaContext, DataTreeConfiguration.DEFAULT_OPERATIONAL));
     }
 
     /**
index 237d61a5796e20c351d16408e05c8457f70c5682..df72495d98f0e266f5e2aa59f9bcec5d08fad39f 100644 (file)
@@ -17,9 +17,7 @@ import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.ma
 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;
@@ -27,7 +25,7 @@ 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.TreeType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 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;
@@ -72,7 +70,7 @@ public class StoreTreeNodesTest {
     public void prepare() throws ReactorException {
         schemaContext = TestModel.createTestContext();
         assertNotNull("Schema context must not be null.", schemaContext);
-        rootOper = RootModificationApplyOperation.from(SchemaAwareApplyOperation.from(schemaContext, TreeType.OPERATIONAL));
+        rootOper = RootModificationApplyOperation.from(SchemaAwareApplyOperation.from(schemaContext, DataTreeConfiguration.DEFAULT_OPERATIONAL));
     }
 
     public NormalizedNode<?, ?> createDocumentOne() {