2 * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.data.tree.impl;
10 import static com.google.common.base.Verify.verify;
11 import static java.util.Objects.requireNonNull;
13 import org.eclipse.jdt.annotation.NonNull;
14 import org.eclipse.jdt.annotation.Nullable;
15 import org.opendaylight.yangtools.concepts.Immutable;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
19 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
20 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
21 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
22 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
23 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * A path to a descendant which must exist. This really should be equivalent to YangInstanceIdentifier, but for now we
29 * need to deal with up to two possible paths -- one with AugmentationIdentifiers and one without.
31 // FIXME: 8.0.0: remove this structure and just keep the 'path' YangInstanceIdentifier
32 final class MandatoryDescendant implements Immutable {
33 private static final Logger LOG = LoggerFactory.getLogger(MandatoryDescendant.class);
35 // Correctly-nested path, mirroring Augmentation and choice/case structure
36 private final @NonNull YangInstanceIdentifier path;
37 // Legacy trivial path,
38 private final @Nullable YangInstanceIdentifier legacyPath;
40 private MandatoryDescendant(final YangInstanceIdentifier path, final YangInstanceIdentifier legacyPath) {
41 this.path = requireNonNull(path);
42 this.legacyPath = legacyPath;
45 static @NonNull MandatoryDescendant create(final YangInstanceIdentifier parentId,
46 final DataNodeContainer parentSchema, final DataSchemaNode childSchema) {
47 return new MandatoryDescendant(parentId.node(NodeIdentifier.create(childSchema.getQName())).toOptimized(),
51 void enforceOnData(final NormalizedNode data) {
52 // Find try primary path first ...
53 if (NormalizedNodes.findNode(data, path).isPresent()) {
56 // ... if we have a legacy path, try that as well ...
57 if (legacyPath != null && NormalizedNodes.findNode(data, legacyPath).isPresent()) {
58 // .. this should not really be happening ...
59 LOG.debug("Found {} at alternate path {}", path, legacyPath);
63 // ... not found, report the error
64 throw new IllegalArgumentException(String.format("Node %s is missing mandatory descendant %s",
65 data.getIdentifier(), path));
68 static AugmentationSchemaNode getAugIdentifierOfChild(final DataNodeContainer parent, final DataSchemaNode child) {
69 verify(parent instanceof AugmentationTarget,
70 "Unexpected augmenting child %s in non-target parent %s", child, parent);
71 return ((AugmentationTarget) parent).getAvailableAugmentations().stream()
72 .filter(augment -> augment.findDataChildByName(child.getQName()).isPresent())
74 .orElseThrow(() -> new IllegalArgumentException(String.format(
75 "Node %s is marked as augmenting but is not present in the schema of %s", child.getQName(), parent)));
79 public String toString() {
80 return legacyPath == null ? path.toString() : "(" + path + " || " + legacyPath + ")";