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;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Preconditions;
14 import com.google.common.collect.ImmutableMap;
15 import com.google.common.collect.ImmutableSet;
16 import com.google.common.collect.Iterables;
17 import com.google.common.collect.Lists;
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.HashSet;
21 import java.util.Iterator;
24 import java.util.concurrent.ConcurrentHashMap;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
28 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
30 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder;
31 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
32 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
33 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
34 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
35 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
36 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
37 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
38 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
40 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
41 import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
44 * Base strategy for converting an instance identifier into a normalized node structure for container-like types.
46 abstract class InstanceIdToCompositeNodes<T extends YangInstanceIdentifier.PathArgument> extends
47 InstanceIdToNodes<T> {
49 protected InstanceIdToCompositeNodes(final T identifier) {
53 private static YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchema augmentation) {
54 final ImmutableSet.Builder<QName> potentialChildren = ImmutableSet.builder();
55 for (final DataSchemaNode child : augmentation.getChildNodes()) {
56 potentialChildren.add(child.getQName());
58 return new YangInstanceIdentifier.AugmentationIdentifier(potentialChildren.build());
61 private static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation, final DataNodeContainer schema) {
62 final Set<DataSchemaNode> children = new HashSet<>();
63 for (final DataSchemaNode augNode : augmentation.getChildNodes()) {
64 children.add(schema.getDataChildByName(augNode.getQName()));
66 return new EffectiveAugmentationSchema(augmentation, children);
70 @SuppressWarnings("unchecked")
71 public final NormalizedNode<?, ?> create(final YangInstanceIdentifier instanceId, final Optional<NormalizedNode<?, ?>> lastChild, final Optional<Map.Entry<QName,ModifyAction>> operation) {
72 checkNotNull(instanceId);
73 final Iterator<YangInstanceIdentifier.PathArgument> iterator = instanceId.getPathArguments().iterator();
74 final YangInstanceIdentifier.PathArgument legacyData = iterator.next();
76 if (!isMixin(this) && getIdentifier().getNodeType() != null) {
77 checkArgument(getIdentifier().getNodeType().equals(legacyData.getNodeType()),
78 "Node QName must be %s was %s", getIdentifier().getNodeType(), legacyData.getNodeType());
80 final NormalizedNodeContainerBuilder builder = createBuilder(legacyData);
82 if (iterator.hasNext()) {
83 final YangInstanceIdentifier.PathArgument childPath = iterator.next();
84 final InstanceIdToNodes childOp = getChildOperation(childPath);
86 final YangInstanceIdentifier childId = YangInstanceIdentifier.create(Iterables.skip(instanceId.getPathArguments(), 1));
87 builder.addChild(childOp.create(childId, lastChild, operation));
89 if(lastChild.isPresent()) {
90 builder.withValue(Lists.newArrayList((Collection<?>) lastChild.get().getValue()));
92 if(operation.isPresent()) {
93 Preconditions.checkArgument(builder instanceof AttributesBuilder<?>);
94 addModifyOpIfPresent(operation, ((AttributesBuilder<?>) builder));
98 return builder.build();
101 private InstanceIdToNodes getChildOperation(final YangInstanceIdentifier.PathArgument childPath) {
102 final InstanceIdToNodes childOp;
104 childOp = getChild(childPath);
105 } catch (final RuntimeException e) {
106 throw new IllegalArgumentException(String.format("Failed to process child node %s", childPath), e);
108 checkArgument(childOp != null, "Node %s is not allowed inside %s", childPath, getIdentifier());
112 protected abstract NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode);
114 static abstract class DataContainerNormalizationOperation<T extends YangInstanceIdentifier.PathArgument> extends
115 InstanceIdToCompositeNodes<T> {
117 private final DataNodeContainer schema;
118 private final Map<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArg;
120 protected DataContainerNormalizationOperation(final T identifier, final DataNodeContainer schema) {
122 this.schema = schema;
123 this.byArg = new ConcurrentHashMap<>();
127 public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
128 InstanceIdToNodes<?> potential = byArg.get(child);
129 if (potential != null) {
132 potential = fromLocalSchema(child);
133 return register(potential);
136 private InstanceIdToNodes<?> fromLocalSchema(final YangInstanceIdentifier.PathArgument child) {
137 if (child instanceof YangInstanceIdentifier.AugmentationIdentifier) {
138 return fromSchemaAndQNameChecked(schema, ((YangInstanceIdentifier.AugmentationIdentifier) child).getPossibleChildNames()
141 return fromSchemaAndQNameChecked(schema, child.getNodeType());
144 private InstanceIdToNodes<?> register(final InstanceIdToNodes<?> potential) {
145 if (potential != null) {
146 byArg.put(potential.getIdentifier(), potential);
152 static final class ListItemNormalization extends
153 DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifierWithPredicates> {
155 protected ListItemNormalization(final YangInstanceIdentifier.NodeIdentifierWithPredicates identifier, final ListSchemaNode schema) {
156 super(identifier, schema);
160 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument currentArg) {
161 final DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> builder = Builders
162 .mapEntryBuilder().withNodeIdentifier((YangInstanceIdentifier.NodeIdentifierWithPredicates) currentArg);
163 for (final Map.Entry<QName, Object> keyValue : ((YangInstanceIdentifier.NodeIdentifierWithPredicates) currentArg).getKeyValues().entrySet()) {
164 builder.addChild(Builders.leafBuilder()
166 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(keyValue.getKey())).withValue(keyValue.getValue())
174 static final class UnkeyedListItemNormalization extends DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifier> {
176 protected UnkeyedListItemNormalization(final ListSchemaNode schema) {
177 super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()), schema);
181 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
182 return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier());
187 static final class ContainerTransformation extends DataContainerNormalizationOperation<YangInstanceIdentifier.NodeIdentifier> {
189 protected ContainerTransformation(final ContainerSchemaNode schema) {
190 super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()), schema);
194 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
195 return Builders.containerBuilder().withNodeIdentifier(getIdentifier());
199 static final class OrderedLeafListMixinNormalization extends UnorderedLeafListMixinNormalization {
202 public OrderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
207 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
208 return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier());
212 static class UnorderedLeafListMixinNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
214 private final InstanceIdToNodes<?> innerOp;
216 public UnorderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
217 super(new YangInstanceIdentifier.NodeIdentifier(potential.getQName()));
218 innerOp = new InstanceIdToSimpleNodes.LeafListEntryNormalization(potential);
222 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
223 return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier());
227 public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
228 if (child instanceof YangInstanceIdentifier.NodeWithValue) {
235 static final class AugmentationNormalization extends DataContainerNormalizationOperation<YangInstanceIdentifier.AugmentationIdentifier> implements MixinNormalizationOp {
237 public AugmentationNormalization(final AugmentationSchema augmentation, final DataNodeContainer schema) {
238 super(augmentationIdentifierFrom(augmentation), augmentationProxy(augmentation, schema));
242 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
243 return Builders.augmentationBuilder().withNodeIdentifier(getIdentifier());
247 static class UnorderedMapMixinNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
249 private final ListItemNormalization innerNode;
251 public UnorderedMapMixinNormalization(final ListSchemaNode list) {
252 super(new YangInstanceIdentifier.NodeIdentifier(list.getQName()));
253 this.innerNode = new ListItemNormalization(new YangInstanceIdentifier.NodeIdentifierWithPredicates(list.getQName(),
254 Collections.<QName, Object>emptyMap()), list);
258 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
259 return Builders.mapBuilder().withNodeIdentifier(getIdentifier());
263 public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
264 if (child.getNodeType().equals(getIdentifier().getNodeType())) {
271 static final class OrderedMapMixinNormalization extends UnorderedMapMixinNormalization {
273 public OrderedMapMixinNormalization(final ListSchemaNode list) {
278 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
279 return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier());
284 static class ChoiceNodeNormalization extends InstanceIdToCompositeNodes<YangInstanceIdentifier.NodeIdentifier> implements MixinNormalizationOp {
286 private final ImmutableMap<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArg;
288 protected ChoiceNodeNormalization(final ChoiceSchemaNode schema) {
289 super(new YangInstanceIdentifier.NodeIdentifier(schema.getQName()));
290 final ImmutableMap.Builder<YangInstanceIdentifier.PathArgument, InstanceIdToNodes<?>> byArgBuilder = ImmutableMap.builder();
292 for (final ChoiceCaseNode caze : schema.getCases()) {
293 for (final DataSchemaNode cazeChild : caze.getChildNodes()) {
294 final InstanceIdToNodes<?> childOp = fromDataSchemaNode(cazeChild);
295 byArgBuilder.put(childOp.getIdentifier(), childOp);
298 byArg = byArgBuilder.build();
302 public InstanceIdToNodes<?> getChild(final YangInstanceIdentifier.PathArgument child) {
303 return byArg.get(child);
307 protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final YangInstanceIdentifier.PathArgument compositeNode) {
308 return Builders.choiceBuilder().withNodeIdentifier(getIdentifier());