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.ModificationType;
19 import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
20 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
21 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
24 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
27 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
28 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
29 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
38 import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
41 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
42 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
43 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
44 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
45 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
46 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
47 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
48 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
49 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
50 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
51 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
52 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
53 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
54 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
55 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
56 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
57 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
58 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
59 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
60 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
61 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
62 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
64 import com.google.common.base.Function;
65 import com.google.common.base.Optional;
66 import com.google.common.base.Preconditions;
67 import com.google.common.cache.CacheBuilder;
68 import com.google.common.cache.CacheLoader;
69 import com.google.common.cache.LoadingCache;
70 import com.google.common.collect.ImmutableMap;
71 import com.google.common.primitives.UnsignedLong;
73 public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
75 public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
76 if (schemaNode instanceof ContainerSchemaNode) {
77 return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
78 } else if (schemaNode instanceof ListSchemaNode) {
79 return fromListSchemaNode((ListSchemaNode) schemaNode);
80 } else if (schemaNode instanceof ChoiceNode) {
81 return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
82 } else if (schemaNode instanceof LeafListSchemaNode) {
83 return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
84 } else if (schemaNode instanceof LeafSchemaNode) {
85 return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
87 throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
90 private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
91 List<QName> keyDefinition = schemaNode.getKeyDefinition();
92 if (keyDefinition == null || keyDefinition.isEmpty()) {
93 return new UnkeyedListModificationStrategy(schemaNode);
95 if (schemaNode.isUserOrdered()) {
96 return new OrderedMapModificationStrategy(schemaNode);
99 return new UnorderedMapModificationStrategy(schemaNode);
102 private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
103 if(schemaNode.isUserOrdered()) {
104 return new OrderedLeafSetModificationStrategy(schemaNode);
106 return new UnorderedLeafSetModificationStrategy(schemaNode);
111 public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
112 final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
113 AugmentationSchema augSchema = null;
114 allAugments: for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
115 boolean containsAll = true;
116 for (DataSchemaNode child : potential.getChildNodes()) {
117 if (identifier.getPossibleChildNames().contains(child.getQName())) {
118 augSchema = potential;
123 if (augSchema != null) {
124 return new AugmentationModificationStrategy(augSchema, resolvedTree);
129 protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
130 Optional<ModificationApplyOperation> potential = getChild(child);
131 checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
132 return potential.get();
136 public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
137 if (modification.getModificationType() == ModificationType.WRITE) {
138 verifyWritenStructure(modification.getWritenValue());
142 protected abstract void verifyWritenStructure(NormalizedNode<?, ?> writenValue);
145 public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
146 switch (modification.getModificationType()) {
148 checkDeleteApplicable(modification, current);
149 case SUBTREE_MODIFIED:
150 checkSubtreeModificationApplicable(path,modification, current);
153 checkWriteApplicable(path,modification, current);
156 checkMergeApplicable(path,modification,current);
161 throw new UnsupportedOperationException("Suplied modification type "+modification.getModificationType()+ "is not supported.");
166 protected void checkMergeApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
167 Optional<StoreMetadataNode> original = modification.getOriginal();
168 if (original.isPresent() && current.isPresent()) {
169 checkNotConflicting(path,original.get(), current.get());
173 protected void checkWriteApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
174 Optional<StoreMetadataNode> original = modification.getOriginal();
175 if (original.isPresent() && current.isPresent()) {
176 checkNotConflicting(path,original.get(), current.get());
177 } else if(original.isPresent()) {
178 throw new DataPreconditionFailedException(path,"Node was deleted by other transaction.");
182 protected static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException {
183 checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction.");
184 checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction");
187 protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification,
188 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
190 private void checkDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
194 public final Optional<StoreMetadataNode> apply(final NodeModification modification,
195 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
197 switch (modification.getModificationType()) {
199 return modification.storeSnapshot(Optional.<StoreMetadataNode> absent());
200 case SUBTREE_MODIFIED:
201 Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
203 return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
206 if(currentMeta.isPresent()) {
207 return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(),subtreeVersion)));
208 } // Fallback to write is intentional - if node is not preexisting merge is same as write
210 return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, subtreeVersion)));
214 throw new IllegalArgumentException("Provided modification type is not supported.");
218 protected abstract StoreMetadataNode applyMerge(NodeModification modification,
219 StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
221 protected abstract StoreMetadataNode applyWrite(NodeModification modification,
222 Optional<StoreMetadataNode> currentMeta, UnsignedLong subtreeVersion);
224 protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification,
225 StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
227 public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends
228 SchemaAwareApplyOperation {
230 private final T schema;
231 private final Class<? extends NormalizedNode<?, ?>> nodeClass;
233 protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
235 this.schema = schema;
236 this.nodeClass = nodeClass;
240 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
241 checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
245 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
246 throw new UnsupportedOperationException("Node " + schema.getPath()
247 + "is leaf type node. Child nodes not allowed");
251 protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
252 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
253 throw new UnsupportedOperationException("Node " + schema.getPath()
254 + "is leaf type node. Subtree change is not allowed.");
258 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
259 final UnsignedLong subtreeVersion) {
260 return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
264 protected StoreMetadataNode applyWrite(final NodeModification modification,
265 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
266 UnsignedLong nodeVersion = subtreeVersion;
267 return StoreMetadataNode.builder().setNodeVersion(nodeVersion).setSubtreeVersion(subtreeVersion)
268 .setData(modification.getWritenValue()).build();
272 protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
273 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
274 throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
279 public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
281 @SuppressWarnings({ "unchecked", "rawtypes" })
282 protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
283 super(schema, (Class) LeafSetEntryNode.class);
287 public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
289 @SuppressWarnings({ "unchecked", "rawtypes" })
290 protected LeafModificationStrategy(final LeafSchemaNode schema) {
291 super(schema, (Class) LeafNode.class);
295 public static abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
297 private final Class<? extends NormalizedNode<?, ?>> nodeClass;
299 protected NormalizedNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
300 this.nodeClass = nodeClass;
304 public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
305 if (modification.getModificationType() == ModificationType.WRITE) {
308 for (NodeModification childModification : modification.getModifications()) {
309 resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
314 protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification,
315 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
316 // FIXME: Implement proper write check for replacement of node container
317 // prerequisite is to have transaction chain available for clients
318 // otherwise this will break chained writes to same node.
321 @SuppressWarnings("rawtypes")
323 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
324 checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
325 checkArgument(writenValue instanceof NormalizedNodeContainer);
326 NormalizedNodeContainer writenCont = (NormalizedNodeContainer) writenValue;
327 for (Object child : writenCont.getValue()) {
328 checkArgument(child instanceof NormalizedNode);
329 NormalizedNode childNode = (NormalizedNode) child;
334 protected StoreMetadataNode applyWrite(final NodeModification modification,
335 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
337 NormalizedNode<?, ?> newValue = modification.getWritenValue();
339 final UnsignedLong nodeVersion;
340 if (currentMeta.isPresent()) {
341 nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion());
343 nodeVersion = subtreeVersion;
346 final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion);
347 if (!modification.hasAdditionalModifications()) {
351 @SuppressWarnings("rawtypes")
352 NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
353 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder) //
354 .setNodeVersion(nodeVersion) //
355 .setSubtreeVersion(subtreeVersion);
357 return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion);
361 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
362 final UnsignedLong subtreeVersion) {
363 // For Node Containers - merge is same as subtree change - we only replace children.
364 return applySubtreeChange(modification, currentMeta, subtreeVersion);
368 public StoreMetadataNode applySubtreeChange(final NodeModification modification,
369 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
370 // Bump subtree version to its new target
371 final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion());
373 @SuppressWarnings("rawtypes")
374 NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
375 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder, currentMeta)
376 .setIdentifier(modification.getIdentifier()).setNodeVersion(currentMeta.getNodeVersion())
377 .setSubtreeVersion(updatedSubtreeVersion);
379 return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion);
382 private StoreMetadataNode mutateChildren(final Iterable<NodeModification> modifications, final StoreMetadataNode meta,
383 final StoreNodeCompositeBuilder builder, final UnsignedLong nodeVersion) {
385 for (NodeModification mod : modifications) {
386 final PathArgument id = mod.getIdentifier();
387 final Optional<StoreMetadataNode> cm = meta.getChild(id);
389 Optional<StoreMetadataNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
390 if (result.isPresent()) {
391 builder.add(result.get());
397 return builder.build();
401 protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
402 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
403 checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction.");
404 checkChildPreconditions(path,modification,current);
408 private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
409 StoreMetadataNode currentMeta = current.get();
410 for (NodeModification childMod : modification.getModifications()) {
411 PathArgument childId = childMod.getIdentifier();
412 Optional<StoreMetadataNode> childMeta = currentMeta.getChild(childId);
413 InstanceIdentifier childPath = StoreUtils.append(path, childId);
414 resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta);
419 protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification,
420 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
421 if(current.isPresent()) {
422 checkChildPreconditions(path,modification,current);
426 @SuppressWarnings("rawtypes")
427 protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
430 public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends
431 NormalizedNodeContainerModificationStrategy {
433 private final T schema;
434 private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
435 .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
438 public ModificationApplyOperation apply(final PathArgument identifier) {
439 if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
440 return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier);
443 DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
451 protected DataNodeContainerModificationStrategy(final T schema,
452 final Class<? extends NormalizedNode<?, ?>> nodeClass) {
454 this.schema = schema;
457 protected T getSchema() {
462 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
464 return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
465 } catch (ExecutionException e) {
466 return Optional.absent();
471 @SuppressWarnings("rawtypes")
472 protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original);
475 public String toString() {
476 return getClass().getSimpleName() + " [" + schema + "]";
481 public static class ContainerModificationStrategy extends
482 DataNodeContainerModificationStrategy<ContainerSchemaNode> {
484 public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
485 super(schemaNode, ContainerNode.class);
489 @SuppressWarnings("rawtypes")
490 protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
491 checkArgument(original instanceof ContainerNode);
492 return ImmutableContainerNodeBuilder.create((ContainerNode) original);
496 public static class UnkeyedListItemModificationStrategy extends
497 DataNodeContainerModificationStrategy<ListSchemaNode> {
499 public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
500 super(schemaNode, UnkeyedListEntryNode.class);
504 @SuppressWarnings("rawtypes")
505 protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
506 checkArgument(original instanceof UnkeyedListEntryNode);
507 return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original);
511 public static class AugmentationModificationStrategy extends
512 DataNodeContainerModificationStrategy<AugmentationSchema> {
514 protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
515 super(createAugmentProxy(schema,resolved), AugmentationNode.class);
519 @SuppressWarnings("rawtypes")
520 protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
521 checkArgument(original instanceof AugmentationNode);
522 return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original);
526 public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
528 private final ChoiceNode schema;
529 private final Map<PathArgument, ModificationApplyOperation> childNodes;
531 public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
532 super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
533 this.schema = schemaNode;
534 ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
536 for (ChoiceCaseNode caze : schemaNode.getCases()) {
537 for (DataSchemaNode cazeChild : caze.getChildNodes()) {
538 SchemaAwareApplyOperation childNode = from(cazeChild);
539 child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
542 childNodes = child.build();
546 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
547 return Optional.fromNullable(childNodes.get(child));
551 @SuppressWarnings("rawtypes")
552 protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
553 checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
554 return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original);
558 public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
560 protected ListEntryModificationStrategy(final ListSchemaNode schema) {
561 super(schema, MapEntryNode.class);
565 @SuppressWarnings("rawtypes")
566 protected final DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
567 checkArgument(original instanceof MapEntryNode);
568 return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original);
572 public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
574 private final Optional<ModificationApplyOperation> entryStrategy;
576 @SuppressWarnings({ "unchecked", "rawtypes" })
577 protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
578 super((Class) LeafSetNode.class);
579 entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
582 @SuppressWarnings("rawtypes")
584 protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
585 checkArgument(original instanceof LeafSetNode<?>);
586 return ImmutableLeafSetNodeBuilder.create((LeafSetNode<?>) original);
590 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
591 if (identifier instanceof NodeWithValue) {
592 return entryStrategy;
594 return Optional.absent();
598 public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
600 private final Optional<ModificationApplyOperation> entryStrategy;
602 @SuppressWarnings({ "unchecked", "rawtypes" })
603 protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
604 super((Class) LeafSetNode.class);
605 entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
608 @SuppressWarnings("rawtypes")
610 protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
611 checkArgument(original instanceof OrderedLeafSetNode<?>);
612 return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode<?>) original);
616 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
617 if (identifier instanceof NodeWithValue) {
618 return entryStrategy;
620 return Optional.absent();
624 public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
626 private final Optional<ModificationApplyOperation> entryStrategy;
628 protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
629 entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
633 protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
634 final UnsignedLong subtreeVersion) {
635 return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
639 protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
640 final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
641 throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
645 protected StoreMetadataNode applyWrite(final NodeModification modification,
646 final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
647 return StoreMetadataNode.createRecursively(modification.getWritenValue(), subtreeVersion);
651 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
652 if (child instanceof NodeIdentifier) {
653 return entryStrategy;
655 return Optional.absent();
659 protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
664 protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
665 final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
666 throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
671 public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
673 private final Optional<ModificationApplyOperation> entryStrategy;
675 protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
676 super(MapNode.class);
677 entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
680 @SuppressWarnings("rawtypes")
682 protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
683 checkArgument(original instanceof MapNode);
684 return ImmutableMapNodeBuilder.create((MapNode) original);
688 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
689 if (identifier instanceof NodeIdentifierWithPredicates) {
690 return entryStrategy;
692 return Optional.absent();
696 public String toString() {
697 return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
701 public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
703 private final Optional<ModificationApplyOperation> entryStrategy;
705 protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
706 super(OrderedMapNode.class);
707 entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
710 @SuppressWarnings("rawtypes")
712 protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
713 checkArgument(original instanceof OrderedMapNode);
714 return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original);
718 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
719 if (identifier instanceof NodeIdentifierWithPredicates) {
720 return entryStrategy;
722 return Optional.absent();
726 public String toString() {
727 return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
731 public void verifyIdentifier(final PathArgument identifier) {
735 public static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
736 Set<DataSchemaNode> realChildSchemas = new HashSet<>();
737 for(DataSchemaNode augChild : schema.getChildNodes()) {
738 realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
740 return new AugmentationSchemaProxy(schema, realChildSchemas);
743 public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException {
745 throw new DataPreconditionFailedException(path, message);