X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-dom-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fmd%2Fsal%2Fdom%2Fstore%2Fimpl%2FSchemaAwareApplyOperation.java;h=a5c9b7983a92f93a9a2e2049688e0d33eaed1c8b;hp=dd7eb3f71b68012b497bee6b5fb2119bcf9455c9;hb=35563cb3c795ab92d0e85c34e3b3bab5da0c73bc;hpb=b23703bef6c3aaafe2dc83608a03b738ad42f945 diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java index dd7eb3f71b..a5c9b7983a 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java @@ -2,6 +2,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl; import static com.google.common.base.Preconditions.checkArgument; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; @@ -10,6 +11,7 @@ import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder; +import org.opendaylight.yangtools.yang.common.QName; 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; @@ -24,6 +26,8 @@ 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.OrderedMapNode; +import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder; @@ -32,6 +36,8 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableCo 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.ImmutableOrderedMapNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder; import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; @@ -60,7 +66,7 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper if (schemaNode instanceof ContainerSchemaNode) { return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode); } else if (schemaNode instanceof ListSchemaNode) { - return new ListMapModificationStrategy((ListSchemaNode) schemaNode); + return fromListSchemaNode((ListSchemaNode) schemaNode); } else if (schemaNode instanceof ChoiceNode) { return new ChoiceModificationStrategy((ChoiceNode) schemaNode); } else if (schemaNode instanceof LeafListSchemaNode) { @@ -71,26 +77,36 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass()); } + private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) { + List keyDefinition = schemaNode.getKeyDefinition(); + if (keyDefinition == null || keyDefinition.isEmpty()) { + return new UnkeyedListModificationStrategy(schemaNode); + } + if (schemaNode.isUserOrdered()) { + return new OrderedMapModificationStrategy(schemaNode); + } + + return new UnorderedMapModificationStrategy(schemaNode); + } + public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree, final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) { AugmentationSchema augSchema = null; - allAugments : for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) { + allAugments: for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) { boolean containsAll = true; - for(DataSchemaNode child : potential.getChildNodes()) { - if(identifier.getPossibleChildNames().contains(child.getQName())) { + for (DataSchemaNode child : potential.getChildNodes()) { + if (identifier.getPossibleChildNames().contains(child.getQName())) { augSchema = potential; break allAugments; } } } - if(augSchema != null) { - return new AugmentationModificationStrategy(augSchema,resolvedTree); + if (augSchema != null) { + return new AugmentationModificationStrategy(augSchema, resolvedTree); } return null; } - - protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) { Optional potential = getChild(child); checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child); @@ -115,6 +131,8 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper return isSubtreeModificationApplicable(modification, current); case WRITE: return isWriteApplicable(modification, current); + case MERGE: + return isMergeApplicable(modification,current); case UNMODIFIED: return true; default: @@ -122,6 +140,16 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } } + private boolean isMergeApplicable(final NodeModification modification, final Optional current) { + Optional original = modification.getOriginal(); + if (original.isPresent() && current.isPresent()) { + return isNotConflicting(original.get(), current.get()); + } else if (current.isPresent()) { + return true; + } + return true; + } + protected boolean isWriteApplicable(final NodeModification modification, final Optional current) { Optional original = modification.getOriginal(); if (original.isPresent() && current.isPresent()) { @@ -152,10 +180,16 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper switch (modification.getModificationType()) { case DELETE: - return modification.storeSnapshot(Optional.absent()); + return modification.storeSnapshot(Optional. absent()); case SUBTREE_MODIFIED: - Preconditions.checkArgument(currentMeta.isPresent(),"Metadata not available for modification",modification); - return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(), subtreeVersion))); + Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification", + modification); + return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(), + subtreeVersion))); + case MERGE: + if(currentMeta.isPresent()) { + return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(),subtreeVersion))); + } // Fallback to write is intentional - if node is not preexisting merge is same as write case WRITE: return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, subtreeVersion))); case UNMODIFIED: @@ -165,6 +199,9 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } } + protected abstract StoreMetadataNode applyMerge(NodeModification modification, + StoreMetadataNode currentMeta, UnsignedLong subtreeVersion); + protected abstract StoreMetadataNode applyWrite(NodeModification modification, Optional currentMeta, UnsignedLong subtreeVersion); @@ -201,14 +238,16 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper + "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) { UnsignedLong nodeVersion = subtreeVersion; - if (currentMeta.isPresent()) { - nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion()); - } - return StoreMetadataNode.builder().setNodeVersion(nodeVersion).setSubtreeVersion(subtreeVersion) .setData(modification.getWritenValue()).build(); } @@ -296,6 +335,13 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } + @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) { @@ -374,8 +420,8 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper NormalizedNodeContainerModificationStrategy { private final T schema; - private final LoadingCache childCache = CacheBuilder.newBuilder().build( - CacheLoader.from(new Function() { + private final LoadingCache childCache = CacheBuilder.newBuilder() + .build(CacheLoader.from(new Function() { @Override public ModificationApplyOperation apply(final PathArgument identifier) { @@ -438,6 +484,22 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } + public static class UnkeyedListItemModificationStrategy extends + DataNodeContainerModificationStrategy { + + public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) { + super(schemaNode, UnkeyedListEntryNode.class); + } + + @Override + @SuppressWarnings("rawtypes") + protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) { + checkArgument(identifier instanceof NodeIdentifier); + return ImmutableUnkeyedListEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier); + } + + } + public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy { @@ -447,7 +509,6 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } - @Override protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) { return Builders.augmentationBuilder().withNodeIdentifier((AugmentationIdentifier) identifier); @@ -458,17 +519,17 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy { private final ChoiceNode schema; - private final Map childNodes; + private final Map childNodes; public ChoiceModificationStrategy(final ChoiceNode schemaNode) { super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class); this.schema = schemaNode; ImmutableMap.Builder child = ImmutableMap.builder(); - for(ChoiceCaseNode caze : schemaNode.getCases()) { - for(DataSchemaNode cazeChild : caze.getChildNodes()) { + for (ChoiceCaseNode caze : schemaNode.getCases()) { + for (DataSchemaNode cazeChild : caze.getChildNodes()) { SchemaAwareApplyOperation childNode = from(cazeChild); - child.put(new NodeIdentifier(cazeChild.getQName()),childNode); + child.put(new NodeIdentifier(cazeChild.getQName()), childNode); } } childNodes = child.build(); @@ -528,11 +589,58 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } - public static class ListMapModificationStrategy extends NormalizedNodeContainerModificationStrategy { + public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation { private final Optional entryStrategy; - protected ListMapModificationStrategy(final ListSchemaNode schema) { + protected UnkeyedListModificationStrategy(final ListSchemaNode schema) { + entryStrategy = Optional. of(new UnkeyedListItemModificationStrategy(schema)); + } + + @Override + protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta, + final UnsignedLong subtreeVersion) { + return applyWrite(modification, Optional.of(currentMeta), subtreeVersion); + } + + @Override + protected StoreMetadataNode applySubtreeChange(final NodeModification modification, + final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) { + throw new UnsupportedOperationException("UnkeyedList does not support subtree change."); + } + + @Override + protected StoreMetadataNode applyWrite(final NodeModification modification, + final Optional currentMeta, final UnsignedLong subtreeVersion) { + return StoreMetadataNode.createRecursively(modification.getWritenValue(), subtreeVersion); + } + + @Override + public Optional getChild(final PathArgument child) { + if (child instanceof NodeIdentifier) { + return entryStrategy; + } + return Optional.absent(); + } + + @Override + protected void verifyWritenStructure(final NormalizedNode writenValue) { + + } + + @Override + protected boolean isSubtreeModificationApplicable(final NodeModification modification, + final Optional current) { + return false; + } + + } + + public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Optional entryStrategy; + + protected UnorderedMapModificationStrategy(final ListSchemaNode schema) { super(MapNode.class); entryStrategy = Optional. of(new ListEntryModificationStrategy(schema)); } @@ -553,7 +661,36 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper @Override public String toString() { - return "ListMapModificationStrategy [entry=" + entryStrategy + "]"; + 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 PathArgument identifier) { + return ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier); + } + + @Override + public Optional getChild(final PathArgument identifier) { + if (identifier instanceof NodeIdentifierWithPredicates) { + return entryStrategy; + } + return Optional.absent(); + } + + @Override + public String toString() { + return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]"; } }