From d0dfbd6265d9345dd33c6d03d7ea6a85a7e0bfa3 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Wed, 30 Jan 2019 18:12:03 +0100 Subject: [PATCH] Convert MinMaxElementsValidation to ModificationApplyOperation This removes the fragile piggy-backing onto SchemaAwareOperation, as done as part of YANGTOOLS-909 and modifying it to take advantage of DelegatingModificationApplyOperation. This allows us to hide SchemaAwareApplyOperation's checkWriteApplicable(). Change-Id: I804ddb5e4c8b7562bde11994be8b1a5615228d7c JIRA: YANGTOOLS-944 Signed-off-by: Robert Varga --- .../schema/tree/MinMaxElementsValidation.java | 168 ++++++------------ .../data/impl/schema/tree/ModifiedNode.java | 9 +- .../tree/SchemaAwareApplyOperation.java | 6 +- 3 files changed, 65 insertions(+), 118 deletions(-) diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MinMaxElementsValidation.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MinMaxElementsValidation.java index 02335ff676..2c6ec20a20 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MinMaxElementsValidation.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/MinMaxElementsValidation.java @@ -7,8 +7,9 @@ */ package org.opendaylight.yangtools.yang.data.impl.schema.tree; -import com.google.common.base.Preconditions; -import com.google.common.base.Verify; +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; + import java.util.Optional; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -24,7 +25,7 @@ import org.opendaylight.yangtools.yang.model.api.ElementCountConstraintAware; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -final class MinMaxElementsValidation extends SchemaAwareApplyOperation { +final class MinMaxElementsValidation extends DelegatingModificationApplyOperation { private static final Logger LOG = LoggerFactory.getLogger(MinMaxElementsValidation.class); private final SchemaAwareApplyOperation delegate; @@ -33,12 +34,12 @@ final class MinMaxElementsValidation extends SchemaAwareApplyOperation { private MinMaxElementsValidation(final SchemaAwareApplyOperation delegate, final Integer minElements, final Integer maxElements) { - this.delegate = Preconditions.checkNotNull(delegate); + this.delegate = requireNonNull(delegate); this.minElements = minElements != null ? minElements : 0; this.maxElements = maxElements != null ? maxElements : Integer.MAX_VALUE; } - static SchemaAwareApplyOperation from(final SchemaAwareApplyOperation delegate, final DataSchemaNode schema) { + static ModificationApplyOperation from(final SchemaAwareApplyOperation delegate, final DataSchemaNode schema) { if (!(schema instanceof ElementCountConstraintAware)) { return delegate; } @@ -52,35 +53,38 @@ final class MinMaxElementsValidation extends SchemaAwareApplyOperation { return new MinMaxElementsValidation(delegate, constraint.getMinElements(), constraint.getMaxElements()); } - private void validateMinMaxElements(final ModificationPath path, final PathArgument id, - final NormalizedNode data) throws DataValidationFailedException { - final int children = numOfChildrenFromValue(data); - if (minElements > children) { - throw new RequiredElementCountException(path.toInstanceIdentifier(), minElements, maxElements, - children, "%s does not have enough elements (%s), needs at least %s", id, children, minElements); - } - if (maxElements < children) { - throw new RequiredElementCountException(path.toInstanceIdentifier(), minElements, maxElements, - children, "%s has too many elements (%s), can have at most %s", id, children, maxElements); + @Override + ModificationApplyOperation delegate() { + return delegate; + } + + @Override + Optional apply(final ModifiedNode modification, final Optional storeMeta, + final Version version) { + Optional ret = modification.getValidatedNode(this, storeMeta); + if (ret == null) { + // Deal with the result moving on us + ret = delegate.apply(modification, storeMeta, version); + checkChildren(modification.getIdentifier(), numOfChildrenFromTreeNode(ret)); } + return ret; } - private void checkMinMaxElements(final ModificationPath path, final NodeModification nodeMod, + @Override + void checkApplicable(final ModificationPath path, final NodeModification modification, final Optional current, final Version version) throws DataValidationFailedException { - if (!(nodeMod instanceof ModifiedNode)) { - LOG.debug("Could not validate {}, does not implement expected class {}", nodeMod, ModifiedNode.class); + delegate.checkApplicable(path, modification, current, version); + + if (!(modification instanceof ModifiedNode)) { + LOG.debug("Could not validate {}, does not implement expected class {}", modification, ModifiedNode.class); return; } + final ModifiedNode modified = (ModifiedNode) modification; - final ModifiedNode modification = (ModifiedNode) nodeMod; - - // We need to actually perform the operation to get deal with merge in a sane manner. We know the modification + // 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. - final Optional maybeApplied = delegate.apply(modification, current, version); - Verify.verify(maybeApplied.isPresent()); - - final TreeNode applied = maybeApplied.get(); - validateMinMaxElements(path, modification.getIdentifier(), applied.getData()); + final Optional maybeApplied = delegate.apply(modified, current, version); + validateMinMaxElements(path, modified.getIdentifier(), numOfChildrenFromTreeNode(maybeApplied)); // Everything passed. We now have a snapshot of the result node, it would be too bad if we just threw it out. // We know what the result of an apply operation is going to be *if* the following are kept unchanged: @@ -88,107 +92,49 @@ final class MinMaxElementsValidation extends SchemaAwareApplyOperation { // - the schemacontext (therefore, the fact this object is associated with the modification) // // So let's stash the result. We will pick it up during apply operation. - modification.setValidatedNode(this, current, applied); - } - - private static int numOfChildrenFromValue(final NormalizedNode value) { - if (value instanceof NormalizedNodeContainer) { - return ((NormalizedNodeContainer) value).getValue().size(); - } else if (value instanceof UnkeyedListNode) { - return ((UnkeyedListNode) value).getSize(); - } - - throw new IllegalArgumentException(String.format( - "Unexpected type '%s', expected types are NormalizedNodeContainer and UnkeyedListNode", - value.getClass())); - } - - @Override - protected void checkTouchApplicable(final ModificationPath path, final NodeModification modification, - final Optional current, final Version version) throws DataValidationFailedException { - delegate.checkTouchApplicable(path, modification, current, version); - checkMinMaxElements(path, modification, current, version); - } - - @Override - protected void checkMergeApplicable(final ModificationPath path, final NodeModification modification, - final Optional current, final Version version) throws DataValidationFailedException { - delegate.checkMergeApplicable(path, modification, current, version); - checkMinMaxElements(path, modification, current, version); + modified.setValidatedNode(this, current, maybeApplied); } @Override - protected void checkWriteApplicable(final ModificationPath path, final NodeModification modification, - final Optional current, final Version version) throws DataValidationFailedException { - delegate.checkWriteApplicable(path, modification, current, version); - checkMinMaxElements(path, modification, current, version); - } - - @Override - public Optional getChild(final PathArgument child) { - return delegate.getChild(child); - } - - @Override - protected void verifyStructure(final NormalizedNode modification, final boolean verifyChildren) { + void verifyStructure(final NormalizedNode modification, final boolean verifyChildren) { delegate.verifyStructure(modification, verifyChildren); if (verifyChildren) { - final int children = numOfChildrenFromValue(modification); - Preconditions.checkArgument(minElements <= children, - "Node %s does not have enough elements (%s), needs at least %s", modification.getIdentifier(), - children, minElements); - Preconditions.checkArgument(maxElements >= children, - "Node %s has too many elements (%s), can have at most %s", modification.getIdentifier(), children, - maxElements); + checkChildren(modification.getIdentifier(), numOfChildrenFromValue(modification)); } } - @Override - protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta, final Version version) { - final TreeNode validated = modification.getValidatedNode(this, Optional.of(currentMeta)); - if (validated != null) { - return validated; + private void validateMinMaxElements(final ModificationPath path, final PathArgument id, final int children) + throws DataValidationFailedException { + if (minElements > children) { + throw new RequiredElementCountException(path.toInstanceIdentifier(), minElements, maxElements, + children, "%s does not have enough elements (%s), needs at least %s", id, children, minElements); } - - // FIXME: the result moved, make sure we enforce again - return delegate.applyMerge(modification, currentMeta, version); - } - - @Override - protected TreeNode applyTouch(final ModifiedNode modification, final TreeNode currentMeta, final Version version) { - final TreeNode validated = modification.getValidatedNode(this, Optional.of(currentMeta)); - if (validated != null) { - return validated; + if (maxElements < children) { + throw new RequiredElementCountException(path.toInstanceIdentifier(), minElements, maxElements, + children, "%s has too many elements (%s), can have at most %s", id, children, maxElements); } - - // FIXME: the result moved, make sure we enforce again - return delegate.applyTouch(modification, currentMeta, version); } - @Override - protected TreeNode applyWrite(final ModifiedNode modification, final NormalizedNode newValue, - final Optional currentMeta, final Version version) { - final TreeNode validated = modification.getValidatedNode(this, currentMeta); - if (validated != null) { - return validated; - } - - // FIXME: the result moved, make sure we enforce again - return delegate.applyWrite(modification, newValue, currentMeta, version); + private void checkChildren(final PathArgument id, final int children) { + checkArgument(minElements <= children, "Node %s does not have enough elements (%s), needs at least %s", id, + children, minElements); + checkArgument(maxElements >= children, "Node %s has too many elements (%s), can have at most %s", id, children, + maxElements); } - @Override - protected ChildTrackingPolicy getChildPolicy() { - return delegate.getChildPolicy(); + private static int numOfChildrenFromTreeNode(final Optional node) { + return node.isPresent() ? numOfChildrenFromValue(node.get().getData()) : 0; } - @Override - void mergeIntoModifiedNode(final ModifiedNode node, final NormalizedNode value, final Version version) { - delegate.mergeIntoModifiedNode(node, value, version); - } + private static int numOfChildrenFromValue(final NormalizedNode value) { + if (value instanceof NormalizedNodeContainer) { + return ((NormalizedNodeContainer) value).getValue().size(); + } else if (value instanceof UnkeyedListNode) { + return ((UnkeyedListNode) value).getSize(); + } - @Override - void recursivelyVerifyStructure(final NormalizedNode value) { - delegate.recursivelyVerifyStructure(value); + throw new IllegalArgumentException(String.format( + "Unexpected type '%s', expected types are NormalizedNodeContainer and UnkeyedListNode", + value.getClass())); } } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModifiedNode.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModifiedNode.java index 699a785bd8..b4bf65fc0d 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModifiedNode.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/ModifiedNode.java @@ -68,9 +68,9 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode validatedCurrent; - private TreeNode validatedNode; + private Optional validatedNode; private ModifiedNode(final PathArgument identifier, final Optional original, final ChildTrackingPolicy childPolicy) { @@ -348,13 +348,14 @@ final class ModifiedNode extends NodeModification implements StoreTreeNode current, final TreeNode node) { + void setValidatedNode(final ModificationApplyOperation op, final Optional current, + final Optional node) { this.validatedOp = requireNonNull(op); this.validatedCurrent = requireNonNull(current); this.validatedNode = requireNonNull(node); } - TreeNode getValidatedNode(final SchemaAwareApplyOperation op, final Optional current) { + Optional getValidatedNode(final ModificationApplyOperation op, final Optional current) { return op.equals(validatedOp) && current.equals(validatedCurrent) ? validatedNode : null; } } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/SchemaAwareApplyOperation.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/SchemaAwareApplyOperation.java index d50ad5a7c6..43bb4bc5c6 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/SchemaAwareApplyOperation.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/SchemaAwareApplyOperation.java @@ -82,7 +82,7 @@ abstract class SchemaAwareApplyOperation extends ModificationApplyOperation { } } - private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode, + private static ModificationApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode, final DataTreeConfiguration treeConfig) { final List keyDefinition = schemaNode.getKeyDefinition(); final SchemaAwareApplyOperation op; @@ -96,7 +96,7 @@ abstract class SchemaAwareApplyOperation extends ModificationApplyOperation { return MinMaxElementsValidation.from(op, schemaNode); } - private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode, + private static ModificationApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode, final DataTreeConfiguration treeConfig) { final SchemaAwareApplyOperation op; if (schemaNode.isUserOrdered()) { @@ -173,7 +173,7 @@ abstract class SchemaAwareApplyOperation extends ModificationApplyOperation { * @param current current node in TreeNode for modification to apply * @throws DataValidationFailedException when a data dependency conflict is detected */ - protected void checkWriteApplicable(final ModificationPath path, final NodeModification modification, + private static void checkWriteApplicable(final ModificationPath path, final NodeModification modification, final Optional current, final Version version) throws DataValidationFailedException { final Optional original = modification.getOriginal(); if (original.isPresent() && current.isPresent()) { -- 2.36.6