2 * Copyright (c) 2014, 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
9 package org.opendaylight.yangtools.sal.binding.generator.impl;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import java.util.HashSet;
14 import java.util.Iterator;
16 import org.opendaylight.yangtools.yang.binding.Augmentation;
17 import org.opendaylight.yangtools.yang.binding.BindingMapping;
18 import org.opendaylight.yangtools.yang.binding.ChildOf;
19 import org.opendaylight.yangtools.yang.binding.DataObject;
20 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
21 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
22 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
23 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
26 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
27 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
28 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
30 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
32 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
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.SchemaNodeUtils;
37 public final class BindingSchemaContextUtils {
39 private BindingSchemaContextUtils() {
40 throw new UnsupportedOperationException("Utility class should not be instantiated");
43 // FIXME: THis method does not search in case augmentations.
44 public static Optional<DataNodeContainer> findDataNodeContainer(final SchemaContext ctx,
45 final InstanceIdentifier<?> path) {
46 Iterator<PathArgument> pathArguments = path.getPathArguments().iterator();
47 PathArgument currentArg = pathArguments.next();
48 Preconditions.checkArgument(currentArg != null);
49 QName currentQName = BindingReflections.findQName(currentArg.getType());
51 Optional<DataNodeContainer> currentContainer = Optional.absent();
52 if (BindingReflections.isNotification(currentArg.getType())) {
53 currentContainer = findNotification(ctx, currentQName);
54 } else if (BindingReflections.isRpcType(currentArg.getType())) {
55 currentContainer = findFirstDataNodeContainerInRpc(ctx, currentArg.getType());
56 if(currentQName == null && currentContainer.isPresent()) {
57 currentQName = ((DataSchemaNode) currentContainer.get()).getQName();
60 currentContainer = findDataNodeContainer(ctx, currentQName);
63 while (currentContainer.isPresent() && pathArguments.hasNext()) {
64 currentArg = pathArguments.next();
65 if (Augmentation.class.isAssignableFrom(currentArg.getType())) {
66 currentQName = BindingReflections.findQName(currentArg.getType());
67 if(pathArguments.hasNext()) {
68 currentArg = pathArguments.next();
70 return currentContainer;
73 if(ChildOf.class.isAssignableFrom(currentArg.getType()) && BindingReflections.isAugmentationChild(currentArg.getType())) {
74 currentQName = BindingReflections.findQName(currentArg.getType());
76 currentQName = QName.create(currentQName, BindingReflections.findQName(currentArg.getType()).getLocalName());
78 Optional<DataNodeContainer> potential = findDataNodeContainer(currentContainer.get(), currentQName);
79 if (potential.isPresent()) {
80 currentContainer = potential;
82 return Optional.absent();
85 return currentContainer;
88 private static Optional<DataNodeContainer> findNotification(final SchemaContext ctx, final QName notificationQName) {
89 for (NotificationDefinition notification : ctx.getNotifications()) {
90 if (notification.getQName().equals(notificationQName)) {
91 return Optional.<DataNodeContainer> of(notification);
94 return Optional.absent();
97 private static Optional<DataNodeContainer> findDataNodeContainer(final DataNodeContainer ctx,
98 final QName targetQName) {
100 for (DataSchemaNode child : ctx.getChildNodes()) {
101 if (child instanceof ChoiceSchemaNode) {
102 DataNodeContainer potential = findInCases(((ChoiceSchemaNode) child), targetQName);
103 if (potential != null) {
104 return Optional.of(potential);
106 } else if (child instanceof DataNodeContainer && child.getQName().equals(targetQName)) {
107 return Optional.of((DataNodeContainer) child);
108 } else if (child instanceof DataNodeContainer //
109 && child.isAddedByUses() //
110 && child.getQName().getLocalName().equals(targetQName.getLocalName())) {
111 return Optional.of((DataNodeContainer) child);
115 return Optional.absent();
118 private static DataNodeContainer findInCases(final ChoiceSchemaNode choiceNode, final QName targetQName) {
119 for (ChoiceCaseNode caze : choiceNode.getCases()) {
120 Optional<DataNodeContainer> potential = findDataNodeContainer(caze, targetQName);
121 if (potential.isPresent()) {
122 return potential.get();
128 private static Optional<DataNodeContainer> findFirstDataNodeContainerInRpc(final SchemaContext ctx,
129 final Class<? extends DataObject> targetType) {
130 final YangModuleInfo moduleInfo;
132 moduleInfo = BindingReflections.getModuleInfo(targetType);
133 } catch (Exception e) {
134 throw new IllegalArgumentException(
135 String.format("Failed to load module information for class %s", targetType), e);
138 for(RpcDefinition rpc : ctx.getOperations()) {
139 String rpcNamespace = rpc.getQName().getNamespace().toString();
140 String rpcRevision = rpc.getQName().getFormattedRevision();
141 if(moduleInfo.getNamespace().equals(rpcNamespace) && moduleInfo.getRevision().equals(rpcRevision)) {
142 Optional<DataNodeContainer> potential = findInputOutput(rpc,targetType.getSimpleName());
143 if(potential.isPresent()) {
148 return Optional.absent();
151 private static Optional<DataNodeContainer> findInputOutput(final RpcDefinition rpc, final String targetType) {
152 String rpcName = BindingMapping.getClassName(rpc.getQName());
153 String rpcInputName = rpcName + BindingMapping.RPC_INPUT_SUFFIX;
154 String rpcOutputName = rpcName + BindingMapping.RPC_OUTPUT_SUFFIX;
155 if(targetType.equals(rpcInputName)) {
156 return Optional.<DataNodeContainer>of(rpc.getInput());
157 } else if (targetType.equals(rpcOutputName)) {
158 return Optional.<DataNodeContainer>of(rpc.getOutput());
160 return Optional.absent();
163 public static Set<AugmentationSchema> collectAllAugmentationDefinitions(final SchemaContext currentSchema, final AugmentationTarget ctxNode) {
164 HashSet<AugmentationSchema> augmentations = new HashSet<>();
165 augmentations.addAll(ctxNode.getAvailableAugmentations());
166 if(ctxNode instanceof DataSchemaNode && ((DataSchemaNode) ctxNode).isAddedByUses()) {
168 System.out.println(ctxNode);
172 // TODO Auto-generated method stub
173 return augmentations;
176 public static Optional<ChoiceSchemaNode> findInstantiatedChoice(final DataNodeContainer parent, final Class<?> choiceClass) {
177 return findInstantiatedChoice(parent, BindingReflections.findQName(choiceClass));
180 public static Optional<ChoiceSchemaNode> findInstantiatedChoice(final DataNodeContainer ctxNode, final QName choiceName) {
181 DataSchemaNode potential = ctxNode.getDataChildByName(choiceName);
182 if (potential == null) {
183 potential = ctxNode.getDataChildByName(choiceName.getLocalName());
186 if (potential instanceof ChoiceSchemaNode) {
187 return Optional.of((ChoiceSchemaNode) potential);
190 return Optional.absent();
193 public static Optional<ChoiceCaseNode> findInstantiatedCase(final ChoiceSchemaNode instantiatedChoice, final ChoiceCaseNode originalDefinition) {
194 ChoiceCaseNode potential = instantiatedChoice.getCaseNodeByName(originalDefinition.getQName());
195 if(originalDefinition.equals(potential)) {
196 return Optional.of(potential);
198 if (potential != null) {
199 SchemaNode potentialRoot = SchemaNodeUtils.getRootOriginalIfPossible(potential);
200 if (originalDefinition.equals(potentialRoot)) {
201 return Optional.of(potential);
204 // We try to find case by name, then lookup its root definition
205 // and compare it with original definition
206 // This solves case, if choice was inside grouping
207 // which was used in different module and thus namespaces are
208 // different, but local names are still same.
210 // Still we need to check equality of definition, because local name is not
211 // sufficient to uniquelly determine equality of cases
213 potential = instantiatedChoice.getCaseNodeByName(originalDefinition.getQName().getLocalName());
214 if(potential != null && (originalDefinition.equals(SchemaNodeUtils.getRootOriginalIfPossible(potential)))) {
215 return Optional.of(potential);
217 return Optional.absent();