From 2107a0dea241ea8ffce8a2950a5e6b5799dcda66 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Wed, 21 May 2014 13:55:41 +0200 Subject: [PATCH] BUG-509: break up SchemaAwareApplyOperation This patch breaks up the SchemaAwareApplyOperation class by moving its abstract subclasses out, allowing their subclasses to be retained within them. This will allow to better understand the relationships between the classes. Change-Id: I0acf48fa7c38d600fe38a8ec9951858f46be18e0 Signed-off-by: Robert Varga --- ...DataNodeContainerModificationStrategy.java | 154 +++++ ...izedNodeContainerModificationStrategy.java | 328 ++++++++++ .../tree/data/SchemaAwareApplyOperation.java | 569 ++---------------- .../data/ValueNodeModificationStrategy.java | 85 +++ .../data/SchemaAwareApplyOperationRoot.java | 2 +- 5 files changed, 609 insertions(+), 529 deletions(-) create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/DataNodeContainerModificationStrategy.java create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/DataNodeContainerModificationStrategy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/DataNodeContainerModificationStrategy.java new file mode 100644 index 0000000000..aea070c120 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/DataNodeContainerModificationStrategy.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2014 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 + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ExecutionException; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +abstract class DataNodeContainerModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final T schema; + private final LoadingCache childCache = CacheBuilder.newBuilder() + .build(CacheLoader.from(new Function() { + + @Override + public ModificationApplyOperation apply(final PathArgument identifier) { + if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) { + return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier); + } + + DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType()); + if (child == null) { + return null; + } + return from(child); + } + })); + + protected DataNodeContainerModificationStrategy(final T schema, + final Class> nodeClass) { + super(nodeClass); + this.schema = schema; + } + + protected T getSchema() { + return schema; + } + + @Override + public Optional getChild(final PathArgument identifier) { + try { + return Optional. fromNullable(childCache.get(identifier)); + } catch (ExecutionException e) { + return Optional.absent(); + } + } + + @Override + @SuppressWarnings("rawtypes") + protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode original); + + @Override + public String toString() { + return getClass().getSimpleName() + " [" + schema + "]"; + } + + public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy { + + protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) { + super(createAugmentProxy(schema,resolved), AugmentationNode.class); + } + + @Override + @SuppressWarnings("rawtypes") + protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof AugmentationNode); + return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original); + } + + + private static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) { + Set realChildSchemas = new HashSet<>(); + for(DataSchemaNode augChild : schema.getChildNodes()) { + realChildSchemas.add(resolved.getDataChildByName(augChild.getQName())); + } + return new AugmentationSchemaProxy(schema, realChildSchemas); + } + } + + public static class ContainerModificationStrategy extends DataNodeContainerModificationStrategy { + + public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) { + super(schemaNode, ContainerNode.class); + } + + @Override + @SuppressWarnings("rawtypes") + protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof ContainerNode); + return ImmutableContainerNodeBuilder.create((ContainerNode) original); + } + } + + public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy { + + protected ListEntryModificationStrategy(final ListSchemaNode schema) { + super(schema, MapEntryNode.class); + } + + @Override + @SuppressWarnings("rawtypes") + protected final DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof MapEntryNode); + return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original); + } + } + + public static class UnkeyedListItemModificationStrategy extends DataNodeContainerModificationStrategy { + + public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) { + super(schemaNode, UnkeyedListEntryNode.class); + } + + @Override + @SuppressWarnings("rawtypes") + protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof UnkeyedListEntryNode); + return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original); + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java new file mode 100644 index 0000000000..7ab840e0e0 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2014 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 + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ListEntryModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafSetEntryModificationStrategy; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +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.api.schema.NormalizedNodeContainer; +import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder; +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.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.primitives.UnsignedLong; + +abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation { + + private final Class> nodeClass; + + protected NormalizedNodeContainerModificationStrategy(final Class> nodeClass) { + this.nodeClass = nodeClass; + } + + @Override + public void verifyStructure(final NodeModification modification) throws IllegalArgumentException { + if (modification.getModificationType() == ModificationType.WRITE) { + + } + for (NodeModification childModification : modification.getModifications()) { + resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification); + } + } + + @Override + protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + // 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(writtenValue instanceof NormalizedNodeContainer); + + NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue; + for (Object child : container.getValue()) { + checkArgument(child instanceof NormalizedNode); + + /* + * FIXME: fail-fast semantics: + * + * We can validate the data structure here, aborting the commit + * before it ever progresses to being committed. + */ + } + } + + @Override + protected StoreMetadataNode applyWrite(final NodeModification modification, + final Optional currentMeta, final UnsignedLong subtreeVersion) { + + NormalizedNode newValue = modification.getWrittenValue(); + + final UnsignedLong nodeVersion; + if (currentMeta.isPresent()) { + nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion()); + } else { + nodeVersion = subtreeVersion; + } + + final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion); + if (!modification.hasAdditionalModifications()) { + return newValueMeta; + } + + @SuppressWarnings("rawtypes") + NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue); + StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(nodeVersion, dataBuilder) // + .setSubtreeVersion(subtreeVersion); + + return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion); + } + + @Override + protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta, + final UnsignedLong subtreeVersion) { + // For Node Containers - merge is same as subtree change - we only replace children. + return applySubtreeChange(modification, currentMeta, subtreeVersion); + } + + @Override + public StoreMetadataNode applySubtreeChange(final NodeModification modification, + final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) { + // Bump subtree version to its new target + final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion()); + + @SuppressWarnings("rawtypes") + NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData()); + StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(dataBuilder, currentMeta) + .setIdentifier(modification.getIdentifier()) + .setSubtreeVersion(updatedSubtreeVersion); + + return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion); + } + + private StoreMetadataNode mutateChildren(final Iterable modifications, final StoreMetadataNode meta, + final StoreNodeCompositeBuilder builder, final UnsignedLong nodeVersion) { + + for (NodeModification mod : modifications) { + final PathArgument id = mod.getIdentifier(); + final Optional cm = meta.getChild(id); + + Optional result = resolveChildOperation(id).apply(mod, cm, nodeVersion); + if (result.isPresent()) { + builder.add(result.get()); + } else { + builder.remove(id); + } + } + + return builder.build(); + } + + @Override + protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction."); + checkChildPreconditions(path,modification,current); + + } + + private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional current) throws DataPreconditionFailedException { + StoreMetadataNode currentMeta = current.get(); + for (NodeModification childMod : modification.getModifications()) { + PathArgument childId = childMod.getIdentifier(); + Optional childMeta = currentMeta.getChild(childId); + InstanceIdentifier childPath = StoreUtils.append(path, childId); + resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta); + } + } + + @Override + protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + if(current.isPresent()) { + checkChildPreconditions(path,modification,current); + } + } + + @SuppressWarnings("rawtypes") + protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode original); + + public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Map childNodes; + + public ChoiceModificationStrategy(final ChoiceNode schemaNode) { + super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class); + ImmutableMap.Builder child = ImmutableMap.builder(); + + for (ChoiceCaseNode caze : schemaNode.getCases()) { + for (DataSchemaNode cazeChild : caze.getChildNodes()) { + SchemaAwareApplyOperation childNode = from(cazeChild); + child.put(new NodeIdentifier(cazeChild.getQName()), childNode); + } + } + childNodes = child.build(); + } + + @Override + public Optional getChild(final 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); + } + } + + public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Optional entryStrategy; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) { + super((Class) LeafSetNode.class); + entryStrategy = Optional. of(new LeafSetEntryModificationStrategy(schema)); + } + + @SuppressWarnings("rawtypes") + @Override + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof OrderedLeafSetNode); + return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode) original); + } + + @Override + public Optional getChild(final PathArgument identifier) { + if (identifier instanceof NodeWithValue) { + return entryStrategy; + } + return Optional.absent(); + } + } + + public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Optional entryStrategy; + + protected OrderedMapModificationStrategy(final ListSchemaNode schema) { + super(OrderedMapNode.class); + entryStrategy = Optional. of(new ListEntryModificationStrategy(schema)); + } + + @SuppressWarnings("rawtypes") + @Override + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof OrderedMapNode); + return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original); + } + + @Override + public Optional getChild(final PathArgument identifier) { + if (identifier instanceof NodeIdentifierWithPredicates) { + return entryStrategy; + } + return Optional.absent(); + } + + @Override + public String toString() { + return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]"; + } + } + + public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Optional entryStrategy; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) { + super((Class) LeafSetNode.class); + entryStrategy = Optional. of(new LeafSetEntryModificationStrategy(schema)); + } + + @SuppressWarnings("rawtypes") + @Override + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof LeafSetNode); + return ImmutableLeafSetNodeBuilder.create((LeafSetNode) original); + } + + @Override + public Optional getChild(final PathArgument identifier) { + if (identifier instanceof NodeWithValue) { + return entryStrategy; + } + return Optional.absent(); + } + } + + public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Optional entryStrategy; + + protected UnorderedMapModificationStrategy(final ListSchemaNode schema) { + super(MapNode.class); + entryStrategy = Optional. of(new ListEntryModificationStrategy(schema)); + } + + @SuppressWarnings("rawtypes") + @Override + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof MapNode); + return ImmutableMapNodeBuilder.create((MapNode) original); + } + + @Override + public Optional getChild(final PathArgument identifier) { + if (identifier instanceof NodeIdentifierWithPredicates) { + return entryStrategy; + } + return Optional.absent(); + } + + @Override + public String toString() { + return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]"; + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java index 620c00791c..7afc12caab 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java @@ -9,49 +9,25 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; import static com.google.common.base.Preconditions.checkArgument; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutionException; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException; import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; -import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ContainerModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.UnkeyedListItemModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.ChoiceModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.OrderedLeafSetModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.OrderedMapModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.UnorderedLeafSetModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafModificationStrategy; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; -import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; -import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; -import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; -import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; -import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; -import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; -import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode; -import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode; -import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder; -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.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy; import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; -import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; import org.opendaylight.yangtools.yang.model.api.ChoiceNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; @@ -59,17 +35,15 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Preconditions; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableMap; import com.google.common.primitives.UnsignedLong; abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { + private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareApplyOperation.class); public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) { if (schemaNode instanceof ContainerSchemaNode) { @@ -86,6 +60,26 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass()); } + public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree, + final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) { + AugmentationSchema augSchema = null; + + allAugments: + for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) { + for (DataSchemaNode child : potential.getChildNodes()) { + if (identifier.getPossibleChildNames().contains(child.getQName())) { + augSchema = potential; + break allAugments; + } + } + } + + if (augSchema != null) { + return new DataNodeContainerModificationStrategy.AugmentationModificationStrategy(augSchema, resolvedTree); + } + return null; + } + private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) { List keyDefinition = schemaNode.getKeyDefinition(); if (keyDefinition == null || keyDefinition.isEmpty()) { @@ -95,7 +89,7 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { return new OrderedMapModificationStrategy(schemaNode); } - return new UnorderedMapModificationStrategy(schemaNode); + return new NormalizedNodeContainerModificationStrategy.UnorderedMapModificationStrategy(schemaNode); } private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) { @@ -106,25 +100,9 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { } } - - public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree, - final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) { - AugmentationSchema augSchema = null; - - allAugments: - for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) { - for (DataSchemaNode child : potential.getChildNodes()) { - if (identifier.getPossibleChildNames().contains(child.getQName())) { - augSchema = potential; - break allAugments; - } - } - } - - if (augSchema != null) { - return new AugmentationModificationStrategy(augSchema, resolvedTree); - } - return null; + private static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException { + checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction."); + checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction"); } protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) { @@ -140,8 +118,6 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { } } - protected abstract void verifyWrittenStructure(NormalizedNode writtenValue); - @Override public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional current) throws DataPreconditionFailedException { switch (modification.getModificationType()) { @@ -189,15 +165,11 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { } } - protected static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException { - checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction."); - checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction"); - } - - protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification, - final Optional current) throws DataPreconditionFailedException; - private void checkDeleteApplicable(final NodeModification modification, final Optional current) { + // Delete is always applicable, we do not expose it to subclasses + if (current.isPresent()) { + LOG.trace("Delete operation turned to no-op on missing node {}", modification); + } } @Override @@ -234,400 +206,10 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification, StoreMetadataNode currentMeta, UnsignedLong subtreeVersion); - public static abstract class ValueNodeModificationStrategy extends SchemaAwareApplyOperation { - - private final T schema; - private final Class> nodeClass; - - protected ValueNodeModificationStrategy(final T schema, final Class> nodeClass) { - super(); - this.schema = schema; - this.nodeClass = nodeClass; - } - - @Override - protected void verifyWrittenStructure(final NormalizedNode writtenValue) { - checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass); - } - - @Override - public Optional getChild(final PathArgument child) { - throw new UnsupportedOperationException("Node " + schema.getPath() - + "is leaf type node. Child nodes not allowed"); - } - - @Override - protected StoreMetadataNode applySubtreeChange(final NodeModification modification, - final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) { - throw new UnsupportedOperationException("Node " + schema.getPath() - + "is leaf type node. Subtree change is not allowed."); - } - - @Override - protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta, - final UnsignedLong subtreeVersion) { - return applyWrite(modification, Optional.of(currentMeta), subtreeVersion); - } - - @Override - protected StoreMetadataNode applyWrite(final NodeModification modification, - final Optional currentMeta, final UnsignedLong subtreeVersion) { - return StoreMetadataNode.builder(subtreeVersion).setSubtreeVersion(subtreeVersion) - .setData(modification.getWrittenValue()).build(); - } - - @Override - protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { - throw new DataPreconditionFailedException(path, "Subtree modification is not allowed."); - } - - } - - public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy { - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) { - super(schema, (Class) LeafSetEntryNode.class); - } - } - - public static class LeafModificationStrategy extends ValueNodeModificationStrategy { - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected LeafModificationStrategy(final LeafSchemaNode schema) { - super(schema, (Class) LeafNode.class); - } - } - - public static abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation { - - private final Class> nodeClass; - - protected NormalizedNodeContainerModificationStrategy(final Class> nodeClass) { - this.nodeClass = nodeClass; - } - - @Override - public void verifyStructure(final NodeModification modification) throws IllegalArgumentException { - if (modification.getModificationType() == ModificationType.WRITE) { - - } - for (NodeModification childModification : modification.getModifications()) { - resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification); - } - } - - @Override - protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { - // 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(writtenValue instanceof NormalizedNodeContainer); - - NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue; - for (Object child : container.getValue()) { - checkArgument(child instanceof NormalizedNode); - - /* - * FIXME: fail-fast semantics: - * - * We can validate the data structure here, aborting the commit - * before it ever progresses to being committed. - */ - } - } - - @Override - protected StoreMetadataNode applyWrite(final NodeModification modification, - final Optional currentMeta, final UnsignedLong subtreeVersion) { - - NormalizedNode newValue = modification.getWrittenValue(); - - final UnsignedLong nodeVersion; - if (currentMeta.isPresent()) { - nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion()); - } else { - nodeVersion = subtreeVersion; - } - - final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion); - if (!modification.hasAdditionalModifications()) { - return newValueMeta; - } - - @SuppressWarnings("rawtypes") - NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue); - StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(nodeVersion, dataBuilder) // - .setSubtreeVersion(subtreeVersion); - - return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion); - } - - @Override - protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta, - final UnsignedLong subtreeVersion) { - // For Node Containers - merge is same as subtree change - we only replace children. - return applySubtreeChange(modification, currentMeta, subtreeVersion); - } - - @Override - public StoreMetadataNode applySubtreeChange(final NodeModification modification, - final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) { - // Bump subtree version to its new target - final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion()); - - @SuppressWarnings("rawtypes") - NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData()); - StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(dataBuilder, currentMeta) - .setIdentifier(modification.getIdentifier()) - .setSubtreeVersion(updatedSubtreeVersion); - - return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion); - } - - private StoreMetadataNode mutateChildren(final Iterable modifications, final StoreMetadataNode meta, - final StoreNodeCompositeBuilder builder, final UnsignedLong nodeVersion) { - - for (NodeModification mod : modifications) { - final PathArgument id = mod.getIdentifier(); - final Optional cm = meta.getChild(id); - - Optional result = resolveChildOperation(id).apply(mod, cm, nodeVersion); - if (result.isPresent()) { - builder.add(result.get()); - } else { - builder.remove(id); - } - } - - return builder.build(); - } - - @Override - protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { - checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction."); - checkChildPreconditions(path,modification,current); - - } - - private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional current) throws DataPreconditionFailedException { - StoreMetadataNode currentMeta = current.get(); - for (NodeModification childMod : modification.getModifications()) { - PathArgument childId = childMod.getIdentifier(); - Optional childMeta = currentMeta.getChild(childId); - InstanceIdentifier childPath = StoreUtils.append(path, childId); - resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta); - } - } - - @Override - protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { - if(current.isPresent()) { - checkChildPreconditions(path,modification,current); - } - } - - @SuppressWarnings("rawtypes") - protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode original); - } - - public static abstract class DataNodeContainerModificationStrategy extends NormalizedNodeContainerModificationStrategy { - - private final T schema; - private final LoadingCache childCache = CacheBuilder.newBuilder() - .build(CacheLoader.from(new Function() { - - @Override - public ModificationApplyOperation apply(final PathArgument identifier) { - if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) { - return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier); - } - - DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType()); - if (child == null) { - return null; - } - return from(child); - } - })); - - protected DataNodeContainerModificationStrategy(final T schema, - final Class> nodeClass) { - super(nodeClass); - this.schema = schema; - } - - protected T getSchema() { - return schema; - } - - @Override - public Optional getChild(final PathArgument identifier) { - try { - return Optional. fromNullable(childCache.get(identifier)); - } catch (ExecutionException e) { - return Optional.absent(); - } - } - - @Override - @SuppressWarnings("rawtypes") - protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode original); - - @Override - public String toString() { - return getClass().getSimpleName() + " [" + schema + "]"; - } - - } - - public static class ContainerModificationStrategy extends DataNodeContainerModificationStrategy { - - public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) { - super(schemaNode, ContainerNode.class); - } - - @Override - @SuppressWarnings("rawtypes") - protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof ContainerNode); - return ImmutableContainerNodeBuilder.create((ContainerNode) original); - } - } - - public static class UnkeyedListItemModificationStrategy extends DataNodeContainerModificationStrategy { - - public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) { - super(schemaNode, UnkeyedListEntryNode.class); - } - - @Override - @SuppressWarnings("rawtypes") - protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof UnkeyedListEntryNode); - return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original); - } - } - - public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy { - - protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) { - super(createAugmentProxy(schema,resolved), AugmentationNode.class); - } - - @Override - @SuppressWarnings("rawtypes") - protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof AugmentationNode); - return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original); - } - } - - public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy { - - private final Map childNodes; - - public ChoiceModificationStrategy(final ChoiceNode schemaNode) { - super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class); - ImmutableMap.Builder child = ImmutableMap.builder(); - - for (ChoiceCaseNode caze : schemaNode.getCases()) { - for (DataSchemaNode cazeChild : caze.getChildNodes()) { - SchemaAwareApplyOperation childNode = from(cazeChild); - child.put(new NodeIdentifier(cazeChild.getQName()), childNode); - } - } - childNodes = child.build(); - } - - @Override - public Optional getChild(final 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); - } - } - - public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy { - - protected ListEntryModificationStrategy(final ListSchemaNode schema) { - super(schema, MapEntryNode.class); - } - - @Override - @SuppressWarnings("rawtypes") - protected final DataContainerNodeBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof MapEntryNode); - return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original); - } - } - - public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy { - - private final Optional entryStrategy; - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) { - super((Class) LeafSetNode.class); - entryStrategy = Optional. of(new LeafSetEntryModificationStrategy(schema)); - } - - @SuppressWarnings("rawtypes") - @Override - protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof LeafSetNode); - return ImmutableLeafSetNodeBuilder.create((LeafSetNode) original); - } - - @Override - public Optional getChild(final PathArgument identifier) { - if (identifier instanceof NodeWithValue) { - return entryStrategy; - } - return Optional.absent(); - } - } - - public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy { - - private final Optional entryStrategy; - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) { - super((Class) LeafSetNode.class); - entryStrategy = Optional. of(new LeafSetEntryModificationStrategy(schema)); - } - - @SuppressWarnings("rawtypes") - @Override - protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof OrderedLeafSetNode); - return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode) original); - } + protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification, + final Optional current) throws DataPreconditionFailedException; - @Override - public Optional getChild(final PathArgument identifier) { - if (identifier instanceof NodeWithValue) { - return entryStrategy; - } - return Optional.absent(); - } - } + protected abstract void verifyWrittenStructure(NormalizedNode writtenValue); public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation { @@ -673,75 +255,6 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { final Optional current) throws DataPreconditionFailedException { throw new DataPreconditionFailedException(path, "Subtree modification is not allowed."); } - - } - - public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy { - - private final Optional entryStrategy; - - protected UnorderedMapModificationStrategy(final ListSchemaNode schema) { - super(MapNode.class); - entryStrategy = Optional. of(new ListEntryModificationStrategy(schema)); - } - - @SuppressWarnings("rawtypes") - @Override - protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof MapNode); - return ImmutableMapNodeBuilder.create((MapNode) original); - } - - @Override - public Optional getChild(final PathArgument identifier) { - if (identifier instanceof NodeIdentifierWithPredicates) { - return entryStrategy; - } - return Optional.absent(); - } - - @Override - public String toString() { - return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]"; - } - } - - public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy { - - private final Optional entryStrategy; - - protected OrderedMapModificationStrategy(final ListSchemaNode schema) { - super(OrderedMapNode.class); - entryStrategy = Optional. of(new ListEntryModificationStrategy(schema)); - } - - @SuppressWarnings("rawtypes") - @Override - protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof OrderedMapNode); - return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original); - } - - @Override - public Optional getChild(final PathArgument identifier) { - if (identifier instanceof NodeIdentifierWithPredicates) { - return entryStrategy; - } - return Optional.absent(); - } - - @Override - public String toString() { - return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]"; - } - } - - public static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) { - Set realChildSchemas = new HashSet<>(); - for(DataSchemaNode augChild : schema.getChildNodes()) { - realChildSchemas.add(resolved.getDataChildByName(augChild.getQName())); - } - return new AugmentationSchemaProxy(schema, realChildSchemas); } public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException { diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java new file mode 100644 index 0000000000..2892953935 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014 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 + */package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; + + import static com.google.common.base.Preconditions.checkArgument; + +import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException; + import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; + import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; + import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; + import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; + import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; + import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; + +import com.google.common.base.Optional; + import com.google.common.primitives.UnsignedLong; + + abstract class ValueNodeModificationStrategy extends SchemaAwareApplyOperation { + + private final T schema; + private final Class> nodeClass; + + protected ValueNodeModificationStrategy(final T schema, final Class> nodeClass) { + super(); + this.schema = schema; + this.nodeClass = nodeClass; + } + + @Override + protected void verifyWrittenStructure(final NormalizedNode writtenValue) { + checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass); + } + + @Override + public Optional getChild(final PathArgument child) { + throw new UnsupportedOperationException("Node " + schema.getPath() + + "is leaf type node. Child nodes not allowed"); + } + + @Override + protected StoreMetadataNode applySubtreeChange(final NodeModification modification, + final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) { + throw new UnsupportedOperationException("Node " + schema.getPath() + + "is leaf type node. Subtree change is not allowed."); + } + + @Override + protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta, + final UnsignedLong subtreeVersion) { + return applyWrite(modification, Optional.of(currentMeta), subtreeVersion); + } + + @Override + protected StoreMetadataNode applyWrite(final NodeModification modification, + final Optional currentMeta, final UnsignedLong subtreeVersion) { + return StoreMetadataNode.builder(subtreeVersion).setSubtreeVersion(subtreeVersion) + .setData(modification.getWrittenValue()).build(); + } + + @Override + protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + throw new DataPreconditionFailedException(path, "Subtree modification is not allowed."); + } + + public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy { + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) { + super(schema, (Class) LeafSetEntryNode.class); + } + } + + public static class LeafModificationStrategy extends ValueNodeModificationStrategy { + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected LeafModificationStrategy(final LeafSchemaNode schema) { + super(schema, (Class) LeafNode.class); + } + } + } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java index f2cc533207..03ece2f5e0 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java +++ b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java @@ -14,7 +14,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableCo import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -public class SchemaAwareApplyOperationRoot extends SchemaAwareApplyOperation.DataNodeContainerModificationStrategy { +public class SchemaAwareApplyOperationRoot extends DataNodeContainerModificationStrategy { private final SchemaContext context; public SchemaAwareApplyOperationRoot(final SchemaContext context) { -- 2.36.6