69c67953c0ca89f6170797ab516a718f8b9d0f8f
[yangtools.git] / code-generator / binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / impl / BindingSchemaContextUtils.java
1 package org.opendaylight.yangtools.sal.binding.generator.impl;
2
3 import java.util.HashSet;
4 import java.util.Iterator;
5 import java.util.Set;
6
7 import org.opendaylight.yangtools.yang.binding.Augmentation;
8 import org.opendaylight.yangtools.yang.binding.BindingMapping;
9 import org.opendaylight.yangtools.yang.binding.ChildOf;
10 import org.opendaylight.yangtools.yang.binding.DataObject;
11 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
12 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
13 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
14 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
17 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
18 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
19 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
20 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
21 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
23 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
24 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
25
26 import com.google.common.base.Optional;
27 import com.google.common.base.Preconditions;
28
29 public class BindingSchemaContextUtils {
30
31     // FIXME: THis method does not search in case augmentations.
32     public static Optional<DataNodeContainer> findDataNodeContainer(final SchemaContext ctx,
33             final InstanceIdentifier<?> path) {
34         Iterator<PathArgument> pathArguments = path.getPathArguments().iterator();
35         PathArgument currentArg = pathArguments.next();
36         Preconditions.checkArgument(currentArg != null);
37         QName currentQName = BindingReflections.findQName(currentArg.getType());
38
39         Optional<DataNodeContainer> currentContainer = Optional.absent();
40         if (BindingReflections.isNotification(currentArg.getType())) {
41             currentContainer = findNotification(ctx, currentQName);
42         } else if (BindingReflections.isRpcType(currentArg.getType())) {
43             currentContainer = findFirstDataNodeContainerInRpc(ctx, currentArg.getType());
44             if(currentQName == null && currentContainer.isPresent()) {
45                 currentQName = ((DataSchemaNode) currentContainer.get()).getQName();
46             }
47         } else {
48             currentContainer = findDataNodeContainer(ctx, currentQName);
49         }
50
51         while (currentContainer.isPresent() && pathArguments.hasNext()) {
52             currentArg = pathArguments.next();
53             if (Augmentation.class.isAssignableFrom(currentArg.getType())) {
54                 currentQName = BindingReflections.findQName(currentArg.getType());
55                 if(pathArguments.hasNext()) {
56                     currentArg = pathArguments.next();
57                 } else {
58                     return currentContainer;
59                 }
60             }
61             if(ChildOf.class.isAssignableFrom(currentArg.getType()) && BindingReflections.isAugmentationChild(currentArg.getType())) {
62                 currentQName = BindingReflections.findQName(currentArg.getType());
63             } else {
64                 currentQName = QName.create(currentQName, BindingReflections.findQName(currentArg.getType()).getLocalName());
65             }
66             Optional<DataNodeContainer> potential = findDataNodeContainer(currentContainer.get(), currentQName);
67             if (potential.isPresent()) {
68                 currentContainer = potential;
69             } else {
70                 return Optional.absent();
71             }
72         }
73         return currentContainer;
74     }
75
76     private static Optional<DataNodeContainer> findNotification(final SchemaContext ctx, final QName notificationQName) {
77         for (NotificationDefinition notification : ctx.getNotifications()) {
78             if (notification.getQName().equals(notificationQName)) {
79                 return Optional.<DataNodeContainer> of(notification);
80             }
81         }
82         return Optional.absent();
83     }
84
85     private static Optional<DataNodeContainer> findDataNodeContainer(final DataNodeContainer ctx,
86             final QName targetQName) {
87
88         for (DataSchemaNode child : ctx.getChildNodes()) {
89             if (child instanceof ChoiceNode) {
90                 DataNodeContainer potential = findInCases(((ChoiceNode) child), targetQName);
91                 if (potential != null) {
92                     return Optional.of(potential);
93                 }
94             } else if (child instanceof DataNodeContainer && child.getQName().equals(targetQName)) {
95                 return Optional.of((DataNodeContainer) child);
96             } else if (child instanceof DataNodeContainer //
97                     && child.isAddedByUses() //
98                     && child.getQName().getLocalName().equals(targetQName.getLocalName())) {
99                 return Optional.of((DataNodeContainer) child);
100             }
101
102         }
103         return Optional.absent();
104     }
105
106     private static DataNodeContainer findInCases(final ChoiceNode choiceNode, final QName targetQName) {
107         for (ChoiceCaseNode caze : choiceNode.getCases()) {
108             Optional<DataNodeContainer> potential = findDataNodeContainer(caze, targetQName);
109             if (potential.isPresent()) {
110                 return potential.get();
111             }
112         }
113         return null;
114     }
115
116     private static Optional<DataNodeContainer> findFirstDataNodeContainerInRpc(final SchemaContext ctx,
117             final Class<? extends DataObject> targetType) {
118         final YangModuleInfo moduleInfo;
119         try {
120             moduleInfo = BindingReflections.getModuleInfo(targetType);
121         } catch (Exception e) {
122             throw new IllegalArgumentException(
123                     String.format("Failed to load module information for class %s", targetType), e);
124         }
125
126         for(RpcDefinition rpc : ctx.getOperations()) {
127             String rpcNamespace = rpc.getQName().getNamespace().toString();
128             String rpcRevision = rpc.getQName().getFormattedRevision();
129             if(moduleInfo.getNamespace().equals(rpcNamespace) && moduleInfo.getRevision().equals(rpcRevision)) {
130                 Optional<DataNodeContainer> potential = findInputOutput(rpc,targetType.getSimpleName());
131                 if(potential.isPresent()) {
132                     return potential;
133                 }
134             }
135         }
136         return Optional.absent();
137     }
138
139     private static Optional<DataNodeContainer> findInputOutput(final RpcDefinition rpc, final String targetType) {
140         String rpcName = BindingMapping.getClassName(rpc.getQName());
141         String rpcInputName = rpcName + BindingMapping.RPC_INPUT_SUFFIX;
142         String rpcOutputName = rpcName + BindingMapping.RPC_OUTPUT_SUFFIX;
143         if(targetType.equals(rpcInputName)) {
144             return Optional.<DataNodeContainer>of(rpc.getInput());
145         } else if (targetType.equals(rpcOutputName)) {
146             return Optional.<DataNodeContainer>of(rpc.getOutput());
147         }
148        return Optional.absent();
149     }
150
151     public static Set<AugmentationSchema> collectAllAugmentationDefinitions(final SchemaContext currentSchema, final AugmentationTarget ctxNode) {
152         HashSet<AugmentationSchema> augmentations = new HashSet<>();
153         augmentations.addAll(ctxNode.getAvailableAugmentations());
154         if(ctxNode instanceof DataSchemaNode && ((DataSchemaNode) ctxNode).isAddedByUses()) {
155
156             System.out.println(ctxNode);
157
158         }
159
160         // TODO Auto-generated method stub
161         return augmentations;
162     }
163
164     public static Optional<ChoiceNode> findInstantiatedChoice(final DataNodeContainer parent, final Class<?> choiceClass) {
165         return findInstantiatedChoice(parent, BindingReflections.findQName(choiceClass));
166     }
167
168     public static Optional<ChoiceNode> findInstantiatedChoice(final DataNodeContainer ctxNode, final QName choiceName) {
169         DataSchemaNode potential = ctxNode.getDataChildByName(choiceName);
170         if (potential == null) {
171             potential = ctxNode.getDataChildByName(choiceName.getLocalName());
172         }
173
174         if (potential instanceof ChoiceNode) {
175             return Optional.of((ChoiceNode) potential);
176         }
177
178         return Optional.absent();
179     }
180
181     public static Optional<ChoiceCaseNode> findInstantiatedCase(final ChoiceNode instantiatedChoice, final ChoiceCaseNode schema) {
182         ChoiceCaseNode potential = instantiatedChoice.getCaseNodeByName(schema.getQName());
183         if (potential != null) {
184             return Optional.of(potential);
185         }
186         // FIXME: Probably requires more extensive check
187         // e.g. we have one choice and two augmentations from different
188         // modules using same local name
189         // but different namespace / contents
190         return Optional.fromNullable(instantiatedChoice.getCaseNodeByName(schema.getQName().getLocalName()));
191     }
192
193 }