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.ImmutableOrderedLeafSetNodeBuilder;
40 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
41 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
42 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
43 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
44 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
45 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
46 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
47 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
48 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
49 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
50 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
51 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
53 import com.google.common.base.Function;
54 import com.google.common.base.Optional;
55 import com.google.common.base.Preconditions;
56 import com.google.common.cache.CacheBuilder;
57 import com.google.common.cache.CacheLoader;
58 import com.google.common.cache.LoadingCache;
59 import com.google.common.collect.ImmutableMap;
60 import com.google.common.collect.ImmutableSet;
61 import com.google.common.collect.ImmutableSet.Builder;
62 import com.google.common.primitives.UnsignedLong;
64 public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
66 public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
67 if (schemaNode instanceof ContainerSchemaNode) {
68 return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
69 } else if (schemaNode instanceof ListSchemaNode) {
70 return fromListSchemaNode((ListSchemaNode) schemaNode);
71 } else if (schemaNode instanceof ChoiceNode) {
72 return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
73 } else if (schemaNode instanceof LeafListSchemaNode) {
74 return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
75 } else if (schemaNode instanceof LeafSchemaNode) {
76 return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
78 throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
81 private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
82 List<QName> keyDefinition = schemaNode.getKeyDefinition();
83 if (keyDefinition == null || keyDefinition.isEmpty()) {
84 return new UnkeyedListModificationStrategy(schemaNode);
86 if (schemaNode.isUserOrdered()) {
87 return new OrderedMapModificationStrategy(schemaNode);
90 return new UnorderedMapModificationStrategy(schemaNode);
93 private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
94 if(schemaNode.isUserOrdered()) {
95 return new OrderedLeafSetModificationStrategy(schemaNode);
97 return new UnorderedLeafSetModificationStrategy(schemaNode);
102 public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
103 final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
104 AugmentationSchema augSchema = null;
105 allAugments: for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
106 boolean containsAll = true;
107 for (DataSchemaNode child : potential.getChildNodes()) {
108 if (identifier.getPossibleChildNames().contains(child.getQName())) {
109 augSchema = potential;
114 if (augSchema != null) {
115 return new AugmentationModificationStrategy(augSchema, resolvedTree);
120 protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
121 Optional<ModificationApplyOperation> potential = getChild(child);
122 checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
123 return potential.get();
127 public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
128 if (modification.getModificationType() == ModificationType.WRITE) {
129 verifyWritenStructure(modification.getWritenValue());
133 protected abstract void verifyWritenStructure(NormalizedNode<?, ?> writenValue);
136 public boolean isApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
137 switch (modification.getModificationType()) {
139 return isDeleteApplicable(modification, current);
140 case SUBTREE_MODIFIED:
141 return isSubtreeModificationApplicable(modification, current);
143 return isWriteApplicable(modification, current);
145 return isMergeApplicable(modification,current);
153 private boolean isMergeApplicable(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()) {
163 protected boolean isWriteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
164 Optional<StoreMetadataNode> original = modification.getOriginal();
165 if (original.isPresent() && current.isPresent()) {
166 return isNotConflicting(original.get(), current.get());
167 } else if (current.isPresent()) {
174 protected final boolean isNotConflicting(final StoreMetadataNode original, final StoreMetadataNode current) {
175 return original.getNodeVersion().equals(current.getNodeVersion())
176 && original.getSubtreeVersion().equals(current.getSubtreeVersion());
179 protected abstract boolean isSubtreeModificationApplicable(final NodeModification modification,
180 final Optional<StoreMetadataNode> current);
182 private boolean isDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
183 // FiXME: Add delete conflict detection.
188 public final Optional<StoreMetadataNode> apply(final NodeModification modification,
189 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
191 switch (modification.getModificationType()) {
193 return modification.storeSnapshot(Optional.<StoreMetadataNode> absent());
194 case SUBTREE_MODIFIED:
195 Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
197 return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
200 if(currentMeta.isPresent()) {
201 return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(),subtreeVersion)));
202 } // Fallback to write is intentional - if node is not preexisting merge is same as write
204 return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, subtreeVersion)));
208 throw new IllegalArgumentException("Provided modification type is not supported.");
212 protected abstract StoreMetadataNode applyMerge(NodeModification modification,
213 StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
215 protected abstract StoreMetadataNode applyWrite(NodeModification modification,
216 Optional<StoreMetadataNode> currentMeta, UnsignedLong subtreeVersion);
218 protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification,
219 StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
221 public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends
222 SchemaAwareApplyOperation {
224 private final T schema;
225 private final Class<? extends NormalizedNode<?, ?>> nodeClass;
227 protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
229 this.schema = schema;
230 this.nodeClass = nodeClass;
234 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
235 checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
239 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
240 throw new UnsupportedOperationException("Node " + schema.getPath()
241 + "is leaf type node. Child nodes not allowed");
245 protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
246 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
247 throw new UnsupportedOperationException("Node " + schema.getPath()
248 + "is leaf type node. Subtree change is not allowed.");
252 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
253 final UnsignedLong subtreeVersion) {
254 return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
258 protected StoreMetadataNode applyWrite(final NodeModification modification,
259 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
260 UnsignedLong nodeVersion = subtreeVersion;
261 return StoreMetadataNode.builder().setNodeVersion(nodeVersion).setSubtreeVersion(subtreeVersion)
262 .setData(modification.getWritenValue()).build();
266 protected boolean isSubtreeModificationApplicable(final NodeModification modification,
267 final Optional<StoreMetadataNode> current) {
273 public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
275 @SuppressWarnings({ "unchecked", "rawtypes" })
276 protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
277 super(schema, (Class) LeafSetEntryNode.class);
281 public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
283 @SuppressWarnings({ "unchecked", "rawtypes" })
284 protected LeafModificationStrategy(final LeafSchemaNode schema) {
285 super(schema, (Class) LeafNode.class);
289 public static abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
291 private final Class<? extends NormalizedNode<?, ?>> nodeClass;
293 protected NormalizedNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
294 this.nodeClass = nodeClass;
298 public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
299 if (modification.getModificationType() == ModificationType.WRITE) {
302 for (NodeModification childModification : modification.getModifications()) {
303 resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
307 @SuppressWarnings("rawtypes")
309 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
310 checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
311 checkArgument(writenValue instanceof NormalizedNodeContainer);
312 NormalizedNodeContainer writenCont = (NormalizedNodeContainer) writenValue;
313 for (Object child : writenCont.getValue()) {
314 checkArgument(child instanceof NormalizedNode);
315 NormalizedNode childNode = (NormalizedNode) child;
320 protected StoreMetadataNode applyWrite(final NodeModification modification,
321 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
323 NormalizedNode<?, ?> newValue = modification.getWritenValue();
325 UnsignedLong nodeVersion = subtreeVersion;
326 if (currentMeta.isPresent()) {
327 nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion());
329 StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion);
331 if (!modification.hasAdditionalModifications()) {
334 @SuppressWarnings("rawtypes")
335 NormalizedNodeContainerBuilder dataBuilder = createBuilder(modification.getIdentifier());
336 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder) //
337 .setNodeVersion(nodeVersion) //
338 .setSubtreeVersion(subtreeVersion);
340 Set<PathArgument> processedPreexisting = applyPreexistingChildren(modification, newValueMeta.getChildren(),
341 builder, nodeVersion);
342 applyNewChildren(modification, processedPreexisting, builder, nodeVersion);
344 return builder.build();
349 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
350 final UnsignedLong subtreeVersion) {
351 // For Node Containers - merge is same as subtree change - we only replace children.
352 return applySubtreeChange(modification, currentMeta, subtreeVersion);
356 public StoreMetadataNode applySubtreeChange(final NodeModification modification,
357 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
359 UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion());
360 @SuppressWarnings("rawtypes")
361 NormalizedNodeContainerBuilder dataBuilder = createBuilder(modification.getIdentifier());
362 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder)
363 .setIdentifier(modification.getIdentifier()).setNodeVersion(currentMeta.getNodeVersion())
364 .setSubtreeVersion(updatedSubtreeVersion);
365 // We process preexisting nodes
366 Set<PathArgument> processedPreexisting = applyPreexistingChildren(modification, currentMeta.getChildren(),
367 builder, updatedSubtreeVersion);
368 applyNewChildren(modification, processedPreexisting, builder, updatedSubtreeVersion);
369 return builder.build();
372 private void applyNewChildren(final NodeModification modification, final Set<PathArgument> ignore,
373 final StoreNodeCompositeBuilder builder, final UnsignedLong subtreeVersion) {
374 for (NodeModification childModification : modification.getModifications()) {
375 PathArgument childIdentifier = childModification.getIdentifier();
376 // We skip allready processed modifications
377 if (ignore.contains(childIdentifier)) {
381 builder.addIfPresent(resolveChildOperation(childIdentifier) //
382 .apply(childModification, Optional.<StoreMetadataNode> absent(), subtreeVersion));
386 private Set<PathArgument> applyPreexistingChildren(final NodeModification modification,
387 final Iterable<StoreMetadataNode> children, final StoreNodeCompositeBuilder nodeBuilder,
388 final UnsignedLong subtreeVersion) {
389 Builder<PathArgument> processedModifications = ImmutableSet.<PathArgument> builder();
390 for (StoreMetadataNode childMeta : children) {
391 PathArgument childIdentifier = childMeta.getIdentifier();
392 // We retrieve Child modification metadata
393 Optional<NodeModification> childModification = modification.getChild(childIdentifier);
395 if (childModification.isPresent()) {
396 processedModifications.add(childIdentifier);
397 Optional<StoreMetadataNode> result = resolveChildOperation(childIdentifier) //
398 .apply(childModification.get(), Optional.of(childMeta), subtreeVersion);
399 nodeBuilder.addIfPresent(result);
401 // Child is unmodified - reuse existing metadata and data
403 nodeBuilder.add(childMeta);
406 return processedModifications.build();
410 protected boolean isSubtreeModificationApplicable(final NodeModification modification,
411 final Optional<StoreMetadataNode> current) {
412 if (false == current.isPresent()) {
415 boolean result = true;
416 StoreMetadataNode currentMeta = current.get();
417 for (NodeModification childMod : modification.getModifications()) {
418 PathArgument childId = childMod.getIdentifier();
419 Optional<StoreMetadataNode> childMeta = currentMeta.getChild(childId);
420 result &= resolveChildOperation(childId).isApplicable(childMod, childMeta);
425 @SuppressWarnings("rawtypes")
426 protected abstract NormalizedNodeContainerBuilder createBuilder(PathArgument identifier);
429 public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends
430 NormalizedNodeContainerModificationStrategy {
432 private final T schema;
433 private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
434 .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
437 public ModificationApplyOperation apply(final PathArgument identifier) {
438 if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
439 return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier);
442 DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
450 protected DataNodeContainerModificationStrategy(final T schema,
451 final Class<? extends NormalizedNode<?, ?>> nodeClass) {
453 this.schema = schema;
456 protected T getSchema() {
461 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
463 return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
464 } catch (ExecutionException e) {
465 return Optional.absent();
470 @SuppressWarnings("rawtypes")
471 protected abstract DataContainerNodeBuilder createBuilder(PathArgument identifier);
474 public String toString() {
475 return getClass().getSimpleName() + " [" + schema + "]";
480 public static class ContainerModificationStrategy extends
481 DataNodeContainerModificationStrategy<ContainerSchemaNode> {
483 public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
484 super(schemaNode, ContainerNode.class);
488 @SuppressWarnings("rawtypes")
489 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
490 // TODO Auto-generated method stub
491 checkArgument(identifier instanceof NodeIdentifier);
492 return ImmutableContainerNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
497 public static class UnkeyedListItemModificationStrategy extends
498 DataNodeContainerModificationStrategy<ListSchemaNode> {
500 public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
501 super(schemaNode, UnkeyedListEntryNode.class);
505 @SuppressWarnings("rawtypes")
506 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
507 checkArgument(identifier instanceof NodeIdentifier);
508 return ImmutableUnkeyedListEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
513 public static class AugmentationModificationStrategy extends
514 DataNodeContainerModificationStrategy<AugmentationSchema> {
516 protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
517 super(schema, AugmentationNode.class);
518 // FIXME: Use resolved children instead of unresolved.
523 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
524 return Builders.augmentationBuilder().withNodeIdentifier((AugmentationIdentifier) identifier);
529 public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
531 private final ChoiceNode schema;
532 private final Map<PathArgument, ModificationApplyOperation> childNodes;
534 public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
535 super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
536 this.schema = schemaNode;
537 ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
539 for (ChoiceCaseNode caze : schemaNode.getCases()) {
540 for (DataSchemaNode cazeChild : caze.getChildNodes()) {
541 SchemaAwareApplyOperation childNode = from(cazeChild);
542 child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
545 childNodes = child.build();
549 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
550 return Optional.fromNullable(childNodes.get(child));
554 @SuppressWarnings("rawtypes")
555 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
556 checkArgument(identifier instanceof NodeIdentifier);
557 return ImmutableChoiceNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
562 public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
564 protected ListEntryModificationStrategy(final ListSchemaNode schema) {
565 super(schema, MapEntryNode.class);
569 @SuppressWarnings("rawtypes")
570 protected final DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
571 return ImmutableMapEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifierWithPredicates) identifier);
576 public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
578 private final Optional<ModificationApplyOperation> entryStrategy;
580 @SuppressWarnings({ "unchecked", "rawtypes" })
581 protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
582 super((Class) LeafSetNode.class);
583 entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
586 @SuppressWarnings("rawtypes")
588 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
589 return ImmutableLeafSetNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
593 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
594 if (identifier instanceof NodeWithValue) {
595 return entryStrategy;
597 return Optional.absent();
602 public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
604 private final Optional<ModificationApplyOperation> entryStrategy;
606 @SuppressWarnings({ "unchecked", "rawtypes" })
607 protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
608 super((Class) LeafSetNode.class);
609 entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
612 @SuppressWarnings("rawtypes")
614 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
615 return ImmutableOrderedLeafSetNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
619 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
620 if (identifier instanceof NodeWithValue) {
621 return entryStrategy;
623 return Optional.absent();
628 public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
630 private final Optional<ModificationApplyOperation> entryStrategy;
632 protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
633 entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
637 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
638 final UnsignedLong subtreeVersion) {
639 return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
643 protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
644 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
645 throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
649 protected StoreMetadataNode applyWrite(final NodeModification modification,
650 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
651 return StoreMetadataNode.createRecursively(modification.getWritenValue(), subtreeVersion);
655 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
656 if (child instanceof NodeIdentifier) {
657 return entryStrategy;
659 return Optional.absent();
663 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
668 protected boolean isSubtreeModificationApplicable(final NodeModification modification,
669 final Optional<StoreMetadataNode> current) {
675 public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
677 private final Optional<ModificationApplyOperation> entryStrategy;
679 protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
680 super(MapNode.class);
681 entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
684 @SuppressWarnings("rawtypes")
686 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
687 return ImmutableMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
691 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
692 if (identifier instanceof NodeIdentifierWithPredicates) {
693 return entryStrategy;
695 return Optional.absent();
699 public String toString() {
700 return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
704 public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
706 private final Optional<ModificationApplyOperation> entryStrategy;
708 protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
709 super(OrderedMapNode.class);
710 entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
713 @SuppressWarnings("rawtypes")
715 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
716 return ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
720 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
721 if (identifier instanceof NodeIdentifierWithPredicates) {
722 return entryStrategy;
724 return Optional.absent();
728 public String toString() {
729 return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
733 public void verifyIdentifier(final PathArgument identifier) {