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.collect.ImmutableMap;
+import java.util.Collection;
import java.util.Map;
-
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-
abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
private final Class<? extends NormalizedNode<?, ?>> nodeClass;
@Override
public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
- if (modification.getType() == ModificationType.WRITE) {
-
- }
for (ModifiedNode childModification : modification.getChildren()) {
resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
}
}
- @Override
- protected void checkWriteApplicable(final YangInstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws DataValidationFailedException {
- // FIXME: Implement proper write check for replacement of node container
- // prerequisite is to have transaction chain available for clients
- // otherwise this will break chained writes to same node.
- }
-
@SuppressWarnings("rawtypes")
@Override
protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
- checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
+ checkArgument(nodeClass.isInstance(writtenValue), "Node %s is not of type %s", writtenValue, nodeClass);
checkArgument(writtenValue instanceof NormalizedNodeContainer);
NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version);
- if (Iterables.isEmpty(modification.getChildren())) {
+ if (modification.getChildren().isEmpty()) {
return newValueMeta;
}
* As it turns out, once we materialize the written data, we can share the
* code path with the subtree change. So let's create an unsealed TreeNode
* and run the common parts on it -- which end with the node being sealed.
+ *
+ * FIXME: this code needs to be moved out from the prepare() path and into
+ * the read() and seal() paths. Merging of writes needs to be charged
+ * to the code which originated this, not to the code which is
+ * attempting to make it visible.
*/
final MutableTreeNode mutable = newValueMeta.mutable();
mutable.setSubtreeVersion(version);
return mutateChildren(mutable, dataBuilder, version, modification.getChildren());
}
+ /**
+ * Applies write/remove diff operation for each modification child in modification subtree.
+ * Operation also sets the Data tree references for each Tree Node (Index Node) in meta (MutableTreeNode) structure.
+ *
+ * @param meta MutableTreeNode (IndexTreeNode)
+ * @param data DataBuilder
+ * @param nodeVersion Version of TreeNode
+ * @param modifications modification operations to apply
+ * @return Sealed immutable copy of TreeNode structure with all Data Node references set.
+ */
@SuppressWarnings({ "rawtypes", "unchecked" })
private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
for (ModifiedNode mod : modifications) {
- final PathArgument id = mod.getIdentifier();
+ final YangInstanceIdentifier.PathArgument id = mod.getIdentifier();
final Optional<TreeNode> cm = meta.getChild(id);
Optional<TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
// For Node Containers - merge is same as subtree change - we only replace children.
+ modification.resolveModificationType(ModificationType.SUBTREE_MODIFIED);
return applySubtreeChange(modification, currentMeta, version);
}
final MutableTreeNode newMeta = currentMeta.mutable();
newMeta.setSubtreeVersion(version);
+ /*
+ * The user has issued an empty merge operation. In this case we do not perform
+ * a data tree mutation, do not pass GO, and do not collect useless garbage.
+ */
+ final Collection<ModifiedNode> children = modification.getChildren();
+ if (children.isEmpty()) {
+ newMeta.setData(currentMeta.getData());
+ return newMeta.seal();
+ }
+
@SuppressWarnings("rawtypes")
NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
- return mutateChildren(newMeta, dataBuilder, version, modification.getChildren());
+ return mutateChildren(newMeta, dataBuilder, version, children);
}
@Override
private void checkChildPreconditions(final YangInstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
final TreeNode currentMeta = current.get();
for (NodeModification childMod : modification.getChildren()) {
- final PathArgument childId = childMod.getIdentifier();
+ final YangInstanceIdentifier.PathArgument childId = childMod.getIdentifier();
final Optional<TreeNode> childMeta = currentMeta.getChild(childId);
YangInstanceIdentifier childPath = path.node(childId);
public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
- private final Map<PathArgument, ModificationApplyOperation> childNodes;
+ private final Map<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> childNodes;
- public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
- super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
- ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
+ public ChoiceModificationStrategy(final ChoiceSchemaNode schemaNode) {
+ super(ChoiceNode.class);
+ ImmutableMap.Builder<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
for (ChoiceCaseNode caze : schemaNode.getCases()) {
for (DataSchemaNode cazeChild : caze.getChildNodes()) {
SchemaAwareApplyOperation childNode = SchemaAwareApplyOperation.from(cazeChild);
- child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
+ child.put(new YangInstanceIdentifier.NodeIdentifier(cazeChild.getQName()), childNode);
}
}
childNodes = child.build();
}
@Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+ public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument child) {
return Optional.fromNullable(childNodes.get(child));
}
@Override
@SuppressWarnings("rawtypes")
protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
- return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original);
+ checkArgument(original instanceof ChoiceNode);
+ return ImmutableChoiceNodeBuilder.create((ChoiceNode) original);
}
}
entryStrategy = Optional.<ModificationApplyOperation> of(new ValueNodeModificationStrategy.LeafSetEntryModificationStrategy(schema));
}
+ @Override
+ boolean isOrdered() {
+ return true;
+ }
+
@SuppressWarnings("rawtypes")
@Override
protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
}
@Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeWithValue) {
+ public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+ if (identifier instanceof YangInstanceIdentifier.NodeWithValue) {
return entryStrategy;
}
return Optional.absent();
entryStrategy = Optional.<ModificationApplyOperation> of(new DataNodeContainerModificationStrategy.ListEntryModificationStrategy(schema));
}
+ @Override
+ boolean isOrdered() {
+ return true;
+ }
+
@SuppressWarnings("rawtypes")
@Override
protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
}
@Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeIdentifierWithPredicates) {
+ public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+ if (identifier instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
return entryStrategy;
}
return Optional.absent();
}
@Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeWithValue) {
+ public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+ if (identifier instanceof YangInstanceIdentifier.NodeWithValue) {
return entryStrategy;
}
return Optional.absent();
}
@Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeIdentifierWithPredicates) {
+ public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+ if (identifier instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
return entryStrategy;
}
return Optional.absent();