/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
*
- * This program and the accompanying materials are made available under the terms of the Eclipse
- * Public License v1.0 which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+ * This program and the accompanying materials are made available under the
+ * 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.impl.schema.tree;
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.base.Verify;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
}
- private static int findChildrenBefore(final Optional<TreeNode> current) {
- if (current.isPresent()) {
- return numOfChildrenFromValue(current.get().getData());
- } else {
- return 0;
+ private void validateMinMaxElements(final YangInstanceIdentifier path, final PathArgument id,
+ final NormalizedNode<?, ?> data) throws DataValidationFailedException {
+ final int children = numOfChildrenFromValue(data);
+ if (minElements != null && minElements > children) {
+ throw new DataValidationFailedException(path, String.format(
+ "%s does not have enough elements (%s), needs at least %s", id,
+ children, minElements));
}
- }
-
- private static int findChildrenAfter(final ModifiedNode modification) {
- if (modification.getWrittenValue() != null) {
- return numOfChildrenFromValue(modification.getWrittenValue());
- } else {
- return 0;
+ if (maxElements != null && maxElements < children) {
+ throw new DataValidationFailedException(path, String.format(
+ "%s has too many elements (%s), can have at most %s", id, children,
+ maxElements));
}
}
private void checkMinMaxElements(final YangInstanceIdentifier path, final NodeModification nodeMod,
- final Optional<TreeNode> current) throws DataValidationFailedException {
+ final Optional<TreeNode> current, final Version version) throws DataValidationFailedException {
if (!(nodeMod instanceof ModifiedNode)) {
LOG.debug("Could not validate {}, does not implement expected class {}", nodeMod, ModifiedNode.class);
return;
}
+
final ModifiedNode modification = (ModifiedNode) nodeMod;
- final int childrenBefore = findChildrenBefore(current);
+ // We need to actually perform the operation to get deal with merge in a sane manner. We know the modification
+ // is immutable, so the result of validation will probably not change.
+ final Optional<TreeNode> maybeApplied = delegate.apply(modification, current, version);
+ Verify.verify(maybeApplied.isPresent());
- final int childrenAfter = findChildrenAfter(modification);
+ final TreeNode applied = maybeApplied.get();
+ validateMinMaxElements(path, modification.getIdentifier(), applied.getData());
- final int childrenTotal = childrenBefore + childrenAfter + numOfChildrenFromChildMods(modification, current);
- if (minElements != null && minElements > childrenTotal) {
- throw new DataValidationFailedException(path, String.format(
- "%s does not have enough elements (%s), needs at least %s", modification.getIdentifier(),
- childrenTotal, minElements));
- }
- if (maxElements != null && maxElements < childrenTotal) {
- throw new DataValidationFailedException(path, String.format(
- "%s has too many elements (%s), can have at most %s", modification.getIdentifier(), childrenTotal,
- maxElements));
- }
+ // 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:
+ // - the 'current' node
+ // - 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) {
value.getClass()));
}
- private static int numOfChildrenFromChildMods(final ModifiedNode modification, final Optional<TreeNode> current) {
- int result = 0;
- for (final ModifiedNode modChild : modification.getChildren()) {
- switch (modChild.getOperation()) {
- case WRITE:
- result++;
- break;
- case MERGE:
- if (!current.isPresent()) {
- result++;
- }
- break;
- case DELETE:
- result--;
- break;
- case NONE:
- case TOUCH:
- // NOOP
- break;
- default:
- throw new IllegalArgumentException("Unsupported operation type: " + modChild.getOperation());
- }
- }
- return result;
- }
-
@Override
protected void checkTouchApplicable(final YangInstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws DataValidationFailedException {
- delegate.checkTouchApplicable(path, modification, current);
- checkMinMaxElements(path, modification, current);
+ final Optional<TreeNode> current, final Version version) throws DataValidationFailedException {
+ delegate.checkTouchApplicable(path, modification, current, version);
+ checkMinMaxElements(path, modification, current, version);
}
@Override
protected void checkMergeApplicable(final YangInstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws DataValidationFailedException {
- delegate.checkMergeApplicable(path, modification, current);
- checkMinMaxElements(path, modification, current);
+ final Optional<TreeNode> current, final Version version) throws DataValidationFailedException {
+ delegate.checkMergeApplicable(path, modification, current, version);
+ checkMinMaxElements(path, modification, current, version);
}
@Override
protected void checkWriteApplicable(final YangInstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws DataValidationFailedException {
- delegate.checkWriteApplicable(path, modification, current);
- checkMinMaxElements(path, modification, current);
+ final Optional<TreeNode> current, final Version version) throws DataValidationFailedException {
+ delegate.checkWriteApplicable(path, modification, current, version);
+ checkMinMaxElements(path, modification, current, version);
}
-
@Override
public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
return delegate.getChild(child);
}
@Override
- void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
- delegate.verifyStructure(modification);
+ protected void verifyStructure(final NormalizedNode<?, ?> modification, final boolean verifyChildren) {
+ delegate.verifyStructure(modification, verifyChildren);
}
@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;
+ }
+
+ // 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;
+ }
+
+ // FIXME: the result moved, make sure we enforce again
return delegate.applyTouch(modification, currentMeta, version);
}
@Override
protected TreeNode applyWrite(final ModifiedNode modification, final Optional<TreeNode> 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, currentMeta, version);
}
@Override
- protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
- delegate.verifyWrittenStructure(writtenValue);
+ protected ChildTrackingPolicy getChildPolicy() {
+ return delegate.getChildPolicy();
}
@Override
- protected ChildTrackingPolicy getChildPolicy() {
- return delegate.getChildPolicy();
+ void mergeIntoModifiedNode(final ModifiedNode node, final NormalizedNode<?, ?> value, final Version version) {
+ delegate.mergeIntoModifiedNode(node, value, version);
+ }
+
+ @Override
+ void recursivelyVerifyStructure(NormalizedNode<?, ?> value) {
+ delegate.recursivelyVerifyStructure(value);
}
}