Refactored SchemaPath for yang java types. Fixed SchemaPath for augmented nodes types.
[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 static org.opendaylight.controller.yang.model.util.SchemaContextUtil.*;
11
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17
18 import org.opendaylight.controller.binding.generator.util.BindingGeneratorUtil;
19 import org.opendaylight.controller.binding.generator.util.Types;
20 import org.opendaylight.controller.binding.generator.util.generated.type.builder.EnumerationBuilderImpl;
21 import org.opendaylight.controller.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
22 import org.opendaylight.controller.sal.binding.generator.spi.TypeProvider;
23 import org.opendaylight.controller.sal.binding.model.api.Enumeration;
24 import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
25 import org.opendaylight.controller.sal.binding.model.api.Type;
26 import org.opendaylight.controller.sal.binding.model.api.type.builder.EnumBuilder;
27 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
28 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTOBuilder;
29 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
30 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
31 import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
32 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
33 import org.opendaylight.controller.yang.model.api.Module;
34 import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
35 import org.opendaylight.controller.yang.model.api.SchemaContext;
36 import org.opendaylight.controller.yang.model.api.TypeDefinition;
37 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition;
38 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair;
39 import org.opendaylight.controller.yang.model.api.type.IdentityrefTypeDefinition;
40 import org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition;
41 import org.opendaylight.controller.yang.model.api.type.UnionTypeDefinition;
42 import org.opendaylight.controller.yang.model.util.ExtendedType;
43
44 public class TypeProviderImpl implements TypeProvider {
45
46     private final SchemaContext schemaContext;
47     private Map<String, Map<String, GeneratedTransferObject>> genTypeDefsContextMap;
48     private final List<GeneratedTransferObject> allTypeDefinitions;
49
50     public TypeProviderImpl(final SchemaContext schemaContext) {
51         if (schemaContext == null) {
52             throw new IllegalArgumentException("Schema Context cannot be null!");
53         }
54
55         this.schemaContext = schemaContext;
56         this.genTypeDefsContextMap = new HashMap<String, Map<String, GeneratedTransferObject>>();
57         allTypeDefinitions = resolveTypeDefsFromContext();
58     }
59
60     public List<GeneratedTransferObject> getGeneratedTypeDefs() {
61         return allTypeDefinitions;
62     }
63
64     /*
65      * (non-Javadoc)
66      *
67      * @see org.opendaylight.controller.yang.model.type.provider.TypeProvider#
68      * javaTypeForYangType(java.lang.String)
69      */
70     @Override
71     public Type javaTypeForYangType(String type) {
72         Type t = BaseYangTypes.BASE_YANG_TYPES_PROVIDER
73                 .javaTypeForYangType(type);
74         return t;
75     }
76
77     @Override
78     public Type javaTypeForSchemaDefinitionType(
79             final TypeDefinition<?> typeDefinition) {
80         Type returnType = null;
81         if (typeDefinition != null) {
82             final String typedefName = typeDefinition.getQName().getLocalName();
83             if (typeDefinition instanceof ExtendedType) {
84                 final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
85
86                 if (baseTypeDef instanceof LeafrefTypeDefinition) {
87                     final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) baseTypeDef;
88                     returnType = provideTypeForLeafref(leafref);
89                 } else if (baseTypeDef instanceof IdentityrefTypeDefinition) {
90
91                 } else if (baseTypeDef instanceof EnumTypeDefinition) {
92                     final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypeDef;
93                     returnType = resolveEnumFromTypeDefinition(enumTypeDef,
94                             typedefName);
95                 } else {
96
97                     final Module module = resolveModuleFromTypePath(schemaContext, typeDefinition);
98
99                     if (module != null) {
100                         final Map<String, GeneratedTransferObject> genTOs = genTypeDefsContextMap
101                                 .get(module.getName());
102                         if (genTOs != null) {
103                             returnType = genTOs.get(typedefName);
104                         }
105                     }
106                 }
107             } else {
108                 if (typeDefinition instanceof LeafrefTypeDefinition) {
109                     final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition;
110                     returnType = provideTypeForLeafref(leafref);
111                 } else if (typeDefinition instanceof EnumTypeDefinition) {
112                     final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDefinition;
113                     returnType = resolveEnumFromTypeDefinition(enumTypeDef,
114                             typedefName);
115                 } else if (typeDefinition instanceof IdentityrefTypeDefinition) {
116
117                 } else {
118                     returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER
119                             .javaTypeForSchemaDefinitionType(typeDefinition);
120                 }
121             }
122         }
123         return returnType;
124     }
125
126     private TypeDefinition<?> baseTypeDefForExtendedType(
127             final TypeDefinition<?> extendTypeDef) {
128         if (extendTypeDef != null) {
129             final TypeDefinition<?> baseTypeDef = extendTypeDef.getBaseType();
130             if (baseTypeDef instanceof ExtendedType) {
131                 return baseTypeDefForExtendedType(baseTypeDef);
132             } else {
133                 return baseTypeDef;
134             }
135         }
136         return null;
137     }
138
139     public Type baseTypeForExtendedType(final TypeDefinition<?> typeDefinition) {
140         Type returnType = null;
141         if (typeDefinition != null) {
142             final TypeDefinition<?> baseTypeDefinition = baseTypeDefForExtendedType(typeDefinition);
143
144             if (baseTypeDefinition instanceof EnumTypeDefinition) {
145                 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDefinition;
146                 final String enumName = enumTypeDef.getQName().getLocalName();
147                 return resolveEnumFromTypeDefinition(enumTypeDef, enumName);
148             } else {
149                 returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER
150                         .javaTypeForSchemaDefinitionType(typeDefinition);
151             }
152         }
153         return returnType;
154     }
155
156     public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType) {
157         Type returnType = null;
158         if ((leafrefType != null) && (leafrefType.getPathStatement() != null)
159                 && (leafrefType.getPath() != null)) {
160
161             final RevisionAwareXPath xpath = leafrefType.getPathStatement();
162             final String strXPath = xpath.toString();
163
164             if (strXPath != null) {
165                 if (strXPath.matches(".*//[.* | .*//].*")) {
166                     returnType = Types.typeForClass(Object.class);
167                 } else {
168                     final Module module = resolveModuleFromTypePath(schemaContext, leafrefType);
169                     if (module != null) {
170                         final DataSchemaNode dataNode;
171                         if (xpath.isAbsolute()) {
172                             dataNode = findDataSchemaNode(schemaContext,
173                                     module, xpath);
174                         } else {
175                             dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module,
176                                             leafrefType, xpath);
177                         }
178                         returnType = resolveTypeFromDataSchemaNode(dataNode);
179                     }
180                 }
181             }
182         }
183         return returnType;
184     }
185
186     private EnumBuilder resolveEnumFromTypeDefinition(
187             final EnumTypeDefinition enumTypeDef, final String enumName,
188             final GeneratedTypeBuilder typeBuilder) {
189         if ((enumTypeDef != null) && (typeBuilder != null)
190                 && (enumTypeDef.getQName() != null)
191                 && (enumTypeDef.getQName().getLocalName() != null)) {
192
193             final String enumerationName = BindingGeneratorUtil
194                     .parseToClassName(enumName);
195             final EnumBuilder enumBuilder = typeBuilder
196                     .addEnumeration(enumerationName);
197
198             if (enumBuilder != null) {
199                 final List<EnumPair> enums = enumTypeDef.getValues();
200                 if (enums != null) {
201                     int listIndex = 0;
202                     for (final EnumPair enumPair : enums) {
203                         if (enumPair != null) {
204                             final String enumPairName = BindingGeneratorUtil
205                                     .parseToClassName(enumPair.getName());
206                             Integer enumPairValue = enumPair.getValue();
207
208                             if (enumPairValue == null) {
209                                 enumPairValue = listIndex;
210                             }
211                             enumBuilder.addValue(enumPairName, enumPairValue);
212                             listIndex++;
213                         }
214                     }
215                 }
216                 return enumBuilder;
217             }
218         }
219         return null;
220     }
221
222     private Enumeration resolveEnumFromTypeDefinition(
223             final EnumTypeDefinition enumTypeDef, final String enumName) {
224         if ((enumTypeDef != null) && (enumTypeDef.getQName() != null)
225                 && (enumTypeDef.getQName().getLocalName() != null)) {
226
227             final String enumerationName = BindingGeneratorUtil
228                     .parseToClassName(enumName);
229
230             Module module = resolveModuleFromTypePath(schemaContext, enumTypeDef);
231
232             final String basePackageName = BindingGeneratorUtil
233                     .moduleNamespaceToPackageName(module);
234             final String packageName = BindingGeneratorUtil
235                     .packageNameForGeneratedType(basePackageName,
236                             enumTypeDef.getPath());
237
238             final EnumBuilder enumBuilder = new EnumerationBuilderImpl(
239                     packageName, enumerationName);
240
241             if (enumBuilder != null) {
242                 final List<EnumPair> enums = enumTypeDef.getValues();
243                 if (enums != null) {
244                     int listIndex = 0;
245                     for (final EnumPair enumPair : enums) {
246                         if (enumPair != null) {
247                             final String enumPairName = BindingGeneratorUtil
248                                     .parseToClassName(enumPair.getName());
249                             Integer enumPairValue = enumPair.getValue();
250
251                             if (enumPairValue == null) {
252                                 enumPairValue = listIndex;
253                             }
254                             enumBuilder.addValue(enumPairName, enumPairValue);
255                             listIndex++;
256                         }
257                     }
258                 }
259                 return enumBuilder.toInstance(null);
260             }
261         }
262         return null;
263     }
264
265     private Type resolveTypeFromDataSchemaNode(final DataSchemaNode dataNode) {
266         Type returnType = null;
267         if (dataNode != null) {
268             if (dataNode instanceof LeafSchemaNode) {
269                 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
270                 returnType = javaTypeForSchemaDefinitionType(leaf.getType());
271             } else if (dataNode instanceof LeafListSchemaNode) {
272                 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
273                 returnType = javaTypeForSchemaDefinitionType(leafList.getType());
274             }
275         }
276         return returnType;
277     }
278
279     private List<GeneratedTransferObject> resolveTypeDefsFromContext() {
280         final List<GeneratedTransferObject> genTypeDefs = new ArrayList<GeneratedTransferObject>();
281         final Set<Module> modules = schemaContext.getModules();
282         if (modules != null) {
283             for (final Module module : modules) {
284                 if (module != null) {
285                     final String moduleName = module.getName();
286                     final String basePackageName = BindingGeneratorUtil
287                             .moduleNamespaceToPackageName(module);
288
289                     final Set<TypeDefinition<?>> typeDefinitions = module
290                             .getTypeDefinitions();
291
292                     if ((typeDefinitions != null) && (basePackageName != null)) {
293                         for (final TypeDefinition<?> typedef : typeDefinitions) {
294                             final GeneratedTransferObject genTransObj = toGeneratedTransferObject(
295                                     basePackageName, moduleName, typedef);
296                             if (genTransObj != null) {
297                                 genTypeDefs.add(genTransObj);
298                             }
299                         }
300                         // for (final TypeDefinition<?> typedef :
301                         // typeDefinitions) {
302                         // addUnionGeneratedTypeDefinition(basePackageName,
303                         // module.getName(), typedef);
304                         // }
305                     }
306                 }
307             }
308         }
309         return genTypeDefs;
310     }
311
312     private GeneratedTransferObject toGeneratedTransferObject(
313             final String basePackageName, final String moduleName,
314             final TypeDefinition<?> typedef) {
315         if ((basePackageName != null) && (moduleName != null)
316                 && (typedef != null) && (typedef.getQName() != null)) {
317             final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(
318                     basePackageName, typedef);
319
320             final String typedefName = typedef.getQName().getLocalName();
321             final String propertyName = BindingGeneratorUtil
322                     .parseToValidParamName(typedefName);
323
324             final TypeDefinition<?> baseTypeDefinition = baseTypeDefForExtendedType(typedef);
325             if (!(baseTypeDefinition instanceof LeafrefTypeDefinition)
326                     && !(baseTypeDefinition instanceof IdentityrefTypeDefinition)) {
327                 Type returnType = null;
328                 if (baseTypeDefinition instanceof EnumTypeDefinition) {
329                     final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypeDefinition;
330                     returnType = resolveEnumFromTypeDefinition(enumTypeDef,
331                             typedefName);
332                 } else {
333                     returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER
334                             .javaTypeForSchemaDefinitionType(baseTypeDefinition);
335                 }
336
337                 if (returnType != null) {
338                     final GeneratedPropertyBuilder genPropBuilder = genTOBuilder
339                             .addProperty(propertyName);
340
341                     genPropBuilder.addReturnType(returnType);
342                     genTOBuilder.addEqualsIdentity(genPropBuilder);
343                     genTOBuilder.addHashIdentity(genPropBuilder);
344                     genTOBuilder.addToStringProperty(genPropBuilder);
345
346                     Map<String, GeneratedTransferObject> transferObjectsMap = genTypeDefsContextMap
347                             .get(moduleName);
348                     if (transferObjectsMap == null) {
349                         transferObjectsMap = new HashMap<String, GeneratedTransferObject>();
350                         genTypeDefsContextMap.put(moduleName,
351                                 transferObjectsMap);
352                     }
353
354                     final GeneratedTransferObject transferObject = genTOBuilder
355                             .toInstance();
356                     if (transferObject != null) {
357                         transferObjectsMap.put(typedefName, transferObject);
358                         return transferObject;
359                     }
360                 }
361             }
362         }
363         return null;
364     }
365
366     private void addUnionGeneratedTypeDefinition(final String basePackageName,
367             final String moduleName, final TypeDefinition<?> typedef) {
368         if ((basePackageName != null) && (moduleName != null)
369                 && (typedef != null) && (typedef.getQName() != null)) {
370             final TypeDefinition<?> baseTypeDefinition = baseTypeDefForExtendedType(typedef);
371
372             if ((baseTypeDefinition != null)
373                     && (baseTypeDefinition instanceof UnionTypeDefinition)) {
374                 final UnionTypeDefinition unionTypeDef = (UnionTypeDefinition) baseTypeDefinition;
375
376                 final List<TypeDefinition<?>> unionTypes = unionTypeDef
377                         .getTypes();
378                 final Map<String, GeneratedTransferObject> genTOsMap = genTypeDefsContextMap
379                         .get(moduleName);
380                 final GeneratedTOBuilder unionGenTransObject = typedefToTransferObject(
381                         basePackageName, typedef);
382                 if ((unionTypes != null) && (genTOsMap != null)
383                         && (unionGenTransObject != null)) {
384                     for (final TypeDefinition<?> unionType : unionTypes) {
385                         final String typeName = unionType.getQName()
386                                 .getLocalName();
387                         final GeneratedTransferObject genTransferObject = genTOsMap
388                                 .get(typeName);
389
390                         if (genTransferObject != null) {
391                             unionGenTransObject
392                                     .addProperty(
393                                             BindingGeneratorUtil
394                                                     .parseToValidParamName(genTransferObject
395                                                             .getName()))
396                                     .addReturnType(genTransferObject);
397                         }
398                     }
399                     genTOsMap.put(unionTypeDef.getQName().getLocalName(),
400                             unionGenTransObject.toInstance());
401                 }
402             }
403         }
404     }
405
406     private GeneratedTOBuilder typedefToTransferObject(
407             final String basePackageName, final TypeDefinition<?> typedef) {
408
409         final String packageName = BindingGeneratorUtil
410                 .packageNameForGeneratedType(basePackageName, typedef.getPath());
411         final String typeDefTOName = typedef.getQName().getLocalName();
412
413         if ((packageName != null) && (typedef != null)
414                 && (typeDefTOName != null)) {
415             final String genTOName = BindingGeneratorUtil
416                     .parseToClassName(typeDefTOName);
417             final GeneratedTOBuilder newType = new GeneratedTOBuilderImpl(
418                     packageName, genTOName);
419
420             return newType;
421         }
422         return null;
423     }
424 }