1 package org.opendaylight.controller.md.sal.dom.store.impl;
3 import static com.google.common.base.Preconditions.checkArgument;
5 import java.util.HashSet;
9 import java.util.concurrent.ExecutionException;
11 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
12 import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
13 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
14 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder;
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
17 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
19 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
20 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
21 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
30 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
32 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
33 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
34 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
35 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
36 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
37 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
38 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
39 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
40 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
41 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
42 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
43 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
44 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
45 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
46 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
47 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
48 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
49 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
50 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
51 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
52 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
53 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
55 import com.google.common.base.Function;
56 import com.google.common.base.Optional;
57 import com.google.common.base.Preconditions;
58 import com.google.common.cache.CacheBuilder;
59 import com.google.common.cache.CacheLoader;
60 import com.google.common.cache.LoadingCache;
61 import com.google.common.collect.ImmutableMap;
62 import com.google.common.collect.ImmutableSet;
63 import com.google.common.collect.ImmutableSet.Builder;
64 import com.google.common.primitives.UnsignedLong;
66 public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
68 public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
69 if (schemaNode instanceof ContainerSchemaNode) {
70 return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
71 } else if (schemaNode instanceof ListSchemaNode) {
72 return fromListSchemaNode((ListSchemaNode) schemaNode);
73 } else if (schemaNode instanceof ChoiceNode) {
74 return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
75 } else if (schemaNode instanceof LeafListSchemaNode) {
76 return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
77 } else if (schemaNode instanceof LeafSchemaNode) {
78 return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
80 throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
83 private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
84 List<QName> keyDefinition = schemaNode.getKeyDefinition();
85 if (keyDefinition == null || keyDefinition.isEmpty()) {
86 return new UnkeyedListModificationStrategy(schemaNode);
88 if (schemaNode.isUserOrdered()) {
89 return new OrderedMapModificationStrategy(schemaNode);
92 return new UnorderedMapModificationStrategy(schemaNode);
95 private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
96 if(schemaNode.isUserOrdered()) {
97 return new OrderedLeafSetModificationStrategy(schemaNode);
99 return new UnorderedLeafSetModificationStrategy(schemaNode);
104 public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
105 final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
106 AugmentationSchema augSchema = null;
107 allAugments: for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
108 boolean containsAll = true;
109 for (DataSchemaNode child : potential.getChildNodes()) {
110 if (identifier.getPossibleChildNames().contains(child.getQName())) {
111 augSchema = potential;
116 if (augSchema != null) {
117 return new AugmentationModificationStrategy(augSchema, resolvedTree);
122 protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
123 Optional<ModificationApplyOperation> potential = getChild(child);
124 checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
125 return potential.get();
129 public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
130 if (modification.getModificationType() == ModificationType.WRITE) {
131 verifyWritenStructure(modification.getWritenValue());
135 protected abstract void verifyWritenStructure(NormalizedNode<?, ?> writenValue);
138 public boolean isApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
139 switch (modification.getModificationType()) {
141 return isDeleteApplicable(modification, current);
142 case SUBTREE_MODIFIED:
143 return isSubtreeModificationApplicable(modification, current);
145 return isWriteApplicable(modification, current);
147 return isMergeApplicable(modification,current);
155 private boolean isMergeApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
156 Optional<StoreMetadataNode> original = modification.getOriginal();
157 if (original.isPresent() && current.isPresent()) {
158 return isNotConflicting(original.get(), current.get());
159 } else if (current.isPresent()) {
165 protected boolean isWriteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
166 Optional<StoreMetadataNode> original = modification.getOriginal();
167 if (original.isPresent() && current.isPresent()) {
168 return isNotConflicting(original.get(), current.get());
169 } else if (current.isPresent()) {
176 protected final boolean isNotConflicting(final StoreMetadataNode original, final StoreMetadataNode current) {
177 return original.getNodeVersion().equals(current.getNodeVersion())
178 && original.getSubtreeVersion().equals(current.getSubtreeVersion());
181 protected abstract boolean isSubtreeModificationApplicable(final NodeModification modification,
182 final Optional<StoreMetadataNode> current);
184 private boolean isDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
185 // FiXME: Add delete conflict detection.
190 public final Optional<StoreMetadataNode> apply(final NodeModification modification,
191 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
193 switch (modification.getModificationType()) {
195 return modification.storeSnapshot(Optional.<StoreMetadataNode> absent());
196 case SUBTREE_MODIFIED:
197 Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
199 return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
202 if(currentMeta.isPresent()) {
203 return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(),subtreeVersion)));
204 } // Fallback to write is intentional - if node is not preexisting merge is same as write
206 return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, subtreeVersion)));
210 throw new IllegalArgumentException("Provided modification type is not supported.");
214 protected abstract StoreMetadataNode applyMerge(NodeModification modification,
215 StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
217 protected abstract StoreMetadataNode applyWrite(NodeModification modification,
218 Optional<StoreMetadataNode> currentMeta, UnsignedLong subtreeVersion);
220 protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification,
221 StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
223 public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends
224 SchemaAwareApplyOperation {
226 private final T schema;
227 private final Class<? extends NormalizedNode<?, ?>> nodeClass;
229 protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
231 this.schema = schema;
232 this.nodeClass = nodeClass;
236 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
237 checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
241 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
242 throw new UnsupportedOperationException("Node " + schema.getPath()
243 + "is leaf type node. Child nodes not allowed");
247 protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
248 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
249 throw new UnsupportedOperationException("Node " + schema.getPath()
250 + "is leaf type node. Subtree change is not allowed.");
254 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
255 final UnsignedLong subtreeVersion) {
256 return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
260 protected StoreMetadataNode applyWrite(final NodeModification modification,
261 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
262 UnsignedLong nodeVersion = subtreeVersion;
263 return StoreMetadataNode.builder().setNodeVersion(nodeVersion).setSubtreeVersion(subtreeVersion)
264 .setData(modification.getWritenValue()).build();
268 protected boolean isSubtreeModificationApplicable(final NodeModification modification,
269 final Optional<StoreMetadataNode> current) {
275 public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
277 @SuppressWarnings({ "unchecked", "rawtypes" })
278 protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
279 super(schema, (Class) LeafSetEntryNode.class);
283 public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
285 @SuppressWarnings({ "unchecked", "rawtypes" })
286 protected LeafModificationStrategy(final LeafSchemaNode schema) {
287 super(schema, (Class) LeafNode.class);
291 public static abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
293 private final Class<? extends NormalizedNode<?, ?>> nodeClass;
295 protected NormalizedNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
296 this.nodeClass = nodeClass;
300 public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
301 if (modification.getModificationType() == ModificationType.WRITE) {
304 for (NodeModification childModification : modification.getModifications()) {
305 resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
309 @SuppressWarnings("rawtypes")
311 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
312 checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
313 checkArgument(writenValue instanceof NormalizedNodeContainer);
314 NormalizedNodeContainer writenCont = (NormalizedNodeContainer) writenValue;
315 for (Object child : writenCont.getValue()) {
316 checkArgument(child instanceof NormalizedNode);
317 NormalizedNode childNode = (NormalizedNode) child;
322 protected StoreMetadataNode applyWrite(final NodeModification modification,
323 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
325 NormalizedNode<?, ?> newValue = modification.getWritenValue();
327 UnsignedLong nodeVersion = subtreeVersion;
328 if (currentMeta.isPresent()) {
329 nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion());
331 StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion);
333 if (!modification.hasAdditionalModifications()) {
336 @SuppressWarnings("rawtypes")
337 NormalizedNodeContainerBuilder dataBuilder = createBuilder(modification.getIdentifier());
338 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder) //
339 .setNodeVersion(nodeVersion) //
340 .setSubtreeVersion(subtreeVersion);
342 Set<PathArgument> processedPreexisting = applyPreexistingChildren(modification, newValueMeta.getChildren(),
343 builder, nodeVersion);
344 applyNewChildren(modification, processedPreexisting, builder, nodeVersion);
346 return builder.build();
351 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
352 final UnsignedLong subtreeVersion) {
353 // For Node Containers - merge is same as subtree change - we only replace children.
354 return applySubtreeChange(modification, currentMeta, subtreeVersion);
358 public StoreMetadataNode applySubtreeChange(final NodeModification modification,
359 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
361 UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion());
362 @SuppressWarnings("rawtypes")
363 NormalizedNodeContainerBuilder dataBuilder = createBuilder(modification.getIdentifier());
364 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder)
365 .setIdentifier(modification.getIdentifier()).setNodeVersion(currentMeta.getNodeVersion())
366 .setSubtreeVersion(updatedSubtreeVersion);
367 // We process preexisting nodes
368 Set<PathArgument> processedPreexisting = applyPreexistingChildren(modification, currentMeta.getChildren(),
369 builder, updatedSubtreeVersion);
370 applyNewChildren(modification, processedPreexisting, builder, updatedSubtreeVersion);
371 return builder.build();
374 private void applyNewChildren(final NodeModification modification, final Set<PathArgument> ignore,
375 final StoreNodeCompositeBuilder builder, final UnsignedLong subtreeVersion) {
376 for (NodeModification childModification : modification.getModifications()) {
377 PathArgument childIdentifier = childModification.getIdentifier();
378 // We skip allready processed modifications
379 if (ignore.contains(childIdentifier)) {
383 builder.addIfPresent(resolveChildOperation(childIdentifier) //
384 .apply(childModification, Optional.<StoreMetadataNode> absent(), subtreeVersion));
388 private Set<PathArgument> applyPreexistingChildren(final NodeModification modification,
389 final Iterable<StoreMetadataNode> children, final StoreNodeCompositeBuilder nodeBuilder,
390 final UnsignedLong subtreeVersion) {
391 Builder<PathArgument> processedModifications = ImmutableSet.<PathArgument> builder();
392 for (StoreMetadataNode childMeta : children) {
393 PathArgument childIdentifier = childMeta.getIdentifier();
394 // We retrieve Child modification metadata
395 Optional<NodeModification> childModification = modification.getChild(childIdentifier);
397 if (childModification.isPresent()) {
398 processedModifications.add(childIdentifier);
399 Optional<StoreMetadataNode> result = resolveChildOperation(childIdentifier) //
400 .apply(childModification.get(), Optional.of(childMeta), subtreeVersion);
401 nodeBuilder.addIfPresent(result);
403 // Child is unmodified - reuse existing metadata and data
405 nodeBuilder.add(childMeta);
408 return processedModifications.build();
412 protected boolean isSubtreeModificationApplicable(final NodeModification modification,
413 final Optional<StoreMetadataNode> current) {
414 if (false == current.isPresent()) {
417 boolean result = true;
418 StoreMetadataNode currentMeta = current.get();
419 for (NodeModification childMod : modification.getModifications()) {
420 PathArgument childId = childMod.getIdentifier();
421 Optional<StoreMetadataNode> childMeta = currentMeta.getChild(childId);
422 result &= resolveChildOperation(childId).isApplicable(childMod, childMeta);
427 @SuppressWarnings("rawtypes")
428 protected abstract NormalizedNodeContainerBuilder createBuilder(PathArgument identifier);
431 public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends
432 NormalizedNodeContainerModificationStrategy {
434 private final T schema;
435 private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
436 .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
439 public ModificationApplyOperation apply(final PathArgument identifier) {
440 if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
441 return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier);
444 DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
452 protected DataNodeContainerModificationStrategy(final T schema,
453 final Class<? extends NormalizedNode<?, ?>> nodeClass) {
455 this.schema = schema;
458 protected T getSchema() {
463 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
465 return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
466 } catch (ExecutionException e) {
467 return Optional.absent();
472 @SuppressWarnings("rawtypes")
473 protected abstract DataContainerNodeBuilder createBuilder(PathArgument identifier);
476 public String toString() {
477 return getClass().getSimpleName() + " [" + schema + "]";
482 public static class ContainerModificationStrategy extends
483 DataNodeContainerModificationStrategy<ContainerSchemaNode> {
485 public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
486 super(schemaNode, ContainerNode.class);
490 @SuppressWarnings("rawtypes")
491 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
492 // TODO Auto-generated method stub
493 checkArgument(identifier instanceof NodeIdentifier);
494 return ImmutableContainerNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
499 public static class UnkeyedListItemModificationStrategy extends
500 DataNodeContainerModificationStrategy<ListSchemaNode> {
502 public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
503 super(schemaNode, UnkeyedListEntryNode.class);
507 @SuppressWarnings("rawtypes")
508 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
509 checkArgument(identifier instanceof NodeIdentifier);
510 return ImmutableUnkeyedListEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
515 public static class AugmentationModificationStrategy extends
516 DataNodeContainerModificationStrategy<AugmentationSchema> {
518 protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
519 super(createAugmentProxy(schema,resolved), AugmentationNode.class);
520 // FIXME: Use resolved children instead of unresolved.
525 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
526 return Builders.augmentationBuilder().withNodeIdentifier((AugmentationIdentifier) identifier);
531 public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
533 private final ChoiceNode schema;
534 private final Map<PathArgument, ModificationApplyOperation> childNodes;
536 public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
537 super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
538 this.schema = schemaNode;
539 ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
541 for (ChoiceCaseNode caze : schemaNode.getCases()) {
542 for (DataSchemaNode cazeChild : caze.getChildNodes()) {
543 SchemaAwareApplyOperation childNode = from(cazeChild);
544 child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
547 childNodes = child.build();
551 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
552 return Optional.fromNullable(childNodes.get(child));
556 @SuppressWarnings("rawtypes")
557 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
558 checkArgument(identifier instanceof NodeIdentifier);
559 return ImmutableChoiceNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
564 public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
566 protected ListEntryModificationStrategy(final ListSchemaNode schema) {
567 super(schema, MapEntryNode.class);
571 @SuppressWarnings("rawtypes")
572 protected final DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
573 return ImmutableMapEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifierWithPredicates) identifier);
578 public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
580 private final Optional<ModificationApplyOperation> entryStrategy;
582 @SuppressWarnings({ "unchecked", "rawtypes" })
583 protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
584 super((Class) LeafSetNode.class);
585 entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
588 @SuppressWarnings("rawtypes")
590 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
591 return ImmutableLeafSetNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
595 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
596 if (identifier instanceof NodeWithValue) {
597 return entryStrategy;
599 return Optional.absent();
604 public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
606 private final Optional<ModificationApplyOperation> entryStrategy;
608 @SuppressWarnings({ "unchecked", "rawtypes" })
609 protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
610 super((Class) LeafSetNode.class);
611 entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
614 @SuppressWarnings("rawtypes")
616 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
617 return ImmutableOrderedLeafSetNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
621 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
622 if (identifier instanceof NodeWithValue) {
623 return entryStrategy;
625 return Optional.absent();
630 public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
632 private final Optional<ModificationApplyOperation> entryStrategy;
634 protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
635 entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
639 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
640 final UnsignedLong subtreeVersion) {
641 return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
645 protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
646 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
647 throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
651 protected StoreMetadataNode applyWrite(final NodeModification modification,
652 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
653 return StoreMetadataNode.createRecursively(modification.getWritenValue(), subtreeVersion);
657 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
658 if (child instanceof NodeIdentifier) {
659 return entryStrategy;
661 return Optional.absent();
665 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
670 protected boolean isSubtreeModificationApplicable(final NodeModification modification,
671 final Optional<StoreMetadataNode> current) {
677 public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
679 private final Optional<ModificationApplyOperation> entryStrategy;
681 protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
682 super(MapNode.class);
683 entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
686 @SuppressWarnings("rawtypes")
688 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
689 return ImmutableMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
693 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
694 if (identifier instanceof NodeIdentifierWithPredicates) {
695 return entryStrategy;
697 return Optional.absent();
701 public String toString() {
702 return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
706 public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
708 private final Optional<ModificationApplyOperation> entryStrategy;
710 protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
711 super(OrderedMapNode.class);
712 entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
715 @SuppressWarnings("rawtypes")
717 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
718 return ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
722 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
723 if (identifier instanceof NodeIdentifierWithPredicates) {
724 return entryStrategy;
726 return Optional.absent();
730 public String toString() {
731 return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
735 public void verifyIdentifier(final PathArgument identifier) {
739 public static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
740 Set<DataSchemaNode> realChildSchemas = new HashSet<>();
741 for(DataSchemaNode augChild : schema.getChildNodes()) {
742 realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
744 return new AugmentationSchemaProxy(schema, realChildSchemas);