Pass down predicates instead of the entire predicate node
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / leafref / LeafRefValidatation.java
index bf7f2a74ab5458918263758920d6c45d2d54e947..5c4e8ce0d7c0012d45a9a967f7085e8b0d4145f2 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.leafref;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -41,6 +43,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+// FIXME: 3.0.0: Rename to LeafRefValidation
 public final class LeafRefValidatation {
 
     private static final Logger LOG = LoggerFactory.getLogger(LeafRefValidatation.class);
@@ -49,19 +52,23 @@ public final class LeafRefValidatation {
 
     private final Set<LeafRefContext> validatedLeafRefCtx = new HashSet<>();
     private final List<String> errorsMessages = new ArrayList<>();
-    private final DataTreeCandidate tree;
+    private final NormalizedNode<?, ?> root;
 
-    private LeafRefValidatation(final DataTreeCandidate tree) {
-        this.tree = tree;
+    private LeafRefValidatation(final NormalizedNode<?, ?> root) {
+        this.root = root;
     }
 
     public static void validate(final DataTreeCandidate tree, final LeafRefContext rootLeafRefCtx)
             throws LeafRefDataValidationFailedException {
-        new LeafRefValidatation(tree).validate0(rootLeafRefCtx);
+        final Optional<NormalizedNode<?, ?>> root = tree.getRootNode().getDataAfter();
+        if (root.isPresent()) {
+            new LeafRefValidatation(root.get()).validateChildren(rootLeafRefCtx, tree.getRootNode().getChildNodes());
+        }
     }
 
-    private void validate0(final LeafRefContext rootLeafRefCtx) throws LeafRefDataValidationFailedException {
-        for (final DataTreeCandidateNode dataTreeCandidateNode : tree.getRootNode().getChildNodes()) {
+    private void validateChildren(final LeafRefContext rootLeafRefCtx, final Collection<DataTreeCandidateNode> children)
+            throws LeafRefDataValidationFailedException {
+        for (final DataTreeCandidateNode dataTreeCandidateNode : children) {
             if (dataTreeCandidateNode.getModificationType() != ModificationType.UNMODIFIED) {
                 final PathArgument identifier = dataTreeCandidateNode.getIdentifier();
                 final QName childQName = identifier.getNodeType();
@@ -350,18 +357,13 @@ public final class LeafRefValidatation {
     }
 
     private Set<Object> extractRootValues(final LeafRefContext context) {
-        final Set<Object> values = new HashSet<>();
-        addValues(values, tree.getRootNode().getDataAfter(), context.getLeafRefNodePath().getPathFromRoot(), null,
-            QNameWithPredicate.ROOT);
-        return values;
+        return computeValues(root, context.getLeafRefNodePath().getPathFromRoot(), null);
     }
 
     private void validateLeafRefNodeData(final NormalizedNode<?, ?> leaf, final LeafRefContext referencingCtx,
             final ModificationType modificationType, final YangInstanceIdentifier current) {
-        final HashSet<Object> values = new HashSet<>();
-        addValues(values, tree.getRootNode().getDataAfter(),
-            referencingCtx.getAbsoluteLeafRefTargetPath().getPathFromRoot(), current, QNameWithPredicate.ROOT);
-
+        final Set<Object> values = computeValues(root, referencingCtx.getAbsoluteLeafRefTargetPath().getPathFromRoot(),
+            current);
         if (values.contains(leaf.getValue())) {
             LOG.debug("Operation [{}] validate data of LEAFREF node: name[{}] = value[{}] {}", modificationType,
                 referencingCtx.getNodeName(), leaf.getValue(), SUCCESS);
@@ -377,14 +379,16 @@ public final class LeafRefValidatation {
                 referencingCtx.getAbsoluteLeafRefTargetPath()));
     }
 
-    private void addValues(final Set<Object> values, final Optional<? extends NormalizedNode<?, ?>> optDataNode,
-            final Iterable<QNameWithPredicate> path, final YangInstanceIdentifier current,
-            final QNameWithPredicate previousQName) {
+    private Set<Object> computeValues(final NormalizedNode<?, ?> node, final Iterable<QNameWithPredicate> path,
+            final YangInstanceIdentifier current) {
+        final HashSet<Object> values = new HashSet<>();
+        addValues(values, node, ImmutableList.of(), path, current);
+        return values;
+    }
 
-        if (!optDataNode.isPresent()) {
-            return;
-        }
-        final NormalizedNode<?, ?> node = optDataNode.get();
+    private void addValues(final Set<Object> values, final NormalizedNode<?, ?> node,
+            final List<QNamePredicate> nodePredicates, final Iterable<QNameWithPredicate> path,
+            final YangInstanceIdentifier current) {
         if (node instanceof ValueNode) {
             values.add(node.getValue());
             return;
@@ -400,53 +404,45 @@ public final class LeafRefValidatation {
         if (!iterator.hasNext()) {
             return;
         }
-        final QNameWithPredicate qnameWithPredicate = iterator.next();
-        final QName qName = qnameWithPredicate.getQName();
-        final PathArgument pathArgument = new NodeIdentifier(qName);
 
+        final QNameWithPredicate next = iterator.next();
+        final QName qname = next.getQName();
+        final PathArgument pathArgument = new NodeIdentifier(qname);
         if (node instanceof DataContainerNode) {
             final DataContainerNode<?> dataContainerNode = (DataContainerNode<?>) node;
             final Optional<DataContainerChild<? extends PathArgument, ?>> child = dataContainerNode
                     .getChild(pathArgument);
 
             if (child.isPresent()) {
-                addValues(values, child, nextLevel(path), current, qnameWithPredicate);
+                addValues(values, child.get(), next.getQNamePredicates(), nextLevel(path), current);
             } else {
                 for (final ChoiceNode choiceNode : getChoiceNodes(dataContainerNode)) {
-                    addValues(values, Optional.of(choiceNode), path, current,
-                            qnameWithPredicate);
+                    addValues(values, choiceNode, next.getQNamePredicates(), path, current);
                 }
             }
 
         } else if (node instanceof MapNode) {
             final MapNode map = (MapNode) node;
-            final List<QNamePredicate> qNamePredicates = previousQName.getQNamePredicates();
-            if (qNamePredicates.isEmpty() || current == null) {
+            if (nodePredicates.isEmpty() || current == null) {
                 final Iterable<MapEntryNode> value = map.getValue();
                 for (final MapEntryNode mapEntryNode : value) {
                     final Optional<DataContainerChild<? extends PathArgument, ?>> child = mapEntryNode
                             .getChild(pathArgument);
 
                     if (child.isPresent()) {
-                        addValues(values, child, nextLevel(path), current, qnameWithPredicate);
+                        addValues(values, child.get(), next.getQNamePredicates(), nextLevel(path), current);
                     } else {
                         for (final ChoiceNode choiceNode : getChoiceNodes(mapEntryNode)) {
-                            addValues(values, Optional.of(choiceNode), path, current, qnameWithPredicate);
+                            addValues(values, choiceNode, next.getQNamePredicates(), path, current);
                         }
                     }
                 }
             } else {
                 final Map<QName, Set<?>> keyValues = new HashMap<>();
-
-                final Iterator<QNamePredicate> predicates = qNamePredicates.iterator();
-                while (predicates.hasNext()) {
-                    final QNamePredicate predicate = predicates.next();
+                for (QNamePredicate predicate : nodePredicates) {
                     final QName identifier = predicate.getIdentifier();
-                    final LeafRefPath predicatePathKeyExpression = predicate
-                            .getPathKeyExpression();
-
-                    final Set<?> pathKeyExprValues = getPathKeyExpressionValues(
-                            predicatePathKeyExpression, current);
+                    final LeafRefPath predicatePathKeyExpression = predicate.getPathKeyExpression();
+                    final Set<?> pathKeyExprValues = getPathKeyExpressionValues(predicatePathKeyExpression, current);
 
                     keyValues.put(identifier, pathKeyExprValues);
                 }
@@ -457,10 +453,10 @@ public final class LeafRefValidatation {
                                 .getChild(pathArgument);
 
                         if (child.isPresent()) {
-                            addValues(values, child, nextLevel(path), current, qnameWithPredicate);
+                            addValues(values, child.get(), next.getQNamePredicates(), nextLevel(path), current);
                         } else {
                             for (final ChoiceNode choiceNode : getChoiceNodes(mapEntryNode)) {
-                                addValues(values, Optional.of(choiceNode),  path, current, qnameWithPredicate);
+                                addValues(values, choiceNode,  next.getQNamePredicates(), path, current);
                             }
                         }
                     }
@@ -493,12 +489,9 @@ public final class LeafRefValidatation {
 
     private Set<?> getPathKeyExpressionValues(final LeafRefPath predicatePathKeyExpression,
             final YangInstanceIdentifier current) {
-        final Optional<NormalizedNode<?, ?>> parent = findParentNode(tree.getRootNode().getDataAfter(), current);
-        final Set<Object> values = new HashSet<>();
-        addValues(values, parent, nextLevel(predicatePathKeyExpression.getPathFromRoot()), null,
-            QNameWithPredicate.ROOT);
-
-        return values;
+        return findParentNode(Optional.of(root), current)
+                .map(parent -> computeValues(parent, nextLevel(predicatePathKeyExpression.getPathFromRoot()), null))
+                .orElse(ImmutableSet.of());
     }
 
     private static Optional<NormalizedNode<?, ?>> findParentNode(