bb5e80a5257e0153d9ccc24384f319381744eb50
[controller.git] / opendaylight / sal / yang-prototype / code-generator / binding-generator-impl / src / main / java / org / opendaylight / controller / sal / binding / yang / types / TypeProviderImpl.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.sal.binding.yang.types;
9
10 import java.util.LinkedList;
11 import java.util.List;
12 import java.util.Queue;
13 import java.util.Set;
14
15 import org.opendaylight.controller.binding.generator.util.Types;
16 import org.opendaylight.controller.sal.binding.generator.spi.TypeProvider;
17 import org.opendaylight.controller.sal.binding.model.api.Type;
18 import org.opendaylight.controller.yang.common.QName;
19 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
20 import org.opendaylight.controller.yang.model.api.DataNodeContainer;
21 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
22 import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
23 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
24 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
25 import org.opendaylight.controller.yang.model.api.Module;
26 import org.opendaylight.controller.yang.model.api.ModuleImport;
27 import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
28 import org.opendaylight.controller.yang.model.api.SchemaContext;
29 import org.opendaylight.controller.yang.model.api.SchemaPath;
30 import org.opendaylight.controller.yang.model.api.TypeDefinition;
31 import org.opendaylight.controller.yang.model.api.type.IdentityrefTypeDefinition;
32 import org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition;
33 import org.opendaylight.controller.yang.model.util.ExtendedType;
34 import org.opendaylight.controller.yang.model.util.Leafref;
35
36 public class TypeProviderImpl implements TypeProvider {
37
38     private SchemaContext schemaContext;
39
40     public TypeProviderImpl(SchemaContext schemaContext) {
41         this.schemaContext = schemaContext;
42     }
43
44     /*
45      * (non-Javadoc)
46      * 
47      * @see org.opendaylight.controller.yang.model.type.provider.TypeProvider#
48      * javaTypeForYangType(java.lang.String)
49      */
50     @Override
51     public Type javaTypeForYangType(String type) {
52         Type t = BaseYangTypes.BASE_YANG_TYPES_PROVIDER
53                 .javaTypeForYangType(type);
54         return t;
55     }
56
57     @Override
58     public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> typeDefinition) {
59         Type returnType = null;
60         if (typeDefinition != null) {
61             if (typeDefinition instanceof Leafref) {
62                 final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition;
63                 returnType = provideTypeForLeafref(leafref);
64             } else if (typeDefinition instanceof IdentityrefTypeDefinition) {
65
66             } else if (typeDefinition instanceof ExtendedType) {
67                 final TypeDefinition<?> baseType = typeDefinition.getBaseType(); 
68                 return javaTypeForSchemaDefinitionType(baseType);
69             }
70             else {
71                 returnType = baseTypeForExtendedType(typeDefinition);
72             }
73         }
74         return returnType;
75     }
76     
77     public Type baseTypeForExtendedType(final TypeDefinition<?> typeDefinition) {
78         Type returnType = null;
79         if (typeDefinition != null) {
80             if (typeDefinition instanceof ExtendedType) {
81                 final TypeDefinition<?> extType = typeDefinition.getBaseType(); 
82                 return baseTypeForExtendedType(extType);
83             } else {
84                 returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER
85                         .javaTypeForSchemaDefinitionType(typeDefinition);
86             }
87         }
88         return returnType;
89     }
90     
91     public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType) {
92         Type returnType = null;
93         if ((leafrefType != null) && (leafrefType.getPathStatement() != null)
94                 && (leafrefType.getPath() != null)) {
95
96             final RevisionAwareXPath xpath = leafrefType.getPathStatement();
97             final String strXPath = xpath.toString();
98
99             if (strXPath != null) {
100                 if (strXPath.matches(".*//[.* | .*//].*")) {
101                     returnType = Types.typeForClass(Object.class);
102                 } else {
103                     final Module module = resolveModuleFromSchemaPath(leafrefType
104                             .getPath());
105                     if (module != null) {
106                         Queue<String> leafrefPath;
107                         if (!xpath.isAbsolute()) {
108                             leafrefPath = resolveRelativeXPath(xpath,
109                                     leafrefType.getPath());
110                         } else {
111                             leafrefPath = xpathToPrefixedPath(strXPath,
112                                     module.getName());
113                         }
114                         if (leafrefPath != null) {
115                             final DataSchemaNode dataNode = findSchemaNodeForGivenPath(
116                                     module, leafrefPath);
117                             returnType = resolveTypeFromDataSchemaNode(dataNode);
118                         }
119                     }
120                 }
121             }
122         }
123         return returnType;
124     }
125
126     private Type resolveTypeFromDataSchemaNode(final DataSchemaNode dataNode) {
127         Type returnType = null;
128         if (dataNode != null) {
129             if (dataNode instanceof LeafSchemaNode) {
130                 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
131                 returnType = javaTypeForSchemaDefinitionType(leaf.getType());
132             } else if (dataNode instanceof LeafListSchemaNode) {
133                 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
134                 returnType = javaTypeForSchemaDefinitionType(leafList.getType());
135             }
136         }
137         return returnType;
138     }
139
140     /**
141      * Search which starts from root of Module.
142      * 
143      * @param module
144      * @param prefixedPath
145      * @return
146      */
147     private DataSchemaNode findSchemaNodeForGivenPath(final Module module,
148             final Queue<String> prefixedPath) {
149         if ((module != null) && (prefixedPath != null)) {
150             DataNodeContainer nextContainer = module;
151             final String modulePrefix = module.getPrefix();
152             
153             String childNodeName = null;
154             DataSchemaNode schemaNode = null;
155             while ((nextContainer != null) && (prefixedPath.size() > 0)) {
156                 childNodeName = prefixedPath.poll();
157                 if (childNodeName.contains(":")) {
158                     final String[] prefixedChildNode = childNodeName.split(":");
159                     if ((modulePrefix != null)
160                             && modulePrefix.equals(prefixedChildNode[0])) {
161
162                         childNodeName = prefixedChildNode[1];
163                     } else {
164                         final Module nextModule = resolveModuleForPrefix(
165                                 prefixedChildNode[0], module);
166                         final Queue<String> nextModulePrefixedPath = new LinkedList<String>();
167                         nextModulePrefixedPath.add(childNodeName);
168                         nextModulePrefixedPath.addAll(prefixedPath);
169                         prefixedPath.clear();
170
171                         schemaNode = findSchemaNodeForGivenPath(nextModule,
172                                 nextModulePrefixedPath);
173
174                         return schemaNode;
175                     }
176                 }
177
178                 schemaNode = nextContainer.getDataChildByName(childNodeName);
179                 if (schemaNode instanceof ContainerSchemaNode) {
180                     nextContainer = (ContainerSchemaNode) schemaNode;
181                 } else if (schemaNode instanceof ListSchemaNode) {
182                     nextContainer = (ListSchemaNode) schemaNode;
183                 } else {
184                     return schemaNode;
185                 }
186             }
187         }
188
189         return null;
190     }
191
192     private Module resolveModuleFromSchemaPath(final SchemaPath schemaPath) {
193         if ((schemaPath != null) && (schemaPath.getPath() != null)) {
194             final QName qname = schemaPath.getPath().get(0);
195
196             if ((qname != null) && (qname.getNamespace() != null)) {
197                 return schemaContext
198                         .findModuleByNamespace(qname.getNamespace());
199             }
200         }
201         return null;
202     }
203
204     private Queue<String> xpathToPrefixedPath(final String xpath,
205             final String moduleName) {
206         final Queue<String> retQueue = new LinkedList<String>();
207         if ((xpath != null) && (moduleName != null)) {
208             final String[] prefixedPath = xpath.split("/");
209
210             if (prefixedPath != null) {
211                 for (int i = 0; i < prefixedPath.length; ++i) {
212                     if (!prefixedPath[i].isEmpty()) {
213                         retQueue.add(prefixedPath[i]);
214                     }
215                 }
216             }
217         }
218         return retQueue;
219     }
220
221     private Module resolveModuleForPrefix(final String prefix,
222             final Module parent) {
223         if ((prefix != null) && (parent != null)) {
224             final Set<ModuleImport> imports = parent.getImports();
225
226             if (imports != null) {
227                 for (final ModuleImport impModule : imports) {
228                     final String impModPrefix = impModule.getPrefix();
229                     if ((impModPrefix != null) && prefix.equals(impModPrefix)) {
230                         return resolveModuleFromContext(prefix,
231                                 impModule.getModuleName());
232                     }
233                 }
234             }
235         }
236         return null;
237     }
238
239     private Module resolveModuleFromContext(final String prefix,
240             final String moduleName) {
241         final Set<Module> modules = schemaContext.getModules();
242
243         if ((prefix != null) && (moduleName != null) && (modules != null)) {
244             for (Module module : modules) {
245                 if ((module != null) && prefix.equals(module.getPrefix())
246                         && moduleName.equals(module.getName())) {
247                     return module;
248                 }
249             }
250         }
251         return null;
252     }
253
254     private Queue<String> resolveRelativeXPath(
255             final RevisionAwareXPath relativeXPath,
256             final SchemaPath leafrefSchemaPath) {
257         final Queue<String> absolutePath = new LinkedList<String>();
258
259         if ((relativeXPath != null) && !relativeXPath.isAbsolute()
260                 && (leafrefSchemaPath != null)) {
261             final String strXPath = relativeXPath.toString();
262             if (strXPath != null) {
263                 final String[] xpaths = strXPath.split("/");
264
265                 if (xpaths != null) {
266                     int colCount = 0;
267                     while (xpaths[colCount].contains("..")) {
268                         ++colCount;
269                     }
270                     final List<QName> path = leafrefSchemaPath.getPath();
271                     if (path != null) {
272                         int lenght = path.size() - colCount;
273                         for (int i = 0; i < lenght; ++i) {
274                             absolutePath.add(path.get(i).getLocalName());
275                         }
276                         for (int i = colCount; i < xpaths.length; ++i) {
277                             absolutePath.add(xpaths[i]);
278                         }
279                     }
280                 }
281             }
282         }
283         return absolutePath;
284     }
285 }