import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
-import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
private final Set<LeafRefContext> validatedLeafRefCtx = new HashSet<>();
private final List<String> errorsMessages = new ArrayList<>();
- private final NormalizedNode<?, ?> root;
+ private final NormalizedNode root;
- private LeafRefValidation(final NormalizedNode<?, ?> root) {
+ private LeafRefValidation(final NormalizedNode root) {
this.root = root;
}
public static void validate(final DataTreeCandidate tree, final LeafRefContext rootLeafRefCtx)
throws LeafRefDataValidationFailedException {
- final Optional<NormalizedNode<?, ?>> root = tree.getRootNode().getDataAfter();
+ final Optional<NormalizedNode> root = tree.getRootNode().getDataAfter();
if (root.isPresent()) {
new LeafRefValidation(root.get()).validateChildren(rootLeafRefCtx, tree.getRootNode().getChildNodes());
}
final QName childQName = childNode.getIdentifier().getNodeType();
LeafRefContext childReferencingCtx = referencingCtx.getReferencingChildByName(childQName);
if (childReferencingCtx == null) {
- final NormalizedNode<?, ?> data = childNode.getDataAfter().get();
+ final NormalizedNode data = childNode.getDataAfter().get();
if (data instanceof MapEntryNode || data instanceof UnkeyedListEntryNode) {
childReferencingCtx = referencingCtx;
}
final QName childQName = childNode.getIdentifier().getNodeType();
LeafRefContext childReferencedByCtx = referencedByCtx.getReferencedChildByName(childQName);
if (childReferencedByCtx == null) {
- final NormalizedNode<?, ?> data = childNode.getDataAfter().get();
+ final NormalizedNode data = childNode.getDataAfter().get();
if (data instanceof MapEntryNode || data instanceof UnkeyedListEntryNode) {
childReferencedByCtx = referencedByCtx;
}
return childReferencedByCtx;
}
- private void validateNodeData(final NormalizedNode<?, ?> node, final LeafRefContext referencedByCtx,
+ private void validateNodeData(final NormalizedNode node, final LeafRefContext referencedByCtx,
final LeafRefContext referencingCtx, final ModificationType modificationType,
final YangInstanceIdentifier current) {
if (node instanceof LeafNode) {
} else if (node instanceof ChoiceNode) {
validateChoiceNodeData((ChoiceNode) node, referencedByCtx, referencingCtx, modificationType, current);
} else if (node instanceof DataContainerNode) {
- validateDataContainerNodeData((DataContainerNode<?>) node, referencedByCtx, referencingCtx,
- modificationType, current);
+ validateDataContainerNodeData((DataContainerNode) node, referencedByCtx, referencingCtx, modificationType,
+ current);
} else if (node instanceof MapNode) {
validateMapNodeData((MapNode) node, referencedByCtx, referencingCtx, modificationType, current);
}
final LeafRefContext referencingCtx, final ModificationType modificationType,
final YangInstanceIdentifier current) {
if (referencedByCtx != null || referencingCtx != null) {
- for (final NormalizedNode<?, ?> leafSetEntry : node.getValue()) {
+ for (final NormalizedNode leafSetEntry : node.body()) {
if (referencedByCtx != null && referencedByCtx.isReferenced()) {
validateLeafRefTargetNodeData(leafSetEntry, referencedByCtx, modificationType);
}
private void validateChoiceNodeData(final ChoiceNode node, final LeafRefContext referencedByCtx,
final LeafRefContext referencingCtx, final ModificationType modificationType,
final YangInstanceIdentifier current) {
- for (final DataContainerChild<?, ?> child : node.getValue()) {
- final QName qname = child.getNodeType();
+ for (final DataContainerChild child : node.body()) {
+ final QName qname = child.getIdentifier().getNodeType();
final LeafRefContext childReferencedByCtx = referencedByCtx == null ? null
: findReferencedByCtxUnderChoice(referencedByCtx, qname);
final LeafRefContext childReferencingCtx = referencingCtx == null ? null
}
}
- private void validateDataContainerNodeData(final DataContainerNode<?> node, final LeafRefContext referencedByCtx,
+ private void validateDataContainerNodeData(final DataContainerNode node, final LeafRefContext referencedByCtx,
final LeafRefContext referencingCtx, final ModificationType modificationType,
final YangInstanceIdentifier current) {
- for (final DataContainerChild<?, ?> child : node.getValue()) {
+ for (final DataContainerChild child : node.body()) {
if (child instanceof AugmentationNode) {
validateNodeData(child, referencedByCtx, referencingCtx, modificationType, current.node(
child.getIdentifier()));
private void validateMapNodeData(final MapNode node, final LeafRefContext referencedByCtx,
final LeafRefContext referencingCtx, final ModificationType modificationType,
final YangInstanceIdentifier current) {
- for (final MapEntryNode mapEntry : node.getValue()) {
+ for (final MapEntryNode mapEntry : node.asMap().values()) {
final YangInstanceIdentifier mapEntryIdentifier = current.node(mapEntry.getIdentifier());
- for (final DataContainerChild<?, ?> child : mapEntry.getValue()) {
+ for (final DataContainerChild child : mapEntry.body()) {
if (child instanceof AugmentationNode) {
validateNodeData(child, referencedByCtx, referencingCtx, modificationType, current.node(
child.getIdentifier()));
}
}
- private void validateChildNodeData(final DataContainerChild<?, ?> child, final LeafRefContext referencedByCtx,
+ private void validateChildNodeData(final DataContainerChild child, final LeafRefContext referencedByCtx,
final LeafRefContext referencingCtx, final ModificationType modificationType,
final YangInstanceIdentifier current) {
- final QName qname = child.getNodeType();
+ final QName qname = child.getIdentifier().getNodeType();
final LeafRefContext childReferencedByCtx = referencedByCtx == null ? null
: referencedByCtx.getReferencedChildByName(qname);
final LeafRefContext childReferencingCtx = referencingCtx == null ? null
return null;
}
- private void validateLeafRefTargetNodeData(final NormalizedNode<?, ?> leaf, final LeafRefContext
+ private void validateLeafRefTargetNodeData(final NormalizedNode leaf, final LeafRefContext
referencedByCtx, final ModificationType modificationType) {
if (!validatedLeafRefCtx.add(referencedByCtx)) {
LOG.trace("Operation [{}] validate data of leafref TARGET node: name[{}] = value[{}] -> SKIP: Already "
- + "validated", modificationType, referencedByCtx.getNodeName(), leaf.getValue());
+ + "validated", modificationType, referencedByCtx.getNodeName(), leaf.body());
return;
}
LOG.trace("Operation [{}] validate data of leafref TARGET node: name[{}] = value[{}]", modificationType,
- referencedByCtx.getNodeName(), leaf.getValue());
+ referencedByCtx.getNodeName(), leaf.body());
final Set<LeafRefContext> leafRefs = referencedByCtx.getAllReferencedByLeafRefCtxs().values().stream()
.filter(LeafRefContext::isReferencing).collect(Collectors.toSet());
if (leafRefs.isEmpty()) {
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(),
+ leafRefTargetNodeValues, leaf.getIdentifier(), 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(),
+ leafRefTargetNodeValues, leaf.getIdentifier(), leafRefContext.getCurrentNodePath(),
leafRefContext.getAbsoluteLeafRefTargetPath(),
FAILED));
});
return computeValues(root, createPath(context.getLeafRefNodePath()), null);
}
- private void validateLeafRefNodeData(final NormalizedNode<?, ?> leaf, final LeafRefContext referencingCtx,
+ private void validateLeafRefNodeData(final NormalizedNode leaf, final LeafRefContext referencingCtx,
final ModificationType modificationType, final YangInstanceIdentifier current) {
final Set<Object> values = computeValues(root, createPath(referencingCtx.getAbsoluteLeafRefTargetPath()),
current);
- if (values.contains(leaf.getValue())) {
+ if (values.contains(leaf.body())) {
LOG.debug("Operation [{}] validate data of LEAFREF node: name[{}] = value[{}] {}", modificationType,
- referencingCtx.getNodeName(), leaf.getValue(), SUCCESS);
+ referencingCtx.getNodeName(), leaf.body(), SUCCESS);
return;
}
LOG.debug("Operation [{}] validate data of LEAFREF node: name[{}] = value[{}] {}", modificationType,
- referencingCtx.getNodeName(), leaf.getValue(), FAILED);
+ referencingCtx.getNodeName(), leaf.body(), FAILED);
LOG.debug("Invalid leafref value [{}] allowed values {} of LEAFREF node: {} leafRef target path: {}",
- leaf.getValue(), values, leaf.getNodeType(), referencingCtx.getAbsoluteLeafRefTargetPath());
+ leaf.body(), values, leaf.getIdentifier(), 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(),
+ + "target path: %s", leaf.body(), values, leaf.getIdentifier(),
referencingCtx.getAbsoluteLeafRefTargetPath()));
}
- private Set<Object> computeValues(final NormalizedNode<?, ?> node, final Deque<QNameWithPredicate> path,
+ private Set<Object> computeValues(final NormalizedNode node, final Deque<QNameWithPredicate> path,
final YangInstanceIdentifier current) {
final HashSet<Object> values = new HashSet<>();
addValues(values, node, ImmutableList.of(), path, current);
return values;
}
- private void addValues(final Set<Object> values, final NormalizedNode<?, ?> node,
+ private void addValues(final Set<Object> values, final NormalizedNode node,
final List<QNamePredicate> nodePredicates, final Deque<QNameWithPredicate> path,
final YangInstanceIdentifier current) {
if (node instanceof ValueNode) {
- values.add(node.getValue());
+ values.add(node.body());
return;
}
if (node instanceof LeafSetNode<?>) {
- for (final NormalizedNode<?, ?> entry : ((LeafSetNode<?>) node).getValue()) {
- values.add(entry.getValue());
+ for (final NormalizedNode entry : ((LeafSetNode<?>) node).body()) {
+ values.add(entry.body());
}
return;
}
return;
}
- final QName qname = next.getQName();
- final PathArgument pathArgument = new NodeIdentifier(qname);
+ final PathArgument pathArgument = new NodeIdentifier(next.getQName());
if (node instanceof DataContainerNode) {
- final DataContainerNode<?> dataContainerNode = (DataContainerNode<?>) node;
- final Optional<DataContainerChild<?, ?>> child = dataContainerNode.getChild(pathArgument);
- if (child.isPresent()) {
- addNextValues(values, child.get(), next.getQNamePredicates(), path, current);
- } else {
- forEachChoice(dataContainerNode,
- choice -> addValues(values, choice, next.getQNamePredicates(), path, current));
- }
+ processChildNode(values, (DataContainerNode) node, pathArgument, next.getQNamePredicates(), path, current);
} else if (node instanceof MapNode) {
- Stream<MapEntryNode> entries = ((MapNode) node).getValue().stream();
+ Stream<MapEntryNode> entries = ((MapNode) node).body().stream();
if (!nodePredicates.isEmpty() && current != null) {
entries = entries.filter(createMapEntryPredicate(nodePredicates, current));
}
- entries.forEach(mapEntryNode -> {
- final Optional<DataContainerChild<?, ?>> child = mapEntryNode.getChild(pathArgument);
- if (child.isPresent()) {
- addNextValues(values, child.get(), next.getQNamePredicates(), path, current);
- } else {
- forEachChoice(mapEntryNode,
- choice -> addValues(values, choice, next.getQNamePredicates(), path, current));
+ entries.forEach(entry -> processChildNode(values, entry, pathArgument, next.getQNamePredicates(), path,
+ current));
+ }
+ }
+
+ private void processChildNode(final Set<Object> values, final DataContainerNode parent,
+ final PathArgument arg, final List<QNamePredicate> nodePredicates, final Deque<QNameWithPredicate> path,
+ final YangInstanceIdentifier current) {
+ final DataContainerChild child = parent.childByArg(arg);
+ if (child == null) {
+ // FIXME: YANGTOOLS-901. We have SchemaContext nearby, hence we should be able to cache how to get
+ // to the leaf with with specified QName, without having to iterate through Choices/Augmentations.
+ // That perhaps means we should not have QNameWithPredicates, but NodeIdentifierWithPredicates as
+ // the path specification.
+ for (final DataContainerChild mixin : parent.body()) {
+ if (mixin instanceof AugmentationNode || mixin instanceof ChoiceNode) {
+ addValues(values, mixin, nodePredicates, path, current);
}
- });
+ }
+ } else {
+ addNextValues(values, child, nodePredicates, path, current);
}
}
}
return mapEntry -> {
- for (final Entry<QName, Object> entryKeyValue : mapEntry.getIdentifier().getKeyValues().entrySet()) {
+ for (final Entry<QName, Object> entryKeyValue : mapEntry.getIdentifier().entrySet()) {
final Set<?> allowedValues = keyValues.get(entryKeyValue.getKey());
if (allowedValues != null && !allowedValues.contains(entryKeyValue.getValue())) {
return false;
};
}
- private void addNextValues(final Set<Object> values, final NormalizedNode<?, ?> node,
+ private void addNextValues(final Set<Object> values, final NormalizedNode node,
final List<QNamePredicate> nodePredicates, final Deque<QNameWithPredicate> path,
final YangInstanceIdentifier current) {
final QNameWithPredicate element = path.pop();
}
}
- private static void forEachChoice(final DataContainerNode<?> node, final Consumer<ChoiceNode> consumer) {
- for (final DataContainerChild<?, ?> child : node.getValue()) {
- if (child instanceof ChoiceNode) {
- consumer.accept((ChoiceNode) child);
- }
- }
- }
-
private Set<?> getPathKeyExpressionValues(final LeafRefPath predicatePathKeyExpression,
final YangInstanceIdentifier current) {
return findParentNode(Optional.of(root), current).map(parent -> {
}).orElse(ImmutableSet.of());
}
- private static Optional<NormalizedNode<?, ?>> findParentNode(
- final Optional<NormalizedNode<?, ?>> root, final YangInstanceIdentifier path) {
- Optional<NormalizedNode<?, ?>> currentNode = root;
+ private static Optional<NormalizedNode> findParentNode(
+ final Optional<NormalizedNode> root, final YangInstanceIdentifier path) {
+ Optional<NormalizedNode> currentNode = root;
final Iterator<PathArgument> pathIterator = path.getPathArguments().iterator();
while (pathIterator.hasNext()) {
final PathArgument childPathArgument = pathIterator.next();