*/
package org.opendaylight.yangtools.yang.data.impl.leafref;
-import com.google.common.base.Optional;
+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;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
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.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
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.DataContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class LeafRefValidatation {
+// FIXME: 3.0.0: Rename to LeafRefValidation
+public final class LeafRefValidatation {
private static final Logger LOG = LoggerFactory.getLogger(LeafRefValidatation.class);
private static final String FAILED = " -> FAILED";
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();
return childReferencedByCtx;
}
- private void validateNodeData(final NormalizedNode<?, ?> node, final LeafRefContext referencedByCtx, final
- LeafRefContext referencingCtx, final ModificationType modificationType, final YangInstanceIdentifier current) {
+ private void validateNodeData(final NormalizedNode<?, ?> node, final LeafRefContext referencedByCtx,
+ final LeafRefContext referencingCtx, final ModificationType modificationType,
+ final YangInstanceIdentifier current) {
if (node instanceof LeafNode) {
final LeafNode<?> leaf = (LeafNode<?>) node;
} else if (node instanceof DataContainerNode) {
final DataContainerNode<?> dataContainerNode = (DataContainerNode<?>) node;
- for (final DataContainerChild<? extends PathArgument, ?> dataContainerChild : dataContainerNode.getValue()) {
- final QName qname = dataContainerChild.getNodeType();
+ for (final DataContainerChild<? extends PathArgument, ?> child : dataContainerNode.getValue()) {
+ if (child instanceof AugmentationNode) {
+ validateNodeData(child, referencedByCtx, referencingCtx, modificationType, current
+ .node(child.getIdentifier()));
+ return;
+ }
+ final QName qname = child.getNodeType();
final LeafRefContext childReferencedByCtx;
if (referencedByCtx != null) {
childReferencedByCtx = referencedByCtx.getReferencedChildByName(qname);
if (childReferencedByCtx != null || childReferencingCtx != null) {
final YangInstanceIdentifier childYangInstanceIdentifier = current
- .node(dataContainerChild.getIdentifier());
- validateNodeData(dataContainerChild, childReferencedByCtx,
+ .node(child.getIdentifier());
+ validateNodeData(child, childReferencedByCtx,
childReferencingCtx, modificationType, childYangInstanceIdentifier);
}
}
for (final MapEntryNode mapEntry : map.getValue()) {
final YangInstanceIdentifier mapEntryYangInstanceIdentifier = current.node(mapEntry.getIdentifier());
for (final DataContainerChild<? extends PathArgument, ?> mapEntryNode : mapEntry.getValue()) {
- final QName qname = mapEntryNode.getNodeType();
+ if (mapEntryNode instanceof AugmentationNode) {
+ validateNodeData(mapEntryNode, referencedByCtx, referencingCtx, modificationType, current
+ .node(mapEntryNode.getIdentifier()));
+ return;
+ }
+ final QName qname = mapEntryNode.getNodeType();
final LeafRefContext childReferencedByCtx;
if (referencedByCtx != null) {
childReferencedByCtx = referencedByCtx.getReferencedChildByName(qname);
}
if (childReferencedByCtx != null || childReferencingCtx != null) {
- final YangInstanceIdentifier mapEntryNodeYangInstanceIdentifier = mapEntryYangInstanceIdentifier
- .node(mapEntryNode.getIdentifier());
- validateNodeData(mapEntryNode, childReferencedByCtx,
- childReferencingCtx, modificationType,
- mapEntryNodeYangInstanceIdentifier);
+ validateNodeData(mapEntryNode, childReferencedByCtx, childReferencingCtx, modificationType,
+ mapEntryYangInstanceIdentifier.node(mapEntryNode.getIdentifier()));
}
}
}
}
- // FIXME if (node instance of UnkeyedListNode ...
+ // FIXME: check UnkeyedListNode case
}
private static LeafRefContext findReferencingCtxUnderChoice(
private void validateLeafRefTargetNodeData(final NormalizedNode<?, ?> leaf, final LeafRefContext
referencedByCtx, final ModificationType modificationType) {
- final Map<LeafRefContext, Set<?>> leafRefsValues = new HashMap<>();
- if (validatedLeafRefCtx.contains(referencedByCtx)) {
- leafRefTargetNodeDataLog(leaf, referencedByCtx, modificationType, leafRefsValues, null);
+ if (!validatedLeafRefCtx.add(referencedByCtx)) {
+ LOG.trace("Operation [{}] validate data of leafref TARGET node: name[{}] = value[{}] -> SKIP: Already "
+ + "validated", modificationType, referencedByCtx.getNodeName(), leaf.getValue());
return;
}
- final Map<QName, LeafRefContext> allReferencedByLeafRefCtxs = referencedByCtx.getAllReferencedByLeafRefCtxs();
- for (final LeafRefContext leafRefContext : allReferencedByLeafRefCtxs.values()) {
- if (leafRefContext.isReferencing()) {
- final Set<Object> values = new HashSet<>();
-
- final SchemaPath leafRefNodeSchemaPath = leafRefContext.getCurrentNodePath();
- final LeafRefPath leafRefNodePath = LeafRefUtils.schemaPathToLeafRefPath(leafRefNodeSchemaPath,
- leafRefContext.getLeafRefContextModule());
- final Iterable<QNameWithPredicate> pathFromRoot = leafRefNodePath.getPathFromRoot();
- addValues(values, tree.getRootNode().getDataAfter(), pathFromRoot, null, QNameWithPredicate.ROOT);
- leafRefsValues.put(leafRefContext, values);
- }
+ LOG.trace("Operation [{}] validate data of leafref TARGET node: name[{}] = value[{}]", modificationType,
+ referencedByCtx.getNodeName(), leaf.getValue());
+ final Set<LeafRefContext> leafRefs = referencedByCtx.getAllReferencedByLeafRefCtxs().values().stream()
+ .filter(LeafRefContext::isReferencing).collect(Collectors.toSet());
+ if (leafRefs.isEmpty()) {
+ return;
}
- if (!leafRefsValues.isEmpty()) {
- final Set<Object> leafRefTargetNodeValues = new HashSet<>();
- final SchemaPath nodeSchemaPath = referencedByCtx.getCurrentNodePath();
- final LeafRefPath nodePath = LeafRefUtils.schemaPathToLeafRefPath(nodeSchemaPath, referencedByCtx
- .getLeafRefContextModule());
- addValues(leafRefTargetNodeValues, tree.getRootNode().getDataAfter(), nodePath.getPathFromRoot(), null,
- QNameWithPredicate.ROOT);
- leafRefTargetNodeDataLog(leaf, referencedByCtx, modificationType, leafRefsValues,
- leafRefTargetNodeValues);
- } else {
- leafRefTargetNodeDataLog(leaf, referencedByCtx, modificationType, null, null);
- }
- validatedLeafRefCtx.add(referencedByCtx);
+ final Set<Object> leafRefTargetNodeValues = extractRootValues(referencedByCtx);
+ leafRefs.forEach(leafRefContext -> {
+ extractRootValues(leafRefContext).forEach(leafRefsValue -> {
+ if (leafRefTargetNodeValues.contains(leafRefsValue)) {
+ LOG.trace("Valid leafref value [{}] {}", leafRefsValue, SUCCESS);
+ return;
+ }
+
+ LOG.debug("Invalid leafref value [{}] allowed values {} by validation of leafref TARGET node: {} path "
+ + "of invalid LEAFREF node: {} leafRef target path: {} {}", leafRefsValue,
+ leafRefTargetNodeValues, leaf.getNodeType(), leafRefContext.getCurrentNodePath(),
+ leafRefContext.getAbsoluteLeafRefTargetPath(), FAILED);
+ errorsMessages.add(String.format("Invalid leafref value [%s] allowed values %s by validation of leafref"
+ + " TARGET node: %s path of invalid LEAFREF node: %s leafRef target path: %s %s", leafRefsValue,
+ leafRefTargetNodeValues, leaf.getNodeType(), leafRefContext.getCurrentNodePath(),
+ leafRefContext.getAbsoluteLeafRefTargetPath(),
+ FAILED));
+ });
+ });
}
- private void leafRefTargetNodeDataLog(final NormalizedNode<?, ?> leaf, final LeafRefContext referencedByCtx,
- final ModificationType modificationType, final Map<LeafRefContext, Set<?>> leafRefsValues,
- final Set<Object> leafRefTargetNodeValues) {
-
- if (leafRefsValues != null && !leafRefsValues.isEmpty()) {
- final Set<Entry<LeafRefContext, Set<?>>> entrySet = leafRefsValues.entrySet();
- LOG.debug("Operation [{}] validate data of leafref TARGET node: name[{}] = value[{}]",
- modificationType, referencedByCtx.getNodeName(), leaf.getValue());
- for (final Entry<LeafRefContext, Set<?>> entry : entrySet) {
- final LeafRefContext leafRefContext = entry.getKey();
- final Set<?> leafRefValuesSet = entry.getValue();
- for (final Object leafRefsValue : leafRefValuesSet) {
- if (leafRefTargetNodeValues != null && !leafRefTargetNodeValues.contains(leafRefsValue)) {
- LOG.debug("Invalid leafref value [{}] allowed values {} by validation of leafref TARGET node:" +
- " {} path of invalid LEAFREF node: {} leafRef target path: {} {}", leafRefsValue,
- leafRefTargetNodeValues, leaf.getNodeType(), leafRefContext.getCurrentNodePath(),
- leafRefContext.getAbsoluteLeafRefTargetPath(), FAILED);
- errorsMessages.add(String.format("Invalid leafref value [%s] allowed values %s by validation " +
- "of leafref TARGET node: %s path of invalid LEAFREF node: %s leafRef target " +
- "path: %s %s", leafRefsValue, leafRefTargetNodeValues, leaf.getNodeType(),
- leafRefContext.getCurrentNodePath(), leafRefContext.getAbsoluteLeafRefTargetPath(),
- FAILED));
- } else {
- LOG.debug("Valid leafref value [{}] {}", leafRefsValue, SUCCESS);
- }
- }
- }
- } else if (leafRefsValues != null) {
- LOG.debug("Operation [{}] validate data of leafref TARGET node: name[{}] = value[{}] -> SKIP: Already validated",
- modificationType, referencedByCtx.getNodeName(), leaf.getValue());
- }
+ private Set<Object> extractRootValues(final LeafRefContext context) {
+ 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<>();
- final LeafRefPath targetPath = referencingCtx.getAbsoluteLeafRefTargetPath();
- final Iterable<QNameWithPredicate> pathFromRoot = targetPath.getPathFromRoot();
-
- addValues(values, tree.getRootNode().getDataAfter(), pathFromRoot, current, QNameWithPredicate.ROOT);
-
- if (!values.contains(leaf.getValue())) {
- LOG.debug("Operation [{}] validate data of LEAFREF node: name[{}] = value[{}] {}",
- modificationType, referencingCtx.getNodeName(), leaf.getValue(), FAILED);
- LOG.debug("Invalid leafref value [{}] allowed values {} of LEAFREF node: {} leafRef target path: {}",
- leaf.getValue(), values, leaf.getNodeType(), referencingCtx.getAbsoluteLeafRefTargetPath());
- errorsMessages.add(String.format("Invalid leafref value [%s] allowed values %s of LEAFREF node: %s " +
- "leafRef target path: %s", leaf.getValue(), values, leaf.getNodeType(), referencingCtx
- .getAbsoluteLeafRefTargetPath()));
- } else {
+ 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);
+ referencingCtx.getNodeName(), leaf.getValue(), SUCCESS);
+ return;
}
+
+ LOG.debug("Operation [{}] validate data of LEAFREF node: name[{}] = value[{}] {}", modificationType,
+ referencingCtx.getNodeName(), leaf.getValue(), FAILED);
+ LOG.debug("Invalid leafref value [{}] allowed values {} of LEAFREF node: {} leafRef target path: {}",
+ leaf.getValue(), values, leaf.getNodeType(), referencingCtx.getAbsoluteLeafRefTargetPath());
+ errorsMessages.add(String.format("Invalid leafref value [%s] allowed values %s of LEAFREF node: %s leafRef "
+ + "target path: %s", leaf.getValue(), values, leaf.getNodeType(),
+ 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;
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);
}
.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);
}
}
}
return choiceNodes;
}
- private static boolean isMatchingPredicate(final MapEntryNode mapEntryNode, final Map<QName, Set<?>> allowedKeyValues) {
+ private static boolean isMatchingPredicate(final MapEntryNode mapEntryNode,
+ final Map<QName, Set<?>> allowedKeyValues) {
for (final Entry<QName, Object> entryKeyValue : mapEntryNode.getIdentifier().getKeyValues().entrySet()) {
final Set<?> allowedValues = allowedKeyValues.get(entryKeyValue.getKey());
if (allowedValues != null && !allowedValues.contains(entryKeyValue.getValue())) {
private Set<?> getPathKeyExpressionValues(final LeafRefPath predicatePathKeyExpression,
final YangInstanceIdentifier current) {
-
- final Optional<NormalizedNode<?, ?>> parent = findParentNode(tree.getRootNode().getDataAfter(), current);
-
- final Iterable<QNameWithPredicate> predicatePathExpr = predicatePathKeyExpression.getPathFromRoot();
- final Iterable<QNameWithPredicate> predicatePath = nextLevel(predicatePathExpr);
-
- final Set<Object> values = new HashSet<>();
- if (parent != null) {
- addValues(values, parent, predicatePath, 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(
return currentNode;
}
}
- return Optional.absent();
+ return Optional.empty();
}
private static Iterable<QNameWithPredicate> nextLevel(final Iterable<QNameWithPredicate> path) {
return Iterables.skip(path, 1);
}
-}
\ No newline at end of file
+}