1 package org.opendaylight.controller.md.sal.dom.store.impl;
3 import static com.google.common.base.Preconditions.checkArgument;
8 import java.util.concurrent.ExecutionException;
10 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
11 import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
12 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
13 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder;
14 import org.opendaylight.yangtools.yang.common.QName;
15 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
16 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
17 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
18 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
19 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
20 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
29 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
31 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
32 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
33 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
34 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
35 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
36 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
37 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
38 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
39 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
40 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
41 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
42 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
43 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
44 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
45 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
46 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
47 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
48 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
49 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
50 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
52 import com.google.common.base.Function;
53 import com.google.common.base.Optional;
54 import com.google.common.base.Preconditions;
55 import com.google.common.cache.CacheBuilder;
56 import com.google.common.cache.CacheLoader;
57 import com.google.common.cache.LoadingCache;
58 import com.google.common.collect.ImmutableMap;
59 import com.google.common.collect.ImmutableSet;
60 import com.google.common.collect.ImmutableSet.Builder;
61 import com.google.common.primitives.UnsignedLong;
63 public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
65 public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
66 if (schemaNode instanceof ContainerSchemaNode) {
67 return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
68 } else if (schemaNode instanceof ListSchemaNode) {
69 return fromListSchemaNode((ListSchemaNode) schemaNode);
70 } else if (schemaNode instanceof ChoiceNode) {
71 return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
72 } else if (schemaNode instanceof LeafListSchemaNode) {
73 return new LeafSetEntryModificationStrategy((LeafListSchemaNode) schemaNode);
74 } else if (schemaNode instanceof LeafSchemaNode) {
75 return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
77 throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
80 private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
81 List<QName> keyDefinition = schemaNode.getKeyDefinition();
82 if (keyDefinition == null || keyDefinition.isEmpty()) {
83 return new UnkeyedListModificationStrategy(schemaNode);
85 if (schemaNode.isUserOrdered()) {
86 return new OrderedMapModificationStrategy(schemaNode);
89 return new UnorderedMapModificationStrategy(schemaNode);
92 public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
93 final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
94 AugmentationSchema augSchema = null;
95 allAugments: for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
96 boolean containsAll = true;
97 for (DataSchemaNode child : potential.getChildNodes()) {
98 if (identifier.getPossibleChildNames().contains(child.getQName())) {
99 augSchema = potential;
104 if (augSchema != null) {
105 return new AugmentationModificationStrategy(augSchema, resolvedTree);
110 protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
111 Optional<ModificationApplyOperation> potential = getChild(child);
112 checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
113 return potential.get();
117 public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
118 if (modification.getModificationType() == ModificationType.WRITE) {
119 verifyWritenStructure(modification.getWritenValue());
123 protected abstract void verifyWritenStructure(NormalizedNode<?, ?> writenValue);
126 public boolean isApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
127 switch (modification.getModificationType()) {
129 return isDeleteApplicable(modification, current);
130 case SUBTREE_MODIFIED:
131 return isSubtreeModificationApplicable(modification, current);
133 return isWriteApplicable(modification, current);
135 return isMergeApplicable(modification,current);
143 private boolean isMergeApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
144 Optional<StoreMetadataNode> original = modification.getOriginal();
145 if (original.isPresent() && current.isPresent()) {
146 return isNotConflicting(original.get(), current.get());
147 } else if (current.isPresent()) {
153 protected boolean isWriteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
154 Optional<StoreMetadataNode> original = modification.getOriginal();
155 if (original.isPresent() && current.isPresent()) {
156 return isNotConflicting(original.get(), current.get());
157 } else if (current.isPresent()) {
164 protected final boolean isNotConflicting(final StoreMetadataNode original, final StoreMetadataNode current) {
165 return original.getNodeVersion().equals(current.getNodeVersion())
166 && original.getSubtreeVersion().equals(current.getSubtreeVersion());
169 protected abstract boolean isSubtreeModificationApplicable(final NodeModification modification,
170 final Optional<StoreMetadataNode> current);
172 private boolean isDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
173 // FiXME: Add delete conflict detection.
178 public final Optional<StoreMetadataNode> apply(final NodeModification modification,
179 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
181 switch (modification.getModificationType()) {
183 return modification.storeSnapshot(Optional.<StoreMetadataNode> absent());
184 case SUBTREE_MODIFIED:
185 Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
187 return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
190 if(currentMeta.isPresent()) {
191 return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(),subtreeVersion)));
192 } // Fallback to write is intentional - if node is not preexisting merge is same as write
194 return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, subtreeVersion)));
198 throw new IllegalArgumentException("Provided modification type is not supported.");
202 protected abstract StoreMetadataNode applyMerge(NodeModification modification,
203 StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
205 protected abstract StoreMetadataNode applyWrite(NodeModification modification,
206 Optional<StoreMetadataNode> currentMeta, UnsignedLong subtreeVersion);
208 protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification,
209 StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
211 public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends
212 SchemaAwareApplyOperation {
214 private final T schema;
215 private final Class<? extends NormalizedNode<?, ?>> nodeClass;
217 protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
219 this.schema = schema;
220 this.nodeClass = nodeClass;
224 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
225 checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
229 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
230 throw new UnsupportedOperationException("Node " + schema.getPath()
231 + "is leaf type node. Child nodes not allowed");
235 protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
236 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
237 throw new UnsupportedOperationException("Node " + schema.getPath()
238 + "is leaf type node. Subtree change is not allowed.");
242 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
243 final UnsignedLong subtreeVersion) {
244 return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
248 protected StoreMetadataNode applyWrite(final NodeModification modification,
249 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
250 UnsignedLong nodeVersion = subtreeVersion;
251 return StoreMetadataNode.builder().setNodeVersion(nodeVersion).setSubtreeVersion(subtreeVersion)
252 .setData(modification.getWritenValue()).build();
256 protected boolean isSubtreeModificationApplicable(final NodeModification modification,
257 final Optional<StoreMetadataNode> current) {
263 public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
265 @SuppressWarnings({ "unchecked", "rawtypes" })
266 protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
267 super(schema, (Class) LeafSetEntryNode.class);
271 public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
273 @SuppressWarnings({ "unchecked", "rawtypes" })
274 protected LeafModificationStrategy(final LeafSchemaNode schema) {
275 super(schema, (Class) LeafNode.class);
279 public static abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
281 private final Class<? extends NormalizedNode<?, ?>> nodeClass;
283 protected NormalizedNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
284 this.nodeClass = nodeClass;
288 public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
289 if (modification.getModificationType() == ModificationType.WRITE) {
292 for (NodeModification childModification : modification.getModifications()) {
293 resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
297 @SuppressWarnings("rawtypes")
299 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
300 checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
301 checkArgument(writenValue instanceof NormalizedNodeContainer);
302 NormalizedNodeContainer writenCont = (NormalizedNodeContainer) writenValue;
303 for (Object child : writenCont.getValue()) {
304 checkArgument(child instanceof NormalizedNode);
305 NormalizedNode childNode = (NormalizedNode) child;
310 protected StoreMetadataNode applyWrite(final NodeModification modification,
311 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
313 NormalizedNode<?, ?> newValue = modification.getWritenValue();
315 UnsignedLong nodeVersion = subtreeVersion;
316 if (currentMeta.isPresent()) {
317 nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion());
319 StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion);
321 if (!modification.hasAdditionalModifications()) {
324 @SuppressWarnings("rawtypes")
325 NormalizedNodeContainerBuilder dataBuilder = createBuilder(modification.getIdentifier());
326 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder) //
327 .setNodeVersion(nodeVersion) //
328 .setSubtreeVersion(subtreeVersion);
330 Set<PathArgument> processedPreexisting = applyPreexistingChildren(modification, newValueMeta.getChildren(),
331 builder, nodeVersion);
332 applyNewChildren(modification, processedPreexisting, builder, nodeVersion);
334 return builder.build();
339 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
340 final UnsignedLong subtreeVersion) {
341 // For Node Containers - merge is same as subtree change - we only replace children.
342 return applySubtreeChange(modification, currentMeta, subtreeVersion);
346 public StoreMetadataNode applySubtreeChange(final NodeModification modification,
347 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
349 UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion());
350 @SuppressWarnings("rawtypes")
351 NormalizedNodeContainerBuilder dataBuilder = createBuilder(modification.getIdentifier());
352 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder)
353 .setIdentifier(modification.getIdentifier()).setNodeVersion(currentMeta.getNodeVersion())
354 .setSubtreeVersion(updatedSubtreeVersion);
355 // We process preexisting nodes
356 Set<PathArgument> processedPreexisting = applyPreexistingChildren(modification, currentMeta.getChildren(),
357 builder, updatedSubtreeVersion);
358 applyNewChildren(modification, processedPreexisting, builder, updatedSubtreeVersion);
359 return builder.build();
362 private void applyNewChildren(final NodeModification modification, final Set<PathArgument> ignore,
363 final StoreNodeCompositeBuilder builder, final UnsignedLong subtreeVersion) {
364 for (NodeModification childModification : modification.getModifications()) {
365 PathArgument childIdentifier = childModification.getIdentifier();
366 // We skip allready processed modifications
367 if (ignore.contains(childIdentifier)) {
371 builder.addIfPresent(resolveChildOperation(childIdentifier) //
372 .apply(childModification, Optional.<StoreMetadataNode> absent(), subtreeVersion));
376 private Set<PathArgument> applyPreexistingChildren(final NodeModification modification,
377 final Iterable<StoreMetadataNode> children, final StoreNodeCompositeBuilder nodeBuilder,
378 final UnsignedLong subtreeVersion) {
379 Builder<PathArgument> processedModifications = ImmutableSet.<PathArgument> builder();
380 for (StoreMetadataNode childMeta : children) {
381 PathArgument childIdentifier = childMeta.getIdentifier();
382 // We retrieve Child modification metadata
383 Optional<NodeModification> childModification = modification.getChild(childIdentifier);
385 if (childModification.isPresent()) {
386 processedModifications.add(childIdentifier);
387 Optional<StoreMetadataNode> result = resolveChildOperation(childIdentifier) //
388 .apply(childModification.get(), Optional.of(childMeta), subtreeVersion);
389 nodeBuilder.addIfPresent(result);
391 // Child is unmodified - reuse existing metadata and data
393 nodeBuilder.add(childMeta);
396 return processedModifications.build();
400 protected boolean isSubtreeModificationApplicable(final NodeModification modification,
401 final Optional<StoreMetadataNode> current) {
402 if (false == current.isPresent()) {
405 boolean result = true;
406 StoreMetadataNode currentMeta = current.get();
407 for (NodeModification childMod : modification.getModifications()) {
408 PathArgument childId = childMod.getIdentifier();
409 Optional<StoreMetadataNode> childMeta = currentMeta.getChild(childId);
410 result &= resolveChildOperation(childId).isApplicable(childMod, childMeta);
415 @SuppressWarnings("rawtypes")
416 protected abstract NormalizedNodeContainerBuilder createBuilder(PathArgument identifier);
419 public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends
420 NormalizedNodeContainerModificationStrategy {
422 private final T schema;
423 private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
424 .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
427 public ModificationApplyOperation apply(final PathArgument identifier) {
428 if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
429 return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier);
432 DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
440 protected DataNodeContainerModificationStrategy(final T schema,
441 final Class<? extends NormalizedNode<?, ?>> nodeClass) {
443 this.schema = schema;
446 protected T getSchema() {
451 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
453 return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
454 } catch (ExecutionException e) {
455 return Optional.absent();
460 @SuppressWarnings("rawtypes")
461 protected abstract DataContainerNodeBuilder createBuilder(PathArgument identifier);
464 public String toString() {
465 return getClass().getSimpleName() + " [" + schema + "]";
470 public static class ContainerModificationStrategy extends
471 DataNodeContainerModificationStrategy<ContainerSchemaNode> {
473 public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
474 super(schemaNode, ContainerNode.class);
478 @SuppressWarnings("rawtypes")
479 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
480 // TODO Auto-generated method stub
481 checkArgument(identifier instanceof NodeIdentifier);
482 return ImmutableContainerNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
487 public static class UnkeyedListItemModificationStrategy extends
488 DataNodeContainerModificationStrategy<ListSchemaNode> {
490 public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
491 super(schemaNode, UnkeyedListEntryNode.class);
495 @SuppressWarnings("rawtypes")
496 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
497 checkArgument(identifier instanceof NodeIdentifier);
498 return ImmutableUnkeyedListEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
503 public static class AugmentationModificationStrategy extends
504 DataNodeContainerModificationStrategy<AugmentationSchema> {
506 protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
507 super(schema, AugmentationNode.class);
508 // FIXME: Use resolved children instead of unresolved.
513 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
514 return Builders.augmentationBuilder().withNodeIdentifier((AugmentationIdentifier) identifier);
519 public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
521 private final ChoiceNode schema;
522 private final Map<PathArgument, ModificationApplyOperation> childNodes;
524 public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
525 super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
526 this.schema = schemaNode;
527 ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
529 for (ChoiceCaseNode caze : schemaNode.getCases()) {
530 for (DataSchemaNode cazeChild : caze.getChildNodes()) {
531 SchemaAwareApplyOperation childNode = from(cazeChild);
532 child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
535 childNodes = child.build();
539 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
540 return Optional.fromNullable(childNodes.get(child));
544 @SuppressWarnings("rawtypes")
545 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
546 checkArgument(identifier instanceof NodeIdentifier);
547 return ImmutableChoiceNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
552 public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
554 protected ListEntryModificationStrategy(final ListSchemaNode schema) {
555 super(schema, MapEntryNode.class);
559 @SuppressWarnings("rawtypes")
560 protected final DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
561 return ImmutableMapEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifierWithPredicates) identifier);
566 public static class LeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
568 private final Optional<ModificationApplyOperation> entryStrategy;
570 @SuppressWarnings({ "unchecked", "rawtypes" })
571 protected LeafSetModificationStrategy(final LeafListSchemaNode schema) {
572 super((Class) LeafSetNode.class);
573 entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
576 @SuppressWarnings("rawtypes")
578 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
579 return ImmutableLeafSetNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
583 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
584 if (identifier instanceof NodeWithValue) {
585 return entryStrategy;
587 return Optional.absent();
592 public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
594 private final Optional<ModificationApplyOperation> entryStrategy;
596 protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
597 entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
601 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
602 final UnsignedLong subtreeVersion) {
603 return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
607 protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
608 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
609 throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
613 protected StoreMetadataNode applyWrite(final NodeModification modification,
614 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
615 return StoreMetadataNode.createRecursively(modification.getWritenValue(), subtreeVersion);
619 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
620 if (child instanceof NodeIdentifier) {
621 return entryStrategy;
623 return Optional.absent();
627 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
632 protected boolean isSubtreeModificationApplicable(final NodeModification modification,
633 final Optional<StoreMetadataNode> current) {
639 public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
641 private final Optional<ModificationApplyOperation> entryStrategy;
643 protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
644 super(MapNode.class);
645 entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
648 @SuppressWarnings("rawtypes")
650 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
651 return ImmutableMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
655 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
656 if (identifier instanceof NodeIdentifierWithPredicates) {
657 return entryStrategy;
659 return Optional.absent();
663 public String toString() {
664 return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
668 public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
670 private final Optional<ModificationApplyOperation> entryStrategy;
672 protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
673 super(OrderedMapNode.class);
674 entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
677 @SuppressWarnings("rawtypes")
679 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
680 return ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
684 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
685 if (identifier instanceof NodeIdentifierWithPredicates) {
686 return entryStrategy;
688 return Optional.absent();
692 public String toString() {
693 return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
697 public void verifyIdentifier(final PathArgument identifier) {