* 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.tree.impl;
+package org.opendaylight.yangtools.yang.data.spi.node;
import static java.util.Objects.requireNonNull;
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.NormalizedNodes;
-import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
-import org.opendaylight.yangtools.yang.data.tree.api.TreeType;
-import org.opendaylight.yangtools.yang.data.tree.impl.node.TreeNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.ElementCountConstraintAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-// TODO: would making this Serializable be useful (for Functions and similar?)
-final class MandatoryLeafEnforcer implements Immutable {
+public final class MandatoryLeafEnforcer implements Immutable {
private static final Logger LOG = LoggerFactory.getLogger(MandatoryLeafEnforcer.class);
// FIXME: Well, there is still room to optimize footprint and performance. This list of lists can have overlaps,
this.mandatoryNodes = requireNonNull(mandatoryNodes);
}
- static @Nullable MandatoryLeafEnforcer forContainer(final DataNodeContainer schema,
- final DataTreeConfiguration treeConfig) {
- if (!treeConfig.isMandatoryNodesValidationEnabled()) {
- return null;
- }
+ public static @Nullable MandatoryLeafEnforcer forContainer(final DataNodeContainer schema,
+ final boolean includeConfigFalse) {
final var builder = ImmutableList.<ImmutableList<PathArgument>>builder();
- findMandatoryNodes(builder, YangInstanceIdentifier.of(), schema, treeConfig.getTreeType());
+ findMandatoryNodes(builder, YangInstanceIdentifier.of(), schema, includeConfigFalse);
final var mandatoryNodes = builder.build();
return mandatoryNodes.isEmpty() ? null : new MandatoryLeafEnforcer(mandatoryNodes);
}
- void enforceOnData(final NormalizedNode data) {
+ public void enforceOnData(final NormalizedNode data) {
for (var path : mandatoryNodes) {
if (NormalizedNodes.findNode(data, path).isEmpty()) {
throw new IllegalArgumentException("Node " + data.name() + " is missing mandatory descendant "
}
}
- void enforceOnTreeNode(final TreeNode tree) {
- enforceOnData(tree.getData());
- }
-
private static void findMandatoryNodes(final Builder<ImmutableList<PathArgument>> builder,
- final YangInstanceIdentifier id, final DataNodeContainer schema, final TreeType type) {
+ final YangInstanceIdentifier id, final DataNodeContainer schema, final boolean includeConfigFalse) {
for (var child : schema.getChildNodes()) {
- if (SchemaAwareApplyOperation.belongsToTree(type, child)) {
+ if (includeConfigFalse || child.effectiveConfig().orElse(Boolean.TRUE)) {
if (child instanceof ContainerSchemaNode container) {
if (!container.isPresenceContainer()) {
// the container is either:
// - in an augmented subtree
// in both cases just append the NodeID to the ongoing ID and continue the search.
findMandatoryNodes(builder, id.node(NodeIdentifier.create(container.getQName())), container,
- type);
+ includeConfigFalse);
}
} else {
boolean needEnforce = child instanceof MandatoryAware aware && aware.isMandatory();
requires org.opendaylight.yangtools.yang.data.impl;
requires org.opendaylight.yangtools.yang.data.spi;
requires org.opendaylight.yangtools.yang.data.util;
+ requires org.opendaylight.yangtools.yang.model.api;
requires org.slf4j;
// Annotations
import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMap.Builder;
import java.util.Map.Entry;
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.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.spi.node.MandatoryLeafEnforcer;
import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
import org.opendaylight.yangtools.yang.data.tree.api.TreeType;
import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
}
static CaseEnforcer forTree(final CaseSchemaNode schema, final DataTreeConfiguration treeConfig) {
- final TreeType type = treeConfig.getTreeType();
- final Builder<NodeIdentifier, DataSchemaNode> childrenBuilder = ImmutableMap.builder();
- if (SchemaAwareApplyOperation.belongsToTree(type, schema)) {
- for (final DataSchemaNode child : schema.getChildNodes()) {
- if (SchemaAwareApplyOperation.belongsToTree(type, child)) {
+ final var treeType = treeConfig.getTreeType();
+ final var childrenBuilder = ImmutableMap.<NodeIdentifier, DataSchemaNode>builder();
+ if (SchemaAwareApplyOperation.belongsToTree(treeType, schema)) {
+ for (var child : schema.getChildNodes()) {
+ if (SchemaAwareApplyOperation.belongsToTree(treeType, child)) {
childrenBuilder.put(NodeIdentifier.create(child.getQName()), child);
}
}
}
- final ImmutableMap<NodeIdentifier, DataSchemaNode> children = childrenBuilder.build();
+ final var children = childrenBuilder.build();
if (children.isEmpty()) {
return null;
}
- final var enforcer = MandatoryLeafEnforcer.forContainer(schema, treeConfig);
- return enforcer != null ? new EnforcingMandatory(children, enforcer) : new CaseEnforcer(children);
+ if (treeConfig.isMandatoryNodesValidationEnabled()) {
+ final var enforcer = MandatoryLeafEnforcer.forContainer(schema, treeType == TreeType.OPERATIONAL);
+ if (enforcer != null) {
+ return new EnforcingMandatory(children, enforcer);
+ }
+ }
+ return new CaseEnforcer(children);
}
final Set<Entry<NodeIdentifier, DataSchemaNode>> getChildEntries() {
import static java.util.Objects.requireNonNull;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.DistinctNodeContainer;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.spi.node.MandatoryLeafEnforcer;
import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
import org.opendaylight.yangtools.yang.data.tree.impl.node.TreeNode;
import org.opendaylight.yangtools.yang.data.tree.impl.node.Version;
@Override
protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
- final var ret = super.applyMerge(modification, currentMeta, version);
- enforcer.enforceOnTreeNode(ret);
- return ret;
+ return enforce(super.applyMerge(modification, currentMeta, version));
}
@Override
protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue,
final TreeNode currentMeta, final Version version) {
- final var ret = super.applyWrite(modification, newValue, currentMeta, version);
- enforcer.enforceOnTreeNode(ret);
- return ret;
+ return enforce(super.applyWrite(modification, newValue, currentMeta, version));
}
@Override
protected TreeNode applyTouch(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
- final var ret = super.applyTouch(modification, currentMeta, version);
- enforcer.enforceOnTreeNode(ret);
- return ret;
+ return enforce(super.applyTouch(modification, currentMeta, version));
+ }
+
+ private @NonNull TreeNode enforce(final TreeNode treeNode) {
+ enforcer.enforceOnData(treeNode.getData());
+ return treeNode;
}
}
static ContainerModificationStrategy of(final ContainerSchemaNode schema, final DataTreeConfiguration treeConfig) {
if (schema.isPresenceContainer()) {
- final var enforcer = MandatoryLeafEnforcer.forContainer(schema, treeConfig);
+ final var enforcer = enforcerFor(schema, treeConfig);
return enforcer != null ? new EnforcingMandatory(schema, treeConfig, enforcer)
: new ContainerModificationStrategy(schema, treeConfig);
}
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.spi.node.MandatoryLeafEnforcer;
import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
import org.opendaylight.yangtools.yang.data.tree.impl.node.TreeNode;
import org.opendaylight.yangtools.yang.data.tree.impl.node.Version;
@Override
protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
- final var ret = super.applyMerge(modification, currentMeta, version);
- enforcer.enforceOnTreeNode(ret);
- return ret;
+ return enforce(super.applyMerge(modification, currentMeta, version));
}
@Override
protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue,
final TreeNode currentMeta, final Version version) {
- final var ret = super.applyWrite(modification, newValue, currentMeta, version);
- enforcer.enforceOnTreeNode(ret);
- return ret;
+ return enforce(super.applyWrite(modification, newValue, currentMeta, version));
}
@Override
protected TreeNode applyTouch(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
- final var ret = super.applyTouch(modification, currentMeta, version);
- enforcer.enforceOnTreeNode(ret);
- return ret;
+ return enforce(super.applyTouch(modification, currentMeta, version));
+ }
+
+ private @NonNull TreeNode enforce(final TreeNode treeNode) {
+ enforcer.enforceOnData(treeNode.getData());
+ return treeNode;
}
}
static @NonNull MapEntryModificationStrategy of(final ListSchemaNode schema,
final DataTreeConfiguration treeConfig) {
- final var enforcer = MandatoryLeafEnforcer.forContainer(schema, treeConfig);
+ final var enforcer = enforcerFor(schema, treeConfig);
return enforcer != null ? new EnforcingMandatory(schema, treeConfig, enforcer)
: new MapEntryModificationStrategy(schema, treeConfig);
}
import org.opendaylight.yangtools.yang.data.api.schema.AnyxmlNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.spi.node.MandatoryLeafEnforcer;
import org.opendaylight.yangtools.yang.data.tree.api.ConflictingModificationAppliedException;
import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
static final boolean belongsToTree(final TreeType treeType, final DataSchemaNode node) {
return treeType == TreeType.OPERATIONAL || node.effectiveConfig().orElse(Boolean.TRUE);
}
+
+ static final @Nullable MandatoryLeafEnforcer enforcerFor(final DataSchemaNode schema,
+ final DataTreeConfiguration treeConfig) {
+ if (treeConfig.isMandatoryNodesValidationEnabled() && schema instanceof DataNodeContainer container) {
+ final var includeConfigFalse = treeConfig.getTreeType() == TreeType.OPERATIONAL;
+ if (includeConfigFalse || schema.effectiveConfig().orElse(Boolean.TRUE)) {
+ return MandatoryLeafEnforcer.forContainer(container, includeConfigFalse);
+ }
+ }
+ return null;
+ }
}