2 * Copyright (c) 2015 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.yangtools.yang.data.impl.schema;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static com.google.common.base.Preconditions.checkNotNull;
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;
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;
45 * Base strategy for converting an instance identifier into a normalized node structure for container-like types.
47 abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathArgument> extends
48 InstanceIdToNodes<T> {
50 protected InstanceIdToCompositeNodes(final T identifier) {
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());
59 return new YangInstanceIdentifier.AugmentationIdentifier(potentialChildren.build());
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()));
67 return new EffectiveAugmentationSchema(augmentation, children);
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();
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());
81 final NormalizedNodeContainerBuilder builder = createBuilder(legacyData);
83 if (iterator.hasNext()) {
84 final YangInstanceIdentifier.PathArgument childPath = iterator.next();
85 final InstanceIdToNodes childOp = getChildOperation(childPath);
87 final YangInstanceIdentifier childId = YangInstanceIdentifier.create(Iterables.skip(instanceId.getPathArguments(), 1));
88 builder.addChild(childOp.create(childId, lastChild, operation));
90 if(lastChild.isPresent()) {
91 builder.withValue(Lists.newArrayList((Collection<?>) lastChild.get().getValue()));
93 if(operation.isPresent()) {
94 Preconditions.checkArgument(builder instanceof AttributesBuilder<?>);
95 addModifyOpIfPresent(operation, ((AttributesBuilder<?>) builder));
99 return builder.build();
102 private InstanceIdToNodes getChildOperation(final YangInstanceIdentifier.PathArgument childPath) {
103 final InstanceIdToNodes childOp;
105 childOp = getChild(childPath);
106 } catch (final RuntimeException e) {
107 throw new IllegalArgumentException(String.format("Failed to process child node %s", childPath), e);
109 checkArgument(childOp != null, "Node %s is not allowed inside %s", childPath, getIdentifier());
113 @SuppressWarnings("rawtypes")
114 protected abstract NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode);
116 static abstract class DataContainerNormalizationOperation<T extends YangInstanceIdentifier.PathArgument> extends
117 InstanceIdToCompositeNodes<T> {
119 private final DataNodeContainer schema;
120 private final Map<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArg;
122 protected DataContainerNormalizationOperation(final T identifier, final DataNodeContainer schema) {
124 this.schema = schema;
125 this.byArg = new ConcurrentHashMap<>();
129 public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
130 InstanceIdToNodes<?> potential = byArg.get(child);
131 if (potential != null) {
134 potential = fromLocalSchema(child);
135 return register(potential);
138 private InstanceIdToNodes<?> fromLocalSchema(final YangInstanceIdentifier.PathArgument child) {
139 if (child instanceof YangInstanceIdentifier.AugmentationIdentifier) {
140 return fromSchemaAndQNameChecked(schema, ((YangInstanceIdentifier.AugmentationIdentifier) child).getPossibleChildNames()
143 return fromSchemaAndQNameChecked(schema, child.getNodeType());
146 private InstanceIdToNodes<?> register(final InstanceIdToNodes<?> potential) {
147 if (potential != null) {
148 byArg.put(potential.getIdentifier(), potential);
154 static final class ListItemNormalization extends
155 DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifierWithPredicates> {
157 protected ListItemNormalization(final YangInstanceIdentifier.NodeIdentifierWithPredicates identifier, final ListSchemaNode schema) {
158 super(identifier, schema);
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()
168 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(keyValue.getKey())).withValue(keyValue.getValue())
176 static final class UnkeyedListItemNormalization extends DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifier> {
178 protected UnkeyedListItemNormalization(final ListSchemaNode schema) {
179 super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()), schema);
183 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
184 return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier());
189 static final class ContainerTransformation extends DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifier> {
191 protected ContainerTransformation(final ContainerSchemaNode schema) {
192 super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()), schema);
196 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
197 return Builders.containerBuilder().withNodeIdentifier(getIdentifier());
201 static final class OrderedLeafListMixinNormalization extends UnorderedLeafListMixinNormalization {
204 public OrderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
209 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
210 return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier());
214 static class UnorderedLeafListMixinNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
216 private final InstanceIdToNodes<?> innerOp;
218 public UnorderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
219 super(new YangInstanceIdentifier.NodeIdentifier(potential.getQName()));
220 innerOp = new InstanceIdToSimpleNodes.LeafListEntryNormalization(potential);
224 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
225 return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier());
229 public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
230 if (child instanceof YangInstanceIdentifier.NodeWithValue) {
237 static final class AugmentationNormalization extends DataContainerNormalizationOperation<YangInstanceIdentifier.AugmentationIdentifier> implements MixinNormalizationOp {
239 public AugmentationNormalization(final AugmentationSchema augmentation, final DataNodeContainer schema) {
240 super(augmentationIdentifierFrom(augmentation), augmentationProxy(augmentation, schema));
244 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
245 return Builders.augmentationBuilder().withNodeIdentifier(getIdentifier());
249 static class UnorderedMapMixinNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
251 private final ListItemNormalization innerNode;
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);
260 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
261 return Builders.mapBuilder().withNodeIdentifier(getIdentifier());
265 public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
266 if (child.getNodeType().equals(getIdentifier().getNodeType())) {
273 static final class OrderedMapMixinNormalization extends UnorderedMapMixinNormalization {
275 public OrderedMapMixinNormalization(final ListSchemaNode list) {
280 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
281 return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier());
286 static class ChoiceNodeNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
288 private final ImmutableMap<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArg;
290 protected ChoiceNodeNormalization(final ChoiceSchemaNode schema) {
291 super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()));
292 final ImmutableMap.Builder<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArgBuilder = ImmutableMap.builder();
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);
300 byArg = byArgBuilder.build();
304 public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
305 return byArg.get(child);
309 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
310 return Builders.choiceBuilder().withNodeIdentifier(getIdentifier());