private final TreeType treeType;
protected AbstractDataNodeContainerModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass, final TreeType treeType) {
- super(nodeClass);
+ super(nodeClass, treeType);
this.schema = Preconditions.checkNotNull(schema,"schema");
this.treeType = Preconditions.checkNotNull(treeType,"treeType");
}
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.schema.tree.ModifiedNodeDoesNotExistException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.MutableTreeNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
abstract class AbstractNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
private final Class<? extends NormalizedNode<?, ?>> nodeClass;
+ private final boolean verifyChildrenStructure;
- protected AbstractNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
+ protected AbstractNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass,
+ final TreeType treeType) {
this.nodeClass = Preconditions.checkNotNull(nodeClass , "nodeClass");
+ this.verifyChildrenStructure = (treeType == TreeType.CONFIGURATION);
}
@SuppressWarnings("rawtypes")
@Override
- void verifyStructure(final NormalizedNode<?, ?> writtenValue) {
+ void verifyStructure(final NormalizedNode<?, ?> writtenValue, final boolean verifyChildren) {
checkArgument(nodeClass.isInstance(writtenValue), "Node %s is not of type %s", writtenValue, nodeClass);
checkArgument(writtenValue instanceof NormalizedNodeContainer);
-
- final NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
- for (final Object child : container.getValue()) {
- checkArgument(child instanceof NormalizedNode);
- final NormalizedNode<?, ?> castedChild = (NormalizedNode<?, ?>) child;
- final Optional<ModificationApplyOperation> childOp = getChild(castedChild.getIdentifier());
- if(childOp.isPresent()) {
- childOp.get().verifyStructure(castedChild);
- } else {
- throw new SchemaValidationFailedException(String.format("Child %s is not valid child according to schema.",
- castedChild.getIdentifier()));
+ if (verifyChildrenStructure && verifyChildren) {
+ final NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
+ for (final Object child : container.getValue()) {
+ checkArgument(child instanceof NormalizedNode);
+ final NormalizedNode<?, ?> castedChild = (NormalizedNode<?, ?>) child;
+ final Optional<ModificationApplyOperation> childOp = getChild(castedChild.getIdentifier());
+ if (childOp.isPresent()) {
+ childOp.get().verifyStructure(castedChild, verifyChildren);
+ } else {
+ throw new SchemaValidationFailedException(String.format(
+ "Child %s is not valid child according to schema.", castedChild.getIdentifier()));
+ }
}
}
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import java.util.Collection;
import java.util.Iterator;
abstract class AbstractReadyIterator {
final Iterator<ModifiedNode> children;
final ModifiedNode node;
+ final ModificationApplyOperation op;
- private AbstractReadyIterator(final ModifiedNode node, final Iterator<ModifiedNode> children) {
+ private AbstractReadyIterator(final ModifiedNode node, final Iterator<ModifiedNode> children,
+ final ModificationApplyOperation operation) {
this.children = Preconditions.checkNotNull(children);
this.node = Preconditions.checkNotNull(node);
+ this.op = Preconditions.checkNotNull(operation);
}
- static AbstractReadyIterator create(final ModifiedNode root) {
- return new RootReadyIterator(root, root.getChildren().iterator());
+ static AbstractReadyIterator create(final ModifiedNode root, final ModificationApplyOperation operation) {
+ return new RootReadyIterator(root, root.getChildren().iterator(), operation);
}
final AbstractReadyIterator process() {
// been modified. If a child
while (children.hasNext()) {
final ModifiedNode child = children.next();
+ final Optional<ModificationApplyOperation> childOperation = op.getChild(child.getIdentifier());
+ Preconditions.checkState(childOperation.isPresent(), "Schema for child %s is not present.",
+ child.getIdentifier());
final Collection<ModifiedNode> grandChildren = child.getChildren();
if (grandChildren.isEmpty()) {
- child.seal();
+
+ child.seal(childOperation.get());
if (child.getOperation() == LogicalOperation.NONE) {
children.remove();
}
} else {
- return new NestedReadyIterator(this, child, grandChildren.iterator());
+ return new NestedReadyIterator(this, child, grandChildren.iterator(), childOperation.get());
}
}
- node.seal();
+ node.seal(op);
// Remove from parent if we have one and this is a no-op
if (node.getOperation() == LogicalOperation.NONE) {
private static final class NestedReadyIterator extends AbstractReadyIterator {
private final AbstractReadyIterator parent;
- private NestedReadyIterator(final AbstractReadyIterator parent, final ModifiedNode node, final Iterator<ModifiedNode> children) {
- super(node, children);
+ private NestedReadyIterator(final AbstractReadyIterator parent, final ModifiedNode node,
+ final Iterator<ModifiedNode> children, final ModificationApplyOperation operation) {
+ super(node, children, operation);
this.parent = Preconditions.checkNotNull(parent);
}
}
private static final class RootReadyIterator extends AbstractReadyIterator {
- private RootReadyIterator(final ModifiedNode node, final Iterator<ModifiedNode> children) {
- super(node, children);
+ private RootReadyIterator(final ModifiedNode node, final Iterator<ModifiedNode> children,
+ final ModificationApplyOperation operation) {
+ super(node, children, operation);
}
@Override
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
import static com.google.common.base.Preconditions.checkArgument;
+
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
}
@Override
- protected final void verifyStructure(final NormalizedNode<?, ?> writtenValue) {
+ protected final void verifyStructure(final NormalizedNode<?, ?> writtenValue, final boolean verifyChildren) {
checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
}
}
@Override
- void verifyStructure(final NormalizedNode<?, ?> modification) {
+ void verifyStructure(final NormalizedNode<?, ?> modification, final boolean verifyChildren) {
throw new IllegalStateException("Schema Context is not available.");
}
private final Map<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> childNodes;
ChoiceModificationStrategy(final ChoiceSchemaNode schemaNode, final TreeType treeType) {
- super(ChoiceNode.class);
+ super(ChoiceNode.class, treeType);
final ImmutableMap.Builder<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
for (final ChoiceCaseNode caze : schemaNode.getCases()) {
final boolean wasRunning = UPDATER.compareAndSet(this, 0, 1);
Preconditions.checkState(wasRunning, "Attempted to seal an already-sealed Data Tree.");
- AbstractReadyIterator current = AbstractReadyIterator.create(rootNode);
+ AbstractReadyIterator current = AbstractReadyIterator.create(rootNode, strategyTree);
do {
current = current.process();
} while (current != null);
}
@Override
- protected void verifyStructure(final NormalizedNode<?, ?> modification) {
- delegate.verifyStructure(modification);
+ protected void verifyStructure(final NormalizedNode<?, ?> modification, final boolean verifyChildren) {
+ delegate.verifyStructure(modification, verifyChildren);
}
@Override
/**
*
- * Performs structural verification of NodeModification, such as writen values / types
- * uses right structural elements.
+ * Performs structural verification of NodeModification, such as writen values / types uses
+ * right structural elements.
*
- * @param modification to be verified.
- * @throws IllegalArgumentException If provided NodeModification does not adhere to the structure.
+ * @param modification data to be verified.
+ * @param verifyChildren true if structure verification should be run against children.
+ * @throws IllegalArgumentException If provided NodeModification does not adhere to the
+ * structure.
*/
- abstract void verifyStructure(NormalizedNode<?, ?> modification) throws IllegalArgumentException;
+ abstract void verifyStructure(NormalizedNode<?, ?> modification, boolean verifyChildren)
+ throws IllegalArgumentException;
/**
* Return the tracking policy for this node's children.
}
/**
- * Seal the modification node.
+ * Seal the modification node and prune any children which has not been modified.
+ *
+ * @param schema
*/
- void seal() {
+ void seal(final ModificationApplyOperation schema) {
clearSnapshot();
// A TOUCH node without any children is a no-op
- if (operation == LogicalOperation.TOUCH && children.isEmpty()) {
- updateOperationType(LogicalOperation.NONE);
+ switch (operation) {
+ case TOUCH:
+ if (children.isEmpty()) {
+ updateOperationType(LogicalOperation.NONE);
+ }
+ break;
+ case WRITE:
+ schema.verifyStructure(value, true);
+ break;
+ default:
+ break;
}
}
void write(final NormalizedNode<?, ?> value) {
modification.write(value);
- applyOperation.verifyStructure(value);
+ /**
+ * Fast validation of structure, full validation on written data will be run during seal.
+ */
+ applyOperation.verifyStructure(value, false);
}
private void recursiveMerge(final NormalizedNode<?,?> data) {
void merge(final NormalizedNode<?, ?> data) {
/*
- * A merge operation will end up overwriting parts of the tree, retaining others.
- * We want to make sure we do not validate the complete resulting structure, but
- * rather just what was written. In order to do that, we first pretend the data
- * was written, run verification and then perform the merge -- with the explicit
- * assumption that adding the newly-validated data with the previously-validated
- * data will not result in invalid data.
+ * A merge operation will end up overwriting parts of the tree, retaining others. We want to
+ * make sure we do not validate the complete resulting structure, but rather just what was
+ * written. In order to do that, we first pretend the data was written, run verification and
+ * then perform the merge -- with the explicit assumption that adding the newly-validated
+ * data with the previously-validated data will not result in invalid data.
+ *
+ * FIXME: Should be this moved to recursive merge and run for each node?
*/
- applyOperation.verifyStructure(data);
+ applyOperation.verifyStructure(data, false);
recursiveMerge(data);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema, final TreeType treeType) {
- super((Class) LeafSetNode.class);
+ super((Class) LeafSetNode.class, treeType);
entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
}
private final Optional<ModificationApplyOperation> entryStrategy;
OrderedMapModificationStrategy(final ListSchemaNode schema, final TreeType treeType) {
- super(OrderedMapNode.class);
+ super(OrderedMapNode.class, treeType);
entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema, treeType));
}
}
@Override
- final void verifyStructure(final NormalizedNode<?, ?> modification) throws IllegalArgumentException {
- getDelegate().verifyStructure(modification);
+ final void verifyStructure(final NormalizedNode<?, ?> modification, final boolean verifyChildren)
+ throws IllegalArgumentException {
+ getDelegate().verifyStructure(modification, verifyChildren);
}
@Override
}
@Override
- protected void verifyStructure(final NormalizedNode<?, ?> writtenValue) {
+ protected void verifyStructure(final NormalizedNode<?, ?> writtenValue, final boolean verifyChildren) {
}
@SuppressWarnings({ "unchecked", "rawtypes" })
UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema, final TreeType treeType) {
- super((Class) LeafSetNode.class);
+ super((Class) LeafSetNode.class, treeType);
entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
}
private final Optional<ModificationApplyOperation> entryStrategy;
UnorderedMapModificationStrategy(final ListSchemaNode schema, final TreeType treeType) {
- super(MapNode.class);
+ super(MapNode.class, treeType);
entryStrategy = Optional.<ModificationApplyOperation>of(new ListEntryModificationStrategy(schema, treeType));
}
inMemoryDataTree.setSchemaContext(schemaContext);
final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
modificationTree.write(TestModel.TEST_PATH, createFooTestContainerNode());
-
+ modificationTree.ready();
inMemoryDataTree.validate(modificationTree);
final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
inMemoryDataTree.commit(prepare);
inMemoryDataTree.setSchemaContext(schemaContext);
final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
modificationTree.write(TestModel.TEST_PATH, createBarTestContainerNode());
-
+ modificationTree.ready();
inMemoryDataTree.validate(modificationTree);
final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
inMemoryDataTree.commit(prepare);
final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
modificationTree.write(ii, choice1);
-
+ modificationTree.ready();
inMemoryDataTree.validate(modificationTree);
final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
inMemoryDataTree.commit(prepare);