1 package org.opendaylight.controller.md.sal.dom.store.impl;
3 import static com.google.common.base.Preconditions.checkArgument;
7 import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
8 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
9 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder;
10 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
11 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
12 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
13 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
14 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
15 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
16 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
17 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
18 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
19 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
20 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
21 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
22 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
24 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
29 import com.google.common.base.Optional;
30 import com.google.common.collect.ImmutableSet;
31 import com.google.common.collect.ImmutableSet.Builder;
32 import com.google.common.primitives.UnsignedLong;
34 public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
36 public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
37 if (schemaNode instanceof ContainerSchemaNode) {
38 return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
39 } else if (schemaNode instanceof ListSchemaNode) {
40 return new ListMapModificationStrategy((ListSchemaNode) schemaNode);
41 } else if (schemaNode instanceof ChoiceNode) {
42 return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
43 } else if (schemaNode instanceof LeafListSchemaNode) {
44 return new LeafSetEntryModificationStrategy((LeafListSchemaNode) schemaNode);
45 } else if (schemaNode instanceof LeafSchemaNode) {
46 return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
48 throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
52 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
53 throw new IllegalArgumentException();
56 protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
57 Optional<ModificationApplyOperation> potential = getChild(child);
58 checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
59 return potential.get();
63 public final Optional<StoreMetadataNode> apply(final NodeModification modification,
64 final Optional<StoreMetadataNode> currentMeta) {
65 switch (modification.getModificationType()) {
67 return Optional.absent();
68 case SUBTREE_MODIFIED:
69 return Optional.of(applySubtreeChange(modification, currentMeta.get()));
71 return Optional.of(applyWrite(modification, currentMeta));
75 throw new IllegalArgumentException("Provided modification type is not supported.");
79 protected abstract StoreMetadataNode applyWrite(NodeModification modification,
80 Optional<StoreMetadataNode> currentMeta);
82 protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification, StoreMetadataNode currentMeta);
84 public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends
85 SchemaAwareApplyOperation {
87 private final T schema;
89 protected ValueNodeModificationStrategy(final T schema) {
95 public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
96 throw new UnsupportedOperationException("Node " + schema.getPath()
97 + "is leaf type node. Child nodes not allowed");
101 protected StoreMetadataNode applySubtreeChange(final NodeModification modification, final StoreMetadataNode currentMeta) {
102 throw new UnsupportedOperationException("Node " + schema.getPath()
103 + "is leaf type node. Subtree change is not allowed.");
107 protected StoreMetadataNode applyWrite(final NodeModification modification, final Optional<StoreMetadataNode> currentMeta) {
108 return StoreMetadataNode.builder()
109 // FIXME Add .increaseNodeVersion()
110 .setData(modification.getWritenValue()).build();
115 public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
117 protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
122 public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
124 protected LeafModificationStrategy(final LeafSchemaNode schema) {
129 public static abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
132 protected StoreMetadataNode applyWrite(final NodeModification modification, final Optional<StoreMetadataNode> currentMeta) {
134 NormalizedNode<?, ?> newValue = modification.getWritenValue();
136 StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursivelly(newValue, UnsignedLong.valueOf(0));
138 if(!modification.hasAdditionalModifications()) {
141 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(newValueMeta,
142 createBuilder(modification.getIdentifier()));
144 Set<PathArgument> processedPreexisting = applyPreexistingChildren(modification, newValueMeta.getChildren(), builder);
145 applyNewChildren(modification, processedPreexisting, builder);
147 return builder.build();
152 @SuppressWarnings("rawtypes")
153 public StoreMetadataNode applySubtreeChange(final NodeModification modification, final StoreMetadataNode currentMeta) {
155 StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(currentMeta,
156 createBuilder(modification.getIdentifier()));
157 builder.setIdentifier(modification.getIdentifier());
159 // We process preexisting nodes
160 Set<PathArgument> processedPreexisting = applyPreexistingChildren(modification,
161 currentMeta.getChildren(), builder);
162 applyNewChildren(modification, processedPreexisting, builder);
163 return builder.build();
166 private void applyNewChildren(final NodeModification modification, final Set<PathArgument> ignore,
167 final StoreNodeCompositeBuilder builder) {
168 for (NodeModification childModification : modification.getModifications()) {
169 PathArgument childIdentifier = childModification.getIdentifier();
170 // We skip allready processed modifications
171 if (ignore.contains(childIdentifier)) {
174 Optional<StoreMetadataNode> childResult = resolveChildOperation(childIdentifier) //
175 .apply(childModification, Optional.<StoreMetadataNode> absent());
176 if (childResult.isPresent()) {
177 builder.add(childResult.get());
182 private Set<PathArgument> applyPreexistingChildren(final NodeModification modification,
183 final Iterable<StoreMetadataNode> children, final StoreNodeCompositeBuilder nodeBuilder) {
184 Builder<PathArgument> processedModifications = ImmutableSet.<PathArgument> builder();
185 for (StoreMetadataNode childMeta : children) {
186 PathArgument childIdentifier = childMeta.getIdentifier();
187 // We retrieve Child modification metadata
188 Optional<NodeModification> childModification = modification.getChild(childIdentifier);
190 if (childModification.isPresent()) {
191 processedModifications.add(childIdentifier);
192 Optional<StoreMetadataNode> change = resolveChildOperation(childIdentifier) //
193 .apply(childModification.get(), Optional.of(childMeta));
195 // Child is unmodified - reuse existing metadata and data
197 nodeBuilder.add(childMeta);
200 return processedModifications.build();
203 @SuppressWarnings("rawtypes")
204 protected abstract NormalizedNodeContainerBuilder createBuilder(PathArgument identifier);
207 public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends
208 NormalizedNodeContainerModificationStrategy {
210 private final T schema;
212 protected DataNodeContainerModificationStrategy(final T schema) {
214 this.schema = schema;
217 protected T getSchema() {
222 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
223 DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
224 if (child == null || child.isAugmenting()) {
225 return Optional.absent();
227 return Optional.<ModificationApplyOperation> of(from(child));
231 @SuppressWarnings("rawtypes")
232 protected abstract DataContainerNodeBuilder createBuilder(PathArgument identifier);
235 public String toString() {
236 return getClass().getSimpleName() + " [" + schema + "]";
241 public static class ContainerModificationStrategy extends
242 DataNodeContainerModificationStrategy<ContainerSchemaNode> {
244 public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
249 @SuppressWarnings("rawtypes")
250 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
251 // TODO Auto-generated method stub
252 checkArgument(identifier instanceof NodeIdentifier);
253 return ImmutableContainerNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
258 public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
260 private final ChoiceNode schema;
262 public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
263 this.schema = schemaNode;
267 @SuppressWarnings("rawtypes")
268 protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
269 checkArgument(identifier instanceof NodeIdentifier);
270 return ImmutableContainerNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
275 public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
277 protected ListEntryModificationStrategy(final ListSchemaNode schema) {
282 @SuppressWarnings("rawtypes")
283 protected final DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
284 return ImmutableMapEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifierWithPredicates) identifier);
289 public static class LeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
291 private final Optional<ModificationApplyOperation> entryStrategy;
293 protected LeafSetModificationStrategy(final LeafListSchemaNode schema) {
294 entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
298 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
299 return ImmutableLeafSetNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
303 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
304 if (identifier instanceof NodeWithValue) {
305 return entryStrategy;
307 return Optional.absent();
312 public static class ListMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
314 private final Optional<ModificationApplyOperation> entryStrategy;
316 protected ListMapModificationStrategy(final ListSchemaNode schema) {
317 entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
321 protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
322 return ImmutableMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
326 public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
327 if (identifier instanceof NodeIdentifierWithPredicates) {
328 return entryStrategy;
330 return Optional.absent();
334 public String toString() {
335 return "ListMapModificationStrategy [entry=" + entryStrategy + "]";
339 public void verifyIdentifier(final PathArgument identifier) {