*/
package org.opendaylight.yangtools.yang.data.tree.impl;
-import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateTip;
@Override
public final void validate(final DataTreeModification modification) throws DataValidationFailedException {
final var m = accessMod(modification, "validate");
- m.getStrategy().checkApplicable(new ModificationPath(getRootPath()), m.getRootModification(),
- Optional.of(getTipRoot()), m.getVersion());
+ m.getStrategy().checkApplicable(new ModificationPath(getRootPath()), m.getRootModification(), getTipRoot(),
+ m.getVersion());
}
@Override
return new NoopDataTreeCandidate(YangInstanceIdentifier.of(), root, currentRoot);
}
- final var newRoot = m.getStrategy().apply(m.getRootModification(), Optional.of(currentRoot), m.getVersion())
- .orElseThrow(() -> new IllegalStateException("Apply strategy failed to produce root node for modification "
- + modification));
+ final var newRoot = m.getStrategy().apply(m.getRootModification(), currentRoot, m.getVersion())
+ .orElseThrow(() -> new IllegalStateException(
+ "Apply strategy failed to produce root node for modification " + modification));
return new InMemoryDataTreeCandidate(YangInstanceIdentifier.of(), root, currentRoot, newRoot);
}
import static java.util.Objects.requireNonNull;
import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.common.base.Verify;
+import com.google.common.base.VerifyException;
import java.util.Collection;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.DistinctNodeContainer;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
@Override
protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue,
- final Optional<? extends TreeNode> currentMeta, final Version version) {
+ final TreeNode currentMeta, final Version version) {
final var newValueMeta = TreeNode.of(newValue, version);
if (modification.isEmpty()) {
return newValueMeta;
@SuppressWarnings({ "rawtypes", "unchecked" })
private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
-
- for (final ModifiedNode mod : modifications) {
- final PathArgument id = mod.getIdentifier();
- final Optional<? extends TreeNode> cm = meta.findChildByArg(id);
-
- final Optional<? extends TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
+ for (var mod : modifications) {
+ final var id = mod.getIdentifier();
+ final var result = resolveChildOperation(id).apply(mod, meta.childByArg(id), nodeVersion);
if (result.isPresent()) {
- final TreeNode tn = result.orElseThrow();
+ final var tn = result.orElseThrow();
meta.putChild(tn);
data.addChild(tn.getData());
} else {
* we do that, ModifiedNode children will look like this node were a TOUCH and we will let applyTouch() do the
* heavy lifting of applying the children recursively (either through here or through applyWrite().
*/
- final NormalizedNode value = modification.getWrittenValue();
+ final var value = modification.getWrittenValue();
+ if (!(value instanceof DistinctNodeContainer<?, ?> containerValue)) {
+ throw new VerifyException("Attempted to merge non-container " + value);
+ }
- Verify.verify(value instanceof DistinctNodeContainer, "Attempted to merge non-container %s", value);
- for (var c : ((DistinctNodeContainer<?, ?>) value).body()) {
+ for (var c : containerValue.body()) {
final var id = c.name();
modification.modifyChild(id, resolveChildOperation(id), version);
}
// and then append any child entries.
if (!modification.isEmpty()) {
// Version does not matter here as we'll throw it out
- final var current = apply(modification, modification.getOriginal(), Version.initial());
+ final var current = apply(modification, modification.original(), Version.initial());
if (current.isPresent()) {
modification.updateValue(LogicalOperation.WRITE, current.orElseThrow().getData());
mergeChildrenIntoModification(modification, valueChildren, version);
@Override
protected final void checkTouchApplicable(final ModificationPath path, final NodeModification modification,
- final Optional<? extends TreeNode> current, final Version version) throws DataValidationFailedException {
+ final TreeNode currentMeta, final Version version) throws DataValidationFailedException {
final TreeNode currentNode;
- if (current.isEmpty()) {
+ if (currentMeta == null) {
currentNode = defaultTreeNode();
if (currentNode == null) {
if (modification.original() == null) {
"Node was deleted by other transaction.");
}
} else {
- currentNode = current.orElseThrow();
+ currentNode = currentMeta;
}
checkChildPreconditions(path, modification, currentNode, version);
@Override
protected final void checkMergeApplicable(final ModificationPath path, final NodeModification modification,
- final Optional<? extends TreeNode> current, final Version version) throws DataValidationFailedException {
- if (current.isPresent()) {
- checkChildPreconditions(path, modification, current.orElseThrow(), version);
+ final TreeNode currentMeta, final Version version) throws DataValidationFailedException {
+ if (currentMeta != null) {
+ checkChildPreconditions(path, modification, currentMeta, version);
}
}
*
* @param path current node path
* @param modification current modification
- * @param current Current data tree node.
+ * @param currentMeta Current data tree node.
*/
private void checkChildPreconditions(final ModificationPath path, final NodeModification modification,
- final TreeNode current, final Version version) throws DataValidationFailedException {
- for (final NodeModification childMod : modification.getChildren()) {
- final PathArgument childId = childMod.getIdentifier();
- final Optional<? extends TreeNode> childMeta = current.findChildByArg(childId);
+ final @NonNull TreeNode currentMeta, final Version version) throws DataValidationFailedException {
+ for (var childMod : modification.getChildren()) {
+ final var childId = childMod.getIdentifier();
+ final var childMeta = currentMeta.childByArg(childId);
path.push(childId);
try {
}
@Override
- final Optional<? extends TreeNode> apply(final ModifiedNode modification,
- final Optional<? extends TreeNode> storeMeta, final Version version) {
- var validated = modification.validatedNode(this, storeMeta);
+ final Optional<? extends TreeNode> apply(final ModifiedNode modification, final TreeNode currentMeta,
+ final Version version) {
+ var validated = modification.validatedNode(this, currentMeta);
if (validated != null) {
return validated.toOptional();
}
// This might also mean the delegate is maintaining validation
if (delegate instanceof AbstractValidation) {
- validated = modification.validatedNode(delegate, storeMeta);
+ validated = modification.validatedNode(delegate, currentMeta);
if (validated != null) {
return validated.toOptional();
}
}
// Deal with the result moving on us
- final var ret = delegate.apply(modification, storeMeta, version);
+ final var ret = delegate.apply(modification, currentMeta, version);
ret.ifPresent(meta -> enforceOnData(meta.getData()));
return ret;
}
@Override
final void checkApplicable(final ModificationPath path, final NodeModification modification,
- final Optional<? extends TreeNode> current, final Version version) throws DataValidationFailedException {
- delegate.checkApplicable(path, modification, current, version);
+ final TreeNode currentMeta, final Version version) throws DataValidationFailedException {
+ delegate.checkApplicable(path, modification, currentMeta, version);
if (!(modification instanceof ModifiedNode modified)) {
// FIXME: 7.0.0: turn this into a verify?
LOG.debug("Could not validate {}, does not implement expected class {}", modification, ModifiedNode.class);
}
if (delegate instanceof AbstractValidation) {
- checkApplicable(path, verifyNotNull(modified.validatedNode(delegate, current)).toOptional());
+ checkApplicable(path, verifyNotNull(modified.validatedNode(delegate, currentMeta)).toOptional());
return;
}
// We need to actually perform the operation to deal with merge in a sane manner. We know the modification
// is immutable, so the result of validation will probably not change. Note we should not be checking number
- final Optional<? extends TreeNode> applied = delegate.apply(modified, current, version);
+ final var applied = delegate.apply(modified, currentMeta, version);
checkApplicable(path, applied);
// Everything passed. We now have a snapshot of the result node, it would be too bad if we just threw it out.
// - the effective model context (therefore, the fact this object is associated with the modification)
//
// So let's stash the result. We will pick it up during apply operation.
- modified.setValidatedNode(this, current, applied);
+ modified.setValidatedNode(this, currentMeta, applied);
}
private void checkApplicable(final ModificationPath path, final Optional<? extends TreeNode> applied)
import static com.google.common.base.Preconditions.checkState;
import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
import org.opendaylight.yangtools.yang.data.tree.api.ModificationType;
*/
final class AutomaticLifecycleMixin {
/**
- * This is a capture of {@link ModificationApplyOperation#apply(ModifiedNode, Optional, Version)}.
+ * This is a capture of {@link ModificationApplyOperation#apply(ModifiedNode, TreeNode, Version)}.
*/
@FunctionalInterface
interface Apply {
- Optional<? extends TreeNode> apply(ModifiedNode modification, Optional<? extends TreeNode> storeMeta,
- Version version);
+ Optional<? extends TreeNode> apply(ModifiedNode modification, @Nullable TreeNode currentMeta, Version version);
}
/**
* This is a capture of
- * {@link SchemaAwareApplyOperation#applyWrite(ModifiedNode, NormalizedNode, Optional, Version)}.
+ * {@link SchemaAwareApplyOperation#applyWrite(ModifiedNode, NormalizedNode, TreeNode, Version)}.
*/
@FunctionalInterface
interface ApplyWrite {
- TreeNode applyWrite(ModifiedNode modification, NormalizedNode newValue,
- Optional<? extends TreeNode> storeMeta, Version version);
+ TreeNode applyWrite(ModifiedNode modification, NormalizedNode newValue, @Nullable TreeNode currentMeta,
+ Version version);
}
private AutomaticLifecycleMixin() {
-
+ // Hidden on purpose
}
static Optional<? extends TreeNode> apply(final Apply delegate, final ApplyWrite writeDelegate,
- final NormalizedNode emptyNode, final ModifiedNode modification,
- final Optional<? extends TreeNode> storeMeta, final Version version) {
+ final NormalizedNode emptyNode, final ModifiedNode modification, final @Nullable TreeNode currentMeta,
+ final Version version) {
final Optional<? extends TreeNode> ret;
if (modification.getOperation() == LogicalOperation.DELETE) {
if (modification.isEmpty()) {
- return delegate.apply(modification, storeMeta, version);
+ return delegate.apply(modification, currentMeta, version);
}
// Delete with children, implies it really is an empty write
- ret = Optional.of(writeDelegate.applyWrite(modification, emptyNode, storeMeta, version));
- } else if (modification.getOperation() == LogicalOperation.TOUCH && storeMeta.isEmpty()) {
- ret = applyTouch(delegate, emptyNode, modification, storeMeta, version);
+ ret = Optional.of(writeDelegate.applyWrite(modification, emptyNode, currentMeta, version));
+ } else if (modification.getOperation() == LogicalOperation.TOUCH && currentMeta == null) {
+ ret = applyTouch(delegate, emptyNode, modification, null, version);
} else {
// No special handling required here, run normal apply operation
- ret = delegate.apply(modification, storeMeta, version);
+ ret = delegate.apply(modification, currentMeta, version);
}
- return ret.isPresent() ? disappearResult(modification, ret.orElseThrow(), storeMeta) : ret;
+ return ret.isPresent() ? disappearResult(modification, ret.orElseThrow(), currentMeta) : ret;
}
private static Optional<? extends TreeNode> applyTouch(final Apply delegate, final NormalizedNode emptyNode,
- final ModifiedNode modification, final Optional<? extends TreeNode> storeMeta, final Version version) {
+ final ModifiedNode modification, final @Nullable TreeNode currentMeta, final Version version) {
// Container is not present, let's take care of the 'magically appear' part of our job
- final Optional<? extends TreeNode> ret = delegate.apply(modification, fakeMeta(emptyNode, version), version);
+ final var ret = delegate.apply(modification, fakeMeta(emptyNode, version), version);
// If the delegate indicated SUBTREE_MODIFIED, account for the fake and report APPEARED
if (modification.getModificationType() == ModificationType.SUBTREE_MODIFIED) {
}
private static Optional<? extends TreeNode> disappearResult(final ModifiedNode modification, final TreeNode result,
- final Optional<? extends TreeNode> storeMeta) {
+ final @Nullable TreeNode currentMeta) {
// Check if the result is in fact empty before pulling any tricks
if (!isEmpty(result)) {
return Optional.of(result);
// We are pulling the 'disappear' trick, but what we report can be three different things
final ModificationType finalType;
- if (storeMeta.isEmpty()) {
+ if (currentMeta == null) {
// ... there was nothing in the datastore, no change
finalType = ModificationType.UNMODIFIED;
} else if (modification.getModificationType() == ModificationType.WRITE) {
return Optional.empty();
}
- private static Optional<TreeNode> fakeMeta(final NormalizedNode emptyNode, final Version version) {
- return Optional.of(TreeNode.of(emptyNode, version));
+ private static @NonNull TreeNode fakeMeta(final NormalizedNode emptyNode, final Version version) {
+ return TreeNode.of(emptyNode, version);
}
private static boolean isEmpty(final TreeNode treeNode) {
}
@Override
- Optional<? extends TreeNode> apply(final ModifiedNode modification, final Optional<? extends TreeNode> storeMeta,
+ Optional<? extends TreeNode> apply(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
- return AutomaticLifecycleMixin.apply(super::apply, this::applyWrite, emptyNode, modification, storeMeta,
+ return AutomaticLifecycleMixin.apply(super::apply, this::applyWrite, emptyNode, modification, currentMeta,
version);
}
@Override
protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta, final Version version) {
- final TreeNode ret = super.applyMerge(modification, currentMeta, version);
+ final var ret = super.applyMerge(modification, currentMeta, version);
enforceCases(ret);
return ret;
}
@Override
protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue,
- final Optional<? extends TreeNode> currentMeta, final Version version) {
- final TreeNode ret = super.applyWrite(modification, newValue, currentMeta, version);
+ final TreeNode currentMeta, final Version version) {
+ final var ret = super.applyWrite(modification, newValue, currentMeta, version);
enforceCases(ret);
return ret;
}
@Override
protected TreeNode applyTouch(final ModifiedNode modification, final TreeNode currentMeta, final Version version) {
- final TreeNode ret = super.applyTouch(modification, currentMeta, version);
+ final var ret = super.applyTouch(modification, currentMeta, version);
enforceCases(ret);
return ret;
}
@Override
protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
- final TreeNode ret = super.applyMerge(modification, currentMeta, version);
+ final var ret = super.applyMerge(modification, currentMeta, version);
enforcer.enforceOnTreeNode(ret);
return ret;
}
@Override
protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue,
- final Optional<? extends TreeNode> currentMeta, final Version version) {
- final TreeNode ret = super.applyWrite(modification, newValue, currentMeta, version);
+ final TreeNode currentMeta, final Version version) {
+ final var ret = super.applyWrite(modification, newValue, currentMeta, version);
enforcer.enforceOnTreeNode(ret);
return ret;
}
@Override
protected TreeNode applyTouch(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
- final TreeNode ret = super.applyTouch(modification, currentMeta, version);
+ final var ret = super.applyTouch(modification, currentMeta, version);
enforcer.enforceOnTreeNode(ret);
return ret;
}
}
@Override
- Optional<? extends TreeNode> apply(final ModifiedNode modification,
- final Optional<? extends TreeNode> storeMeta, final Version version) {
- return AutomaticLifecycleMixin.apply(super::apply, this::applyWrite, emptyNode, modification, storeMeta,
+ Optional<? extends TreeNode> apply(final ModifiedNode modification, final TreeNode currentMeta,
+ final Version version) {
+ return AutomaticLifecycleMixin.apply(super::apply, this::applyWrite, emptyNode, modification, currentMeta,
version);
}
*/
package org.opendaylight.yangtools.yang.data.tree.impl;
+import static java.util.Objects.requireNonNull;
+
import com.google.common.base.MoreObjects;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode;
}
}
- private final RootNode root;
+ private final @NonNull RootNode root;
InMemoryDataTreeCandidate(final YangInstanceIdentifier rootPath, final ModifiedNode modificationRoot,
final TreeNode beforeRoot, final TreeNode afterRoot) {
super(rootPath);
- root = new RootNode(modificationRoot, beforeRoot, afterRoot);
+ root = new RootNode(modificationRoot, requireNonNull(beforeRoot), requireNonNull(afterRoot));
}
@Override
@Override
public String toString() {
- return MoreObjects.toStringHelper(this).add("rootPath", getRootPath())
- .add("rootNode", getRootNode()).toString();
+ return MoreObjects.toStringHelper(this).add("rootPath", getRootPath()).add("rootNode", getRootNode())
+ .toString();
}
}
}
try {
- return resolveModificationStrategy(path).apply(modification, modification.getOriginal(), version);
+ return resolveModificationStrategy(path).apply(modification, modification.original(), version);
} catch (Exception e) {
LOG.error("Could not create snapshot for {}:{}", path, modification, e);
throw e;
* have same version each time this method is called.
*/
final var originalSnapshotRoot = snapshot.getRootNode();
- final var tempRoot = getStrategy().apply(rootNode, Optional.of(originalSnapshotRoot), version);
- checkState(tempRoot.isPresent(), "Data tree root is not present, possibly removed by previous modification");
-
- final var tempTree = new InMemoryDataTreeSnapshot(snapshot.getEffectiveModelContext(), tempRoot.orElseThrow(),
- strategyTree);
- return tempTree.newModification();
+ return new InMemoryDataTreeSnapshot(snapshot.getEffectiveModelContext(),
+ getStrategy().apply(rootNode, originalSnapshotRoot, version)
+ .orElseThrow(() -> new IllegalStateException(
+ "Data tree root is not present, possibly removed by previous modification")), strategyTree)
+ .newModification();
}
Version getVersion() {
this.applyOper = requireNonNull(applyOper);
}
- TreeNode getRootNode() {
+ @NonNull TreeNode getRootNode() {
return rootNode;
}
}
@Override
- Optional<? extends TreeNode> apply(final ModifiedNode modification, final Optional<? extends TreeNode> storeMeta,
+ Optional<? extends TreeNode> apply(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
- return AutomaticLifecycleMixin.apply(super::apply, this::applyWrite, emptyNode, modification, storeMeta,
+ return AutomaticLifecycleMixin.apply(super::apply, this::applyWrite, emptyNode, modification, currentMeta,
version);
}
@Override
protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue,
- final Optional<? extends TreeNode> currentMeta, final Version version) {
+ final TreeNode currentMeta, final Version version) {
final var newValueMeta = TreeNode.of(newValue, version);
if (modification.isEmpty()) {
return newValueMeta;
@SuppressWarnings({ "rawtypes", "unchecked" })
private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
+ for (var mod : modifications) {
+ final var id = mod.getIdentifier();
+ final var cm = meta.childByArg(id);
- for (final ModifiedNode mod : modifications) {
- final PathArgument id = mod.getIdentifier();
- final Optional<? extends TreeNode> cm = meta.findChildByArg(id);
-
- final Optional<? extends TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
+ final var result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
if (result.isPresent()) {
final TreeNode tn = result.orElseThrow();
meta.putChild(tn);
@Override
protected void checkTouchApplicable(final ModificationPath path, final NodeModification modification,
- final Optional<? extends TreeNode> current, final Version version) throws IncorrectDataStructureException {
+ final TreeNode currentMeta, final Version version) throws IncorrectDataStructureException {
throw new IncorrectDataStructureException(path.toInstanceIdentifier(), "Subtree modification is not allowed.");
}
import static java.util.Objects.requireNonNull;
-import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.schema.DistinctNodeContainer;
@Override
protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
- final TreeNode ret = super.applyMerge(modification, currentMeta, version);
+ final var ret = super.applyMerge(modification, currentMeta, version);
enforcer.enforceOnTreeNode(ret);
return ret;
}
@Override
protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue,
- final Optional<? extends TreeNode> currentMeta, final Version version) {
- final TreeNode ret = super.applyWrite(modification, newValue, currentMeta, version);
+ final TreeNode currentMeta, final Version version) {
+ final var ret = super.applyWrite(modification, newValue, currentMeta, version);
enforcer.enforceOnTreeNode(ret);
return ret;
}
@Override
protected TreeNode applyTouch(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
- final TreeNode ret = super.applyTouch(modification, currentMeta, version);
+ final var ret = super.applyTouch(modification, currentMeta, version);
enforcer.enforceOnTreeNode(ret);
return ret;
}
}
@Override
- Optional<? extends TreeNode> apply(final ModifiedNode modification, final Optional<? extends TreeNode> storeMeta,
+ Optional<? extends TreeNode> apply(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
- return AutomaticLifecycleMixin.apply(super::apply, this::applyWrite, emptyNode, modification, storeMeta,
+ return AutomaticLifecycleMixin.apply(super::apply, this::applyWrite, emptyNode, modification, currentMeta,
version);
}
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import java.util.Optional;
+import org.eclipse.jdt.annotation.Nullable;
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.tree.StoreTreeNode;
* <b>Implementation notes</b>
* <ul>
* <li>Implementations MUST expose all nested suboperations which operates on child nodes expose via
- * {@link #findChildByArg(PathArgument)} method.</li>
- * <li>Same suboperations SHOULD be used when invoked via {@link #apply(ModifiedNode, Optional, Version)},
+ * {@link #childByArg(PathArgument)} method.</li>
+ * <li>Same suboperations SHOULD be used when invoked via {@link #apply(ModifiedNode, TreeNode, Version)},
* if applicable.</li>
* <li>There are exactly two base implementations:
* <ul>
/**
* Implementation of this operation must be stateless and must not change state of this object.
*
- * @param modification
- * NodeModification to be applied
- * @param storeMeta
- * Store Metadata Node on which NodeModification should be
- * applied
+ * @param modification NodeModification to be applied
+ * @param currentMeta Store Metadata Node on which NodeModification should be applied
* @param version New subtree version of parent node
- * @return new {@link TreeNode} if operation resulted in updating
- * node, {@link Optional#absent()} if {@link ModifiedNode}
- * resulted in deletion of this node.
- * @throws IllegalArgumentException
- * If it is not possible to apply Operation on provided Metadata
- * node
+ * @return new {@link TreeNode} if operation resulted in updating node, {@link Optional#empty()} if
+ * {@link ModifiedNode} resulted in deletion of this node.
+ * @throws IllegalArgumentException If it is not possible to apply Operation on provided Metadata node
*/
- abstract Optional<? extends TreeNode> apply(ModifiedNode modification, Optional<? extends TreeNode> storeMeta,
+ abstract Optional<? extends TreeNode> apply(ModifiedNode modification, @Nullable TreeNode currentMeta,
Version version);
/**
*
* @param path Path to modification
* @param modification Modification
- * @param current Metadata Node to which modification should be applied
+ * @param currentMeta Metadata Node to which modification should be applied
* @param version Metadata version
* @throws DataValidationFailedException if the modification is not applicable
*/
abstract void checkApplicable(ModificationPath path, NodeModification modification,
- Optional<? extends TreeNode> current, Version version) throws DataValidationFailedException;
+ @Nullable TreeNode currentMeta, Version version) throws DataValidationFailedException;
/**
* Performs a quick structural verification of NodeModification, such as written values / types uses right
/**
* Stage a merge operation into a {@link ModifiedNode} such that it will be processed correctly by
- * {@link #apply(ModifiedNode, Optional, Version)}. This method is the context which is introducing this operation,
+ * {@link #apply(ModifiedNode, TreeNode, Version)}. This method is the context which is introducing this operation,
* and so any overheads are charged to whoever is in control of the access pattern.
*
* @param modification Original modification node
import com.google.common.base.MoreObjects.ToStringHelper;
import java.util.Collection;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
// Internal cache for TreeNodes created as part of validation
private ModificationApplyOperation validatedOp;
- private Optional<? extends TreeNode> validatedCurrent;
+ private @Nullable TreeNode validatedCurrent;
private ValidatedTreeNode validatedNode;
private ModifiedNode(final PathArgument identifier, final @Nullable TreeNode original,
case WRITE -> {
// A WRITE can collapse all of its children
if (!children.isEmpty()) {
- value = schema.apply(this, getOriginal(), version).map(TreeNode::getData).orElse(null);
+ value = schema.apply(this, original(), version).map(TreeNode::getData).orElse(null);
children.clear();
}
return new ModifiedNode(metadataTree.getIdentifier(), requireNonNull(metadataTree), childPolicy);
}
- void setValidatedNode(final ModificationApplyOperation op, final Optional<? extends TreeNode> current,
+ void setValidatedNode(final ModificationApplyOperation op, final @Nullable TreeNode currentMeta,
final Optional<? extends TreeNode> node) {
validatedOp = requireNonNull(op);
- validatedCurrent = requireNonNull(current);
+ validatedCurrent = currentMeta;
validatedNode = new ValidatedTreeNode(node);
}
* {@link #setValidatedNode(ModificationApplyOperation, Optional, Optional)}.
*
* @param op Currently-executing operation
- * @param current Currently-used tree node
+ * @param storeMeta Currently-used tree node
* @return {@code null} if there is a mismatch with previously-validated node (if present) or the result of previous
* validation.
*/
- @Nullable ValidatedTreeNode validatedNode(final ModificationApplyOperation op,
- final Optional<? extends TreeNode> current) {
- return op.equals(validatedOp) && current.equals(validatedCurrent) ? validatedNode : null;
+ @Nullable ValidatedTreeNode validatedNode(final ModificationApplyOperation op, final @Nullable TreeNode storeMeta) {
+ return op.equals(validatedOp) && Objects.equals(storeMeta, validatedCurrent) ? validatedNode : null;
}
}
import static java.util.Objects.requireNonNull;
import java.util.Optional;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.tree.impl.node.TreeNode;
Optional<? extends TreeNode> snapshot = childNode.getSnapshot();
if (snapshot == null) {
// Snapshot is not present, force instantiation
- snapshot = applyOperation.getChildByArg(child).apply(childNode, childNode.getOriginal(), version);
+ snapshot = applyOperation.getChildByArg(child).apply(childNode, childNode.original(), version);
}
return snapshot.map(TreeNode::getData);
Optional<? extends TreeNode> snapshot = modification.getSnapshot();
if (snapshot == null) {
- snapshot = apply(modification.getOriginal(), version);
+ snapshot = apply(modification.original(), version);
}
if (snapshot.isPresent()) {
return applyOperation;
}
- public Optional<? extends TreeNode> apply(final Optional<? extends TreeNode> data, final Version version) {
+ public Optional<? extends TreeNode> apply(final @Nullable TreeNode data, final Version version) {
return applyOperation.apply(modification, data, version);
}
import java.util.List;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.AnydataNode;
return UniqueValidation.of(schemaNode, treeConfig, MinMaxElementsValidation.from(op));
}
- protected static void checkNotConflicting(final ModificationPath path, final TreeNode original,
- final TreeNode current) throws ConflictingModificationAppliedException {
+ protected static final void checkNotConflicting(final ModificationPath path, final @NonNull TreeNode original,
+ final @NonNull TreeNode current) throws ConflictingModificationAppliedException {
checkConflicting(path, original.getVersion().equals(current.getVersion()),
"Node was replaced by other transaction.");
checkConflicting(path, original.getSubtreeVersion().equals(current.getSubtreeVersion()),
@Override
final void checkApplicable(final ModificationPath path, final NodeModification modification,
- final Optional<? extends TreeNode> current, final Version version) throws DataValidationFailedException {
+ final TreeNode currentMeta, final Version version) throws DataValidationFailedException {
switch (modification.getOperation()) {
- case DELETE -> checkDeleteApplicable(modification, current);
- case TOUCH -> checkTouchApplicable(path, modification, current, version);
- case WRITE -> checkWriteApplicable(path, modification, current, version);
- case MERGE -> checkMergeApplicable(path, modification, current, version);
+ case DELETE -> checkDeleteApplicable(modification, currentMeta);
+ case TOUCH -> checkTouchApplicable(path, modification, currentMeta, version);
+ case WRITE -> checkWriteApplicable(path, modification, currentMeta, version);
+ case MERGE -> checkMergeApplicable(path, modification, currentMeta, version);
case NONE -> {
// No-op
}
}
protected void checkMergeApplicable(final ModificationPath path, final NodeModification modification,
- final Optional<? extends TreeNode> current, final Version version) throws DataValidationFailedException {
+ final TreeNode currentMeta, final Version version) throws DataValidationFailedException {
final var orig = modification.original();
- if (orig != null && current.isPresent()) {
+ if (orig != null && currentMeta != null) {
/*
* We need to do conflict detection only and only if the value of leaf changed before two transactions. If
* value of leaf is unchanged between two transactions it should not cause transaction to fail, since result
* of this merge leads to same data.
*/
- final var cur = current.orElseThrow();
- if (!orig.getData().equals(cur.getData())) {
- checkNotConflicting(path, orig, cur);
+ if (!orig.getData().equals(currentMeta.getData())) {
+ checkNotConflicting(path, orig, currentMeta);
}
}
}
*
* @param path Path from current node in TreeNode
* @param modification modification to apply
- * @param current current node in TreeNode for modification to apply
+ * @param currentMeta current node in TreeNode for modification to apply
* @throws DataValidationFailedException when a data dependency conflict is detected
*/
private static void checkWriteApplicable(final ModificationPath path, final NodeModification modification,
- final Optional<? extends TreeNode> current, final Version version) throws DataValidationFailedException {
+ final TreeNode currentMeta, final Version version) throws DataValidationFailedException {
final var original = modification.original();
- if (original != null && current.isPresent()) {
- checkNotConflicting(path, original, current.orElseThrow());
+ if (original != null && currentMeta != null) {
+ checkNotConflicting(path, original, currentMeta);
} else {
checkConflicting(path, original == null, "Node was deleted by other transaction.");
- checkConflicting(path, current.isEmpty(), "Node was created by other transaction.");
+ checkConflicting(path, currentMeta == null, "Node was created by other transaction.");
}
}
private static void checkDeleteApplicable(final NodeModification modification,
- final Optional<? extends TreeNode> current) {
+ final @Nullable TreeNode currentMeta) {
// Delete is always applicable, we do not expose it to subclasses
- if (current.isEmpty()) {
+ if (currentMeta == null) {
LOG.trace("Delete operation turned to no-op on missing node {}", modification);
}
}
@Override
- Optional<? extends TreeNode> apply(final ModifiedNode modification, final Optional<? extends TreeNode> currentMeta,
+ Optional<? extends TreeNode> apply(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
return switch (modification.getOperation()) {
case DELETE -> {
// Deletion of a non-existing node is a no-op, report it as such
- modification.resolveModificationType(currentMeta.isPresent() ? ModificationType.DELETE
+ modification.resolveModificationType(currentMeta != null ? ModificationType.DELETE
: ModificationType.UNMODIFIED);
yield modification.setSnapshot(Optional.empty());
}
case TOUCH -> {
- checkArgument(currentMeta.isPresent(), "Metadata not available for modification %s", modification);
- yield modification.setSnapshot(Optional.of(applyTouch(modification, currentMeta.orElseThrow(),
- version)));
+ if (currentMeta == null) {
+ throw new IllegalArgumentException("Metadata not available for modification " + modification);
+ }
+ yield modification.setSnapshot(Optional.of(applyTouch(modification, currentMeta, version)));
}
case MERGE -> {
final TreeNode result;
- if (currentMeta.isEmpty()) {
+ if (currentMeta == null) {
// This is a slight optimization: a merge on a non-existing node equals to a write. Written data
// structure is usually verified when the transaction is sealed. To preserve correctness, we have
// to run that validation here.
modification.resolveModificationType(ModificationType.WRITE);
- result = applyWrite(modification, modification.getWrittenValue(), currentMeta, version);
+ result = applyWrite(modification, modification.getWrittenValue(), null, version);
fullVerifyStructure(result.getData());
} else {
- result = applyMerge(modification, currentMeta.orElseThrow(), version);
+ result = applyMerge(modification, currentMeta, version);
}
yield modification.setSnapshot(Optional.of(result));
}
case NONE -> {
modification.resolveModificationType(ModificationType.UNMODIFIED);
- yield currentMeta;
+ yield Optional.ofNullable(currentMeta);
}
};
}
* @param version New subtree version of parent node
* @return A sealed TreeNode representing applied operation.
*/
- protected abstract TreeNode applyMerge(ModifiedNode modification, TreeNode currentMeta, Version version);
+ protected abstract @NonNull TreeNode applyMerge(ModifiedNode modification, @NonNull TreeNode currentMeta,
+ Version version);
- protected abstract TreeNode applyWrite(ModifiedNode modification, NormalizedNode newValue,
- Optional<? extends TreeNode> currentMeta, Version version);
+ protected abstract @NonNull TreeNode applyWrite(ModifiedNode modification, NormalizedNode newValue,
+ @Nullable TreeNode currentMeta, Version version);
/**
* Apply a nested operation. Since there may not actually be a nested operation
* @param version New subtree version of parent node
* @return A sealed TreeNode representing applied operation.
*/
- protected abstract TreeNode applyTouch(ModifiedNode modification, TreeNode currentMeta, Version version);
+ protected abstract @NonNull TreeNode applyTouch(ModifiedNode modification, @NonNull TreeNode currentMeta,
+ Version version);
/**
* Checks is supplied {@link NodeModification} is applicable for Subtree Modification.
*
* @param path Path to current node
* @param modification Node modification which should be applied.
- * @param current Current state of data tree
+ * @param currentMeta Current state of data tree
* @throws ConflictingModificationAppliedException If subtree was changed in conflicting way
* @throws org.opendaylight.yangtools.yang.data.tree.api.IncorrectDataStructureException If subtree
* modification is not applicable (e.g. leaf node).
*/
protected abstract void checkTouchApplicable(ModificationPath path, NodeModification modification,
- Optional<? extends TreeNode> current, Version version) throws DataValidationFailedException;
+ @Nullable TreeNode currentMeta, Version version) throws DataValidationFailedException;
/**
* Return the {@link DataSchemaNode}-subclass schema associated with this operation.
import static java.util.Objects.requireNonNull;
import com.google.common.base.MoreObjects.ToStringHelper;
-import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@Override
protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue,
- final Optional<? extends TreeNode> currentMeta, final Version version) {
+ final TreeNode currentMeta, final Version version) {
return TreeNode.of(newValue, version);
}
@Override
protected void checkTouchApplicable(final ModificationPath path, final NodeModification modification,
- final Optional<? extends TreeNode> current, final Version version) throws IncorrectDataStructureException {
+ final TreeNode currentMeta, final Version version) throws IncorrectDataStructureException {
throw new IncorrectDataStructureException(path.toInstanceIdentifier(), "Subtree modification is not allowed.");
}