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.util;
11 import com.google.common.collect.FluentIterable;
12 import com.google.common.collect.ImmutableSet;
13 import java.util.Collections;
14 import java.util.HashSet;
15 import java.util.List;
17 import javax.annotation.Nullable;
18 import org.opendaylight.yangtools.concepts.Identifiable;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
22 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
24 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
25 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
26 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
27 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
29 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
34 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
35 import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
38 * Schema derived data providing necessary information for mapping
39 * between {@link org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode}
40 * and serialization format defined in RFC6020, since the mapping
43 * @param <T> Path Argument type
46 public abstract class DataSchemaContextNode<T extends PathArgument> implements Identifiable<T> {
48 private final T identifier;
49 private final DataSchemaNode dataSchemaNode;
52 public T getIdentifier() {
56 protected DataSchemaContextNode(final T identifier, final SchemaNode schema) {
58 this.identifier = identifier;
59 if (schema instanceof DataSchemaNode) {
60 this.dataSchemaNode = (DataSchemaNode) schema;
62 this.dataSchemaNode = null;
66 public boolean isMixin() {
70 public boolean isKeyedEntry() {
74 protected Set<QName> getQNameIdentifiers() {
75 return Collections.singleton(identifier.getNodeType());
78 public abstract @Nullable DataSchemaContextNode<?> getChild(final PathArgument child);
80 public abstract @Nullable DataSchemaContextNode<?> getChild(QName child);
82 public abstract boolean isLeaf();
85 public @Nullable DataSchemaNode getDataSchemaNode() {
86 return dataSchemaNode;
89 static final DataSchemaNode findChildSchemaNode(final DataNodeContainer parent, final QName child) {
90 DataSchemaNode potential = parent.getDataChildByName(child);
91 if (potential == null) {
92 Iterable<org.opendaylight.yangtools.yang.model.api.ChoiceNode> choices = FluentIterable.from(
93 parent.getChildNodes()).filter(ChoiceNode.class);
94 potential = findChoice(choices, child);
99 static DataSchemaContextNode<?> fromSchemaAndQNameChecked(final DataNodeContainer schema, final QName child) {
100 DataSchemaNode result = findChildSchemaNode(schema, child);
101 // We try to look up if this node was added by augmentation
102 if ((schema instanceof DataSchemaNode) && result.isAugmenting()) {
103 return fromAugmentation(schema, (AugmentationTarget) schema, result);
105 return fromDataSchemaNode(result);
108 private static org.opendaylight.yangtools.yang.model.api.ChoiceNode findChoice(
109 final Iterable<org.opendaylight.yangtools.yang.model.api.ChoiceNode> choices, final QName child) {
110 org.opendaylight.yangtools.yang.model.api.ChoiceNode foundChoice = null;
111 choiceLoop: for (org.opendaylight.yangtools.yang.model.api.ChoiceNode choice : choices) {
112 for (ChoiceCaseNode caze : choice.getCases()) {
113 if (findChildSchemaNode(caze, child) != null) {
114 foundChoice = choice;
122 public static AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchema augmentation) {
123 ImmutableSet.Builder<QName> potentialChildren = ImmutableSet.builder();
124 for (DataSchemaNode child : augmentation.getChildNodes()) {
125 potentialChildren.add(child.getQName());
127 return new AugmentationIdentifier(potentialChildren.build());
130 static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation,
131 final DataNodeContainer schema) {
132 Set<DataSchemaNode> children = new HashSet<>();
133 for (DataSchemaNode augNode : augmentation.getChildNodes()) {
134 children.add(schema.getDataChildByName(augNode.getQName()));
136 return new EffectiveAugmentationSchema(augmentation, children);
140 * Returns a DataContextNodeOperation for provided child node
142 * If supplied child is added by Augmentation this operation returns a
143 * DataContextNodeOperation for augmentation, otherwise returns a
144 * DataContextNodeOperation for child as call for
145 * {@link #fromDataSchemaNode(DataSchemaNode)}.
153 static @Nullable DataSchemaContextNode<?> fromAugmentation(final DataNodeContainer parent,
154 final AugmentationTarget parentAug, final DataSchemaNode child) {
155 AugmentationSchema augmentation = null;
156 for (AugmentationSchema aug : parentAug.getAvailableAugmentations()) {
157 DataSchemaNode potential = aug.getDataChildByName(child.getQName());
158 if (potential != null) {
163 if (augmentation != null) {
164 return new AugmentationContextNode(augmentation, parent);
166 return fromDataSchemaNode(child);
169 public static @Nullable DataSchemaContextNode<?> fromDataSchemaNode(final DataSchemaNode potential) {
170 if (potential instanceof ContainerSchemaNode) {
171 return new ContainerContextNode((ContainerSchemaNode) potential);
172 } else if (potential instanceof ListSchemaNode) {
173 return fromListSchemaNode((ListSchemaNode) potential);
174 } else if (potential instanceof LeafSchemaNode) {
175 return new LeafContextNode((LeafSchemaNode) potential);
176 } else if (potential instanceof org.opendaylight.yangtools.yang.model.api.ChoiceNode) {
177 return new ChoiceNodeContextNode((org.opendaylight.yangtools.yang.model.api.ChoiceNode) potential);
178 } else if (potential instanceof LeafListSchemaNode) {
179 return fromLeafListSchemaNode((LeafListSchemaNode) potential);
180 } else if (potential instanceof AnyXmlSchemaNode) {
181 return new AnyXmlContextNode((AnyXmlSchemaNode) potential);
186 private static DataSchemaContextNode<?> fromListSchemaNode(final ListSchemaNode potential) {
187 List<QName> keyDefinition = potential.getKeyDefinition();
188 if (keyDefinition == null || keyDefinition.isEmpty()) {
189 return new UnkeyedListMixinContextNode(potential);
191 if (potential.isUserOrdered()) {
192 return new OrderedMapMixinContextNode(potential);
194 return new UnorderedMapMixinContextNode(potential);
197 private static DataSchemaContextNode<?> fromLeafListSchemaNode(final LeafListSchemaNode potential) {
198 if (potential.isUserOrdered()) {
199 return new OrderedLeafListMixinContextNode(potential);
201 return new UnorderedLeafListMixinContextNode(potential);
204 public static DataSchemaContextNode<?> from(final SchemaContext ctx) {
205 return new ContainerContextNode(ctx);