2 * Copyright (c) 2014 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.model.util;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.annotations.Beta;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.List;
16 import java.util.Optional;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
21 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.ContainerLike;
23 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
25 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
28 import org.opendaylight.yangtools.yang.model.api.InputSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.Module;
31 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
32 import org.opendaylight.yangtools.yang.model.api.OutputSchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
34 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
37 public final class SchemaNodeUtils {
38 private SchemaNodeUtils() {
42 public static Optional<SchemaNode> getOriginalIfPossible(final SchemaNode node) {
43 if (node instanceof DerivableSchemaNode) {
44 @SuppressWarnings("unchecked")
45 final Optional<SchemaNode> ret = (Optional<SchemaNode>) ((DerivableSchemaNode) node).getOriginal();
48 return Optional.empty();
51 public static SchemaNode getRootOriginalIfPossible(final SchemaNode data) {
52 Optional<SchemaNode> previous = Optional.empty();
53 Optional<SchemaNode> next = getOriginalIfPossible(data);
54 while (next.isPresent()) {
56 next = getOriginalIfPossible(next.get());
58 return previous.orElse(null);
62 * Returns RPC input or output schema based on supplied QName.
64 * @param rpc RPC Definition
65 * @param qname input or output QName with namespace same as RPC
66 * @return input or output schema. Returns null if RPC does not have input/output specified.
68 public static @Nullable ContainerLike getRpcDataSchema(final @NonNull RpcDefinition rpc,
69 final @NonNull QName qname) {
70 requireNonNull(rpc, "Rpc Schema must not be null");
71 switch (requireNonNull(qname, "QName must not be null").getLocalName()) {
73 return rpc.getInput();
75 return rpc.getOutput();
77 throw new IllegalArgumentException("Supplied qname " + qname
78 + " does not represent rpc input or output.");
83 public static @NonNull Collection<? extends TypeDefinition<?>> getAllTypeDefinitions(
84 final DataNodeContainer parent) {
85 final List<TypeDefinition<?>> typedefs = new ArrayList<>();
86 traverse(new DataNodeAggregator() {
88 protected void addTypedefs(final Collection<? extends TypeDefinition<?>> typeDefs) {
89 typedefs.addAll(typeDefs);
91 }, requireNonNull(parent));
96 public static @NonNull Collection<? extends ContainerSchemaNode> getAllContainers(final DataNodeContainer parent) {
97 final List<ContainerSchemaNode> containers = new ArrayList<>();
98 traverse(new DataNodeAggregator() {
100 protected void addContainer(final ContainerSchemaNode containerNode) {
101 containers.add(containerNode);
103 }, requireNonNull(parent));
108 public static void traverse(final @NonNull DataNodeAggregator aggregator, final DataNodeContainer dataNode) {
109 if (dataNode == null) {
113 for (DataSchemaNode childNode : dataNode.getChildNodes()) {
114 if (childNode.isAugmenting()) {
117 aggregator.addChild(childNode);
118 if (childNode instanceof ContainerSchemaNode) {
119 final ContainerSchemaNode containerNode = (ContainerSchemaNode) childNode;
120 aggregator.addContainer(containerNode);
121 traverse(aggregator, containerNode);
122 } else if (childNode instanceof ListSchemaNode) {
123 final ListSchemaNode list = (ListSchemaNode) childNode;
124 aggregator.addList(list);
125 traverse(aggregator, list);
126 } else if (childNode instanceof ChoiceSchemaNode) {
127 final ChoiceSchemaNode choiceNode = (ChoiceSchemaNode) childNode;
128 aggregator.addChoice(choiceNode);
129 for (final CaseSchemaNode caseNode : choiceNode.getCases()) {
130 traverse(aggregator, caseNode);
135 aggregator.addTypedefs(dataNode.getTypeDefinitions());
137 traverseModule(aggregator, dataNode);
138 traverseGroupings(aggregator, dataNode);
141 private static void traverseModule(final DataNodeAggregator aggregator, final DataNodeContainer dataNode) {
143 if (dataNode instanceof Module) {
144 module = (Module) dataNode;
149 for (NotificationDefinition notificationDefinition : module.getNotifications()) {
150 traverse(aggregator, notificationDefinition);
153 for (RpcDefinition rpcDefinition : module.getRpcs()) {
154 aggregator.addTypedefs(rpcDefinition.getTypeDefinitions());
155 InputSchemaNode input = rpcDefinition.getInput();
157 traverse(aggregator, input);
159 OutputSchemaNode output = rpcDefinition.getOutput();
160 if (output != null) {
161 traverse(aggregator, output);
166 private static void traverseGroupings(final DataNodeAggregator aggregator, final DataNodeContainer dataNode) {
167 for (GroupingDefinition grouping : dataNode.getGroupings()) {
168 aggregator.addGrouping(grouping);
169 traverse(aggregator, grouping);