2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.md.sal.dom.store.impl;
10 import static com.google.common.base.Preconditions.checkArgument;
12 import java.util.HashSet;
13 import java.util.List;
16 import java.util.concurrent.ExecutionException;
18 import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
19 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationApplyOperation;
20 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
21 import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ModificationType;
22 import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NodeModification;
23 import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.StoreMetadataNode;
24 import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.StoreNodeCompositeBuilder;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
28 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
30 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
31 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
32 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
41 import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
43 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
44 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
45 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
46 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
47 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
48 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
49 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
50 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
51 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
52 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
53 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
54 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
55 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
56 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
57 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
58 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
59 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
60 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
61 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
62 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
63 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
64 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
65 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
67 import com.google.common.base.Function;
68 import com.google.common.base.Optional;
69 import com.google.common.base.Preconditions;
70 import com.google.common.cache.CacheBuilder;
71 import com.google.common.cache.CacheLoader;
72 import com.google.common.cache.LoadingCache;
73 import com.google.common.collect.ImmutableMap;
74 import com.google.common.primitives.UnsignedLong;
76 public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
78 public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
79 if (schemaNode instanceof ContainerSchemaNode) {
80 return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
81 } else if (schemaNode instanceof ListSchemaNode) {
82 return fromListSchemaNode((ListSchemaNode) schemaNode);
83 } else if (schemaNode instanceof ChoiceNode) {
84 return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
85 } else if (schemaNode instanceof LeafListSchemaNode) {
86 return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
87 } else if (schemaNode instanceof LeafSchemaNode) {
88 return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
90 throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
93 private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
94 List<QName> keyDefinition = schemaNode.getKeyDefinition();
95 if (keyDefinition == null || keyDefinition.isEmpty()) {
96 return new UnkeyedListModificationStrategy(schemaNode);
98 if (schemaNode.isUserOrdered()) {
99 return new OrderedMapModificationStrategy(schemaNode);
102 return new UnorderedMapModificationStrategy(schemaNode);
105 private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
106 if(schemaNode.isUserOrdered()) {
107 return new OrderedLeafSetModificationStrategy(schemaNode);
109 return new UnorderedLeafSetModificationStrategy(schemaNode);
114 public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
115 final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
116 AugmentationSchema augSchema = null;
119 for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
120 for (DataSchemaNode child : potential.getChildNodes()) {
121 if (identifier.getPossibleChildNames().contains(child.getQName())) {
122 augSchema = potential;
128 if (augSchema != null) {
129 return new AugmentationModificationStrategy(augSchema, resolvedTree);
134 protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
135 Optional<ModificationApplyOperation> potential = getChild(child);
136 checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
137 return potential.get();
141 public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
142 if (modification.getModificationType() == ModificationType.WRITE) {
143 verifyWrittenStructure(modification.getWrittenValue());
147 protected abstract void verifyWrittenStructure(NormalizedNode<?, ?> writtenValue);
150 public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
151 switch (modification.getModificationType()) {
153 checkDeleteApplicable(modification, current);
154 case SUBTREE_MODIFIED:
155 checkSubtreeModificationApplicable(path,modification, current);
158 checkWriteApplicable(path,modification, current);
161 checkMergeApplicable(path,modification,current);
166 throw new UnsupportedOperationException("Suplied modification type "+modification.getModificationType()+ "is not supported.");
171 protected void checkMergeApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
172 Optional<StoreMetadataNode> original = modification.getOriginal();
173 if (original.isPresent() && current.isPresent()) {
175 * We need to do conflict detection only and only if the value of leaf changed
176 * before two transactions. If value of leaf is unchanged between two transactions
177 * it should not cause transaction to fail, since result of this merge
178 * leads to same data.
180 if(!original.get().getData().equals(current.get().getData())) {
182 checkNotConflicting(path,original.get(), current.get());
187 protected void checkWriteApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
188 Optional<StoreMetadataNode> original = modification.getOriginal();
189 if (original.isPresent() && current.isPresent()) {
190 checkNotConflicting(path,original.get(), current.get());
191 } else if(original.isPresent()) {
192 throw new DataPreconditionFailedException(path,"Node was deleted by other transaction.");
196 protected static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException {
197 checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction.");
198 checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction");
201 protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification,
202 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
204 private void checkDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
208 public final Optional<StoreMetadataNode> apply(final NodeModification modification,
209 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
211 switch (modification.getModificationType()) {
213 return modification.storeSnapshot(Optional.<StoreMetadataNode> absent());
214 case SUBTREE_MODIFIED:
215 Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
217 return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
220 if(currentMeta.isPresent()) {
221 return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(),subtreeVersion)));
222 } // Fallback to write is intentional - if node is not preexisting merge is same as write
224 return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, subtreeVersion)));
228 throw new IllegalArgumentException("Provided modification type is not supported.");
232 protected abstract StoreMetadataNode applyMerge(NodeModification modification,
233 StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
235 protected abstract StoreMetadataNode applyWrite(NodeModification modification,
236 Optional<StoreMetadataNode> currentMeta, UnsignedLong subtreeVersion);
238 protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification,
239 StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
241 public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends SchemaAwareApplyOperation {
243 private final T schema;
244 private final Class<? extends NormalizedNode<?, ?>> nodeClass;
246 protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
248 this.schema = schema;
249 this.nodeClass = nodeClass;
253 protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
254 checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
258 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
259 throw new UnsupportedOperationException("Node " + schema.getPath()
260 + "is leaf type node. Child nodes not allowed");
264 protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
265 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
266 throw new UnsupportedOperationException("Node " + schema.getPath()
267 + "is leaf type node. Subtree change is not allowed.");
271 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
272 final UnsignedLong subtreeVersion) {
273 return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
277 protected StoreMetadataNode applyWrite(final NodeModification modification,
278 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
279 UnsignedLong nodeVersion = subtreeVersion;
280 return StoreMetadataNode.builder().setNodeVersion(nodeVersion).setSubtreeVersion(subtreeVersion)
281 .setData(modification.getWrittenValue()).build();
285 protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
286 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
287 throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
292 public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
294 @SuppressWarnings({ "unchecked", "rawtypes" })
295 protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
296 super(schema, (Class) LeafSetEntryNode.class);
300 public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
302 @SuppressWarnings({ "unchecked", "rawtypes" })
303 protected LeafModificationStrategy(final LeafSchemaNode schema) {
304 super(schema, (Class) LeafNode.class);
308 public static abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
310 private final Class<? extends NormalizedNode<?, ?>> nodeClass;
312 protected NormalizedNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
313 this.nodeClass = nodeClass;
317 public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
318 if (modification.getModificationType() == ModificationType.WRITE) {
321 for (NodeModification childModification : modification.getModifications()) {
322 resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
327 protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification,
328 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
329 // FIXME: Implement proper write check for replacement of node container
330 // prerequisite is to have transaction chain available for clients
331 // otherwise this will break chained writes to same node.
334 @SuppressWarnings("rawtypes")
336 protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
337 checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
338 checkArgument(writtenValue instanceof NormalizedNodeContainer);
340 NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
341 for (Object child : container.getValue()) {
342 checkArgument(child instanceof NormalizedNode);
345 * FIXME: fail-fast semantics:
347 * We can validate the data structure here, aborting the commit
348 * before it ever progresses to being committed.
354 protected StoreMetadataNode applyWrite(final NodeModification modification,
355 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
357 NormalizedNode<?, ?> newValue = modification.getWrittenValue();
359 final UnsignedLong nodeVersion;
360 if (currentMeta.isPresent()) {
361 nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion());
363 nodeVersion = subtreeVersion;
366 final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion);
367 if (!modification.hasAdditionalModifications()) {
371 @SuppressWarnings("rawtypes")
372 NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
373 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder) //
374 .setNodeVersion(nodeVersion) //
375 .setSubtreeVersion(subtreeVersion);
377 return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion);
381 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
382 final UnsignedLong subtreeVersion) {
383 // For Node Containers - merge is same as subtree change - we only replace children.
384 return applySubtreeChange(modification, currentMeta, subtreeVersion);
388 public StoreMetadataNode applySubtreeChange(final NodeModification modification,
389 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
390 // Bump subtree version to its new target
391 final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion());
393 @SuppressWarnings("rawtypes")
394 NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
395 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder, currentMeta)
396 .setIdentifier(modification.getIdentifier()).setNodeVersion(currentMeta.getNodeVersion())
397 .setSubtreeVersion(updatedSubtreeVersion);
399 return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion);
402 private StoreMetadataNode mutateChildren(final Iterable<NodeModification> modifications, final StoreMetadataNode meta,
403 final StoreNodeCompositeBuilder builder, final UnsignedLong nodeVersion) {
405 for (NodeModification mod : modifications) {
406 final PathArgument id = mod.getIdentifier();
407 final Optional<StoreMetadataNode> cm = meta.getChild(id);
409 Optional<StoreMetadataNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
410 if (result.isPresent()) {
411 builder.add(result.get());
417 return builder.build();
421 protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
422 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
423 checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction.");
424 checkChildPreconditions(path,modification,current);
428 private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
429 StoreMetadataNode currentMeta = current.get();
430 for (NodeModification childMod : modification.getModifications()) {
431 PathArgument childId = childMod.getIdentifier();
432 Optional<StoreMetadataNode> childMeta = currentMeta.getChild(childId);
433 InstanceIdentifier childPath = StoreUtils.append(path, childId);
434 resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta);
439 protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification,
440 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
441 if(current.isPresent()) {
442 checkChildPreconditions(path,modification,current);
446 @SuppressWarnings("rawtypes")
447 protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
450 public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends NormalizedNodeContainerModificationStrategy {
452 private final T schema;
453 private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
454 .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
457 public ModificationApplyOperation apply(final PathArgument identifier) {
458 if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
459 return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier);
462 DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
470 protected DataNodeContainerModificationStrategy(final T schema,
471 final Class<? extends NormalizedNode<?, ?>> nodeClass) {
473 this.schema = schema;
476 protected T getSchema() {
481 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
483 return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
484 } catch (ExecutionException e) {
485 return Optional.absent();
490 @SuppressWarnings("rawtypes")
491 protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original);
494 public String toString() {
495 return getClass().getSimpleName() + " [" + schema + "]";
500 public static class ContainerModificationStrategy extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
502 public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
503 super(schemaNode, ContainerNode.class);
507 @SuppressWarnings("rawtypes")
508 protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
509 checkArgument(original instanceof ContainerNode);
510 return ImmutableContainerNodeBuilder.create((ContainerNode) original);
514 public static class UnkeyedListItemModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
516 public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
517 super(schemaNode, UnkeyedListEntryNode.class);
521 @SuppressWarnings("rawtypes")
522 protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
523 checkArgument(original instanceof UnkeyedListEntryNode);
524 return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original);
528 public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy<AugmentationSchema> {
530 protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
531 super(createAugmentProxy(schema,resolved), AugmentationNode.class);
535 @SuppressWarnings("rawtypes")
536 protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
537 checkArgument(original instanceof AugmentationNode);
538 return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original);
542 public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
544 private final Map<PathArgument, ModificationApplyOperation> childNodes;
546 public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
547 super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
548 ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
550 for (ChoiceCaseNode caze : schemaNode.getCases()) {
551 for (DataSchemaNode cazeChild : caze.getChildNodes()) {
552 SchemaAwareApplyOperation childNode = from(cazeChild);
553 child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
556 childNodes = child.build();
560 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
561 return Optional.fromNullable(childNodes.get(child));
565 @SuppressWarnings("rawtypes")
566 protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
567 checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
568 return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original);
572 public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
574 protected ListEntryModificationStrategy(final ListSchemaNode schema) {
575 super(schema, MapEntryNode.class);
579 @SuppressWarnings("rawtypes")
580 protected final DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
581 checkArgument(original instanceof MapEntryNode);
582 return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original);
586 public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
588 private final Optional<ModificationApplyOperation> entryStrategy;
590 @SuppressWarnings({ "unchecked", "rawtypes" })
591 protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
592 super((Class) LeafSetNode.class);
593 entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
596 @SuppressWarnings("rawtypes")
598 protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
599 checkArgument(original instanceof LeafSetNode<?>);
600 return ImmutableLeafSetNodeBuilder.create((LeafSetNode<?>) original);
604 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
605 if (identifier instanceof NodeWithValue) {
606 return entryStrategy;
608 return Optional.absent();
612 public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
614 private final Optional<ModificationApplyOperation> entryStrategy;
616 @SuppressWarnings({ "unchecked", "rawtypes" })
617 protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
618 super((Class) LeafSetNode.class);
619 entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
622 @SuppressWarnings("rawtypes")
624 protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
625 checkArgument(original instanceof OrderedLeafSetNode<?>);
626 return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode<?>) original);
630 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
631 if (identifier instanceof NodeWithValue) {
632 return entryStrategy;
634 return Optional.absent();
638 public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
640 private final Optional<ModificationApplyOperation> entryStrategy;
642 protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
643 entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
647 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
648 final UnsignedLong subtreeVersion) {
649 return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
653 protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
654 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
655 throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
659 protected StoreMetadataNode applyWrite(final NodeModification modification,
660 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
661 return StoreMetadataNode.createRecursively(modification.getWrittenValue(), subtreeVersion);
665 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
666 if (child instanceof NodeIdentifier) {
667 return entryStrategy;
669 return Optional.absent();
673 protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
678 protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
679 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
680 throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
685 public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
687 private final Optional<ModificationApplyOperation> entryStrategy;
689 protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
690 super(MapNode.class);
691 entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
694 @SuppressWarnings("rawtypes")
696 protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
697 checkArgument(original instanceof MapNode);
698 return ImmutableMapNodeBuilder.create((MapNode) original);
702 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
703 if (identifier instanceof NodeIdentifierWithPredicates) {
704 return entryStrategy;
706 return Optional.absent();
710 public String toString() {
711 return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
715 public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
717 private final Optional<ModificationApplyOperation> entryStrategy;
719 protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
720 super(OrderedMapNode.class);
721 entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
724 @SuppressWarnings("rawtypes")
726 protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
727 checkArgument(original instanceof OrderedMapNode);
728 return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original);
732 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
733 if (identifier instanceof NodeIdentifierWithPredicates) {
734 return entryStrategy;
736 return Optional.absent();
740 public String toString() {
741 return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
745 public static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
746 Set<DataSchemaNode> realChildSchemas = new HashSet<>();
747 for(DataSchemaNode augChild : schema.getChildNodes()) {
748 realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
750 return new AugmentationSchemaProxy(schema, realChildSchemas);
753 public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException {
755 throw new DataPreconditionFailedException(path, message);