Removed unused dependency.
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / InstanceIdToCompositeNodes.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.data.impl.schema;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static com.google.common.base.Preconditions.checkNotNull;
12
13 import com.google.common.base.Optional;
14 import com.google.common.base.Preconditions;
15 import com.google.common.collect.ImmutableMap;
16 import com.google.common.collect.ImmutableSet;
17 import com.google.common.collect.Iterables;
18 import com.google.common.collect.Lists;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.Map;
24 import java.util.Set;
25 import java.util.concurrent.ConcurrentHashMap;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
31 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder;
32 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
33 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
34 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
35 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
36 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
37 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
38 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
39 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
40 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
42 import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
43
44 /**
45 * Base strategy for converting an instance identifier into a normalized node structure for container-like types.
46 */
47 abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathArgument> extends
48         InstanceIdToNodes<T> {
49
50     protected InstanceIdToCompositeNodes(final T identifier) {
51         super(identifier);
52     }
53
54     private static YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchema augmentation) {
55         final ImmutableSet.Builder<QName> potentialChildren = ImmutableSet.builder();
56         for (final DataSchemaNode child : augmentation.getChildNodes()) {
57             potentialChildren.add(child.getQName());
58         }
59         return new YangInstanceIdentifier.AugmentationIdentifier(potentialChildren.build());
60     }
61
62     private static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation, final DataNodeContainer schema) {
63         final Set<DataSchemaNode> children = new HashSet<>();
64         for (final DataSchemaNode augNode : augmentation.getChildNodes()) {
65             children.add(schema.getDataChildByName(augNode.getQName()));
66         }
67         return new EffectiveAugmentationSchema(augmentation, children);
68     }
69
70     @Override
71     @SuppressWarnings("unchecked")
72     public final NormalizedNode<?, ?> create(final YangInstanceIdentifier instanceId, final Optional<NormalizedNode<?, ?>> lastChild, final Optional<Map.Entry<QName,ModifyAction>> operation) {
73         checkNotNull(instanceId);
74         final Iterator<YangInstanceIdentifier.PathArgument> iterator = instanceId.getPathArguments().iterator();
75         final YangInstanceIdentifier.PathArgument legacyData = iterator.next();
76
77         if (!isMixin(this) && getIdentifier().getNodeType() != null) {
78             checkArgument(getIdentifier().getNodeType().equals(legacyData.getNodeType()),
79                     "Node QName must be %s was %s", getIdentifier().getNodeType(), legacyData.getNodeType());
80         }
81         final NormalizedNodeContainerBuilder builder = createBuilder(legacyData);
82
83         if (iterator.hasNext()) {
84             final YangInstanceIdentifier.PathArgument childPath = iterator.next();
85             final InstanceIdToNodes childOp = getChildOperation(childPath);
86
87             final YangInstanceIdentifier childId = YangInstanceIdentifier.create(Iterables.skip(instanceId.getPathArguments(), 1));
88             builder.addChild(childOp.create(childId, lastChild, operation));
89         } else {
90             if(lastChild.isPresent()) {
91                 builder.withValue(Lists.newArrayList((Collection<?>) lastChild.get().getValue()));
92             }
93             if(operation.isPresent()) {
94                 Preconditions.checkArgument(builder instanceof AttributesBuilder<?>);
95                 addModifyOpIfPresent(operation, ((AttributesBuilder<?>) builder));
96             }
97         }
98
99         return builder.build();
100     }
101
102     private InstanceIdToNodes getChildOperation(final YangInstanceIdentifier.PathArgument childPath) {
103         final InstanceIdToNodes childOp;
104         try {
105             childOp = getChild(childPath);
106         } catch (final RuntimeException e) {
107             throw new IllegalArgumentException(String.format("Failed to process child node %s", childPath), e);
108         }
109         checkArgument(childOp != null, "Node %s is not allowed inside %s", childPath, getIdentifier());
110         return childOp;
111     }
112
113     @SuppressWarnings("rawtypes")
114     protected abstract NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode);
115
116     static abstract class DataContainerNormalizationOperation<T extends YangInstanceIdentifier.PathArgument> extends
117             InstanceIdToCompositeNodes<T> {
118
119         private final DataNodeContainer schema;
120         private final Map<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArg;
121
122         protected DataContainerNormalizationOperation(final T identifier, final DataNodeContainer schema) {
123             super(identifier);
124             this.schema = schema;
125             this.byArg = new ConcurrentHashMap<>();
126         }
127
128         @Override
129         public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
130             InstanceIdToNodes<?> potential = byArg.get(child);
131             if (potential != null) {
132                 return potential;
133             }
134             potential = fromLocalSchema(child);
135             return register(potential);
136         }
137
138         private InstanceIdToNodes<?> fromLocalSchema(final YangInstanceIdentifier.PathArgument child) {
139             if (child instanceof YangInstanceIdentifier.AugmentationIdentifier) {
140                 return fromSchemaAndQNameChecked(schema, ((YangInstanceIdentifier.AugmentationIdentifier) child).getPossibleChildNames()
141                         .iterator().next());
142             }
143             return fromSchemaAndQNameChecked(schema, child.getNodeType());
144         }
145
146         private InstanceIdToNodes<?> register(final InstanceIdToNodes<?> potential) {
147             if (potential != null) {
148                 byArg.put(potential.getIdentifier(), potential);
149             }
150             return potential;
151         }
152     }
153
154     static final class ListItemNormalization extends
155             DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifierWithPredicates> {
156
157         protected ListItemNormalization(final YangInstanceIdentifier.NodeIdentifierWithPredicates identifier, final ListSchemaNode schema) {
158             super(identifier, schema);
159         }
160
161         @Override
162         protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument currentArg) {
163             final DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> builder = Builders
164                     .mapEntryBuilder().withNodeIdentifier((YangInstanceIdentifier.NodeIdentifierWithPredicates) currentArg);
165             for (final Map.Entry<QName, Object> keyValue : ((YangInstanceIdentifier.NodeIdentifierWithPredicates) currentArg).getKeyValues().entrySet()) {
166                 builder.addChild(Builders.leafBuilder()
167                         //
168                         .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(keyValue.getKey())).withValue(keyValue.getValue())
169                         .build());
170             }
171             return builder;
172         }
173
174     }
175
176     static final class UnkeyedListItemNormalization extends DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifier> {
177
178         protected UnkeyedListItemNormalization(final ListSchemaNode schema) {
179             super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()), schema);
180         }
181
182         @Override
183         protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
184             return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier());
185         }
186
187     }
188
189     static final class ContainerTransformation extends DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifier> {
190
191         protected ContainerTransformation(final ContainerSchemaNode schema) {
192             super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()), schema);
193         }
194
195         @Override
196         protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
197             return Builders.containerBuilder().withNodeIdentifier(getIdentifier());
198         }
199     }
200
201     static final class OrderedLeafListMixinNormalization extends UnorderedLeafListMixinNormalization {
202
203
204         public OrderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
205             super(potential);
206         }
207
208         @Override
209         protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
210             return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier());
211         }
212     }
213
214     static class UnorderedLeafListMixinNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
215
216         private final InstanceIdToNodes<?> innerOp;
217
218         public UnorderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
219             super(new YangInstanceIdentifier.NodeIdentifier(potential.getQName()));
220             innerOp = new InstanceIdToSimpleNodes.LeafListEntryNormalization(potential);
221         }
222
223         @Override
224         protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
225             return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier());
226         }
227
228         @Override
229         public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
230             if (child instanceof YangInstanceIdentifier.NodeWithValue) {
231                 return innerOp;
232             }
233             return null;
234         }
235     }
236
237     static final class AugmentationNormalization extends DataContainerNormalizationOperation<YangInstanceIdentifier.AugmentationIdentifier> implements MixinNormalizationOp {
238
239         public AugmentationNormalization(final AugmentationSchema augmentation, final DataNodeContainer schema) {
240             super(augmentationIdentifierFrom(augmentation), augmentationProxy(augmentation, schema));
241         }
242
243         @Override
244         protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
245             return Builders.augmentationBuilder().withNodeIdentifier(getIdentifier());
246         }
247     }
248
249     static class UnorderedMapMixinNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
250
251         private final ListItemNormalization innerNode;
252
253         public UnorderedMapMixinNormalization(final ListSchemaNode list) {
254             super(new YangInstanceIdentifier.NodeIdentifier(list.getQName()));
255             this.innerNode = new ListItemNormalization(new YangInstanceIdentifier.NodeIdentifierWithPredicates(list.getQName(),
256                     Collections.<QName, Object>emptyMap()), list);
257         }
258
259         @Override
260         protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
261             return Builders.mapBuilder().withNodeIdentifier(getIdentifier());
262         }
263
264         @Override
265         public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
266             if (child.getNodeType().equals(getIdentifier().getNodeType())) {
267                 return innerNode;
268             }
269             return null;
270         }
271     }
272
273     static final class OrderedMapMixinNormalization extends UnorderedMapMixinNormalization {
274
275         public OrderedMapMixinNormalization(final ListSchemaNode list) {
276             super(list);
277         }
278
279         @Override
280         protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
281             return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier());
282         }
283
284     }
285
286     static class ChoiceNodeNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
287
288         private final ImmutableMap<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArg;
289
290         protected ChoiceNodeNormalization(final ChoiceSchemaNode schema) {
291             super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()));
292             final ImmutableMap.Builder<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArgBuilder = ImmutableMap.builder();
293
294             for (final ChoiceCaseNode caze : schema.getCases()) {
295                 for (final DataSchemaNode cazeChild : caze.getChildNodes()) {
296                     final InstanceIdToNodes<?> childOp = fromDataSchemaNode(cazeChild);
297                     byArgBuilder.put(childOp.getIdentifier(), childOp);
298                 }
299             }
300             byArg = byArgBuilder.build();
301         }
302
303         @Override
304         public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
305             return byArg.get(child);
306         }
307
308         @Override
309         protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
310             return Builders.choiceBuilder().withNodeIdentifier(getIdentifier());
311         }
312     }
313 }