Fixed resolving of leafref types with relative xpath.
[yangtools.git] / code-generator / binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / impl / BindingGeneratorImpl.java
1 /*\r
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 package org.opendaylight.yangtools.sal.binding.generator.impl;\r
9 \r
10 import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.*;\r
11 import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.*;\r
12 import static org.opendaylight.yangtools.binding.generator.util.Types.BOOLEAN;\r
13 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.*;\r
14 \r
15 import java.util.ArrayList;\r
16 import java.util.Collections;\r
17 import java.util.Comparator;\r
18 import java.util.HashMap;\r
19 import java.util.List;\r
20 import java.util.Map;\r
21 import java.util.Set;\r
22 import java.util.concurrent.Future;\r
23 \r
24 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;\r
25 import org.opendaylight.yangtools.binding.generator.util.Types;\r
26 import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;\r
27 import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;\r
28 import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;\r
29 import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;\r
30 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;\r
31 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;\r
32 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;\r
33 import org.opendaylight.yangtools.sal.binding.model.api.Type;\r
34 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;\r
35 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;\r
36 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;\r
37 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;\r
38 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;\r
39 import org.opendaylight.yangtools.sal.binding.yang.types.GroupingDefinitionDependencySort;\r
40 import org.opendaylight.yangtools.sal.binding.yang.types.TypeProviderImpl;\r
41 import org.opendaylight.yangtools.yang.binding.DataRoot;\r
42 import org.opendaylight.yangtools.yang.binding.Identifiable;\r
43 import org.opendaylight.yangtools.yang.binding.Identifier;\r
44 import org.opendaylight.yangtools.yang.binding.RpcService;\r
45 import org.opendaylight.yangtools.yang.common.QName;\r
46 import org.opendaylight.yangtools.yang.common.RpcResult;\r
47 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;\r
48 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;\r
49 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;\r
50 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;\r
51 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;\r
52 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;\r
53 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;\r
54 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;\r
55 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;\r
56 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;\r
57 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;\r
58 import org.opendaylight.yangtools.yang.model.api.Module;\r
59 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;\r
60 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;\r
61 import org.opendaylight.yangtools.yang.model.api.SchemaContext;\r
62 import org.opendaylight.yangtools.yang.model.api.SchemaNode;\r
63 import org.opendaylight.yangtools.yang.model.api.SchemaPath;\r
64 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;\r
65 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;\r
66 import org.opendaylight.yangtools.yang.model.api.UsesNode;\r
67 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;\r
68 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;\r
69 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;\r
70 import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;\r
71 import org.opendaylight.yangtools.yang.model.util.ExtendedType;\r
72 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;\r
73 import org.opendaylight.yangtools.yang.model.util.UnionType;\r
74 \r
75 import com.google.common.base.Preconditions;\r
76 \r
77 public final class BindingGeneratorImpl implements BindingGenerator {\r
78 \r
79     /**\r
80      * Outter key represents the package name. Outter value represents map of\r
81      * all builders in the same package. Inner key represents the schema node\r
82      * name (in JAVA class/interface name format). Inner value represents\r
83      * instance of builder for schema node specified in key part.\r
84      */\r
85     private Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders;\r
86 \r
87     /**\r
88      * Provide methods for converting YANG types to JAVA types.\r
89      */\r
90     private TypeProvider typeProvider;\r
91 \r
92     /**\r
93      * Holds reference to schema context to resolve data of augmented elemnt\r
94      * when creating augmentation builder\r
95      */\r
96     private SchemaContext schemaContext;\r
97 \r
98     /**\r
99      * Each grouping which is converted from schema node to generated type is\r
100      * added to this map with its Schema path as key to make it easier to get\r
101      * reference to it. In schema nodes in <code>uses</code> attribute there is\r
102      * only Schema Path but when building list of implemented interfaces for\r
103      * Schema node the object of type <code>Type</code> is required. So in this\r
104      * case is used this map.\r
105      */\r
106     private final Map<SchemaPath, GeneratedType> allGroupings = new HashMap<SchemaPath, GeneratedType>();\r
107 \r
108     /**\r
109      * Constant with the concrete name of namespace.\r
110      */\r
111     private final static String YANG_EXT_NAMESPACE = "urn:opendaylight:yang:extension:yang-ext";\r
112 \r
113     /**\r
114      * Constant with the concrete name of identifier.\r
115      */\r
116     private final static String AUGMENT_IDENTIFIER_NAME = "augment-identifier";\r
117 \r
118     /**\r
119      * Only parent constructor is invoked.\r
120      */\r
121     public BindingGeneratorImpl() {\r
122         super();\r
123     }\r
124 \r
125     /**\r
126      * Resolves generated types from <code>context</code> schema nodes of all\r
127      * modules.\r
128      *\r
129      * Generated types are created for modules, groupings, types, containers,\r
130      * lists, choices, augments, rpcs, notification, identities.\r
131      *\r
132      * @param context\r
133      *            schema context which contains data about all schema nodes\r
134      *            saved in modules\r
135      * @return list of types (usually <code>GeneratedType</code>\r
136      *         <code>GeneratedTransferObject</code>which are generated from\r
137      *         <code>context</code> data.\r
138      * @throws IllegalArgumentException\r
139      *             if param <code>context</code> is null\r
140      * @throws IllegalStateException\r
141      *             if <code>context</code> contain no modules\r
142      */\r
143     @Override\r
144     public List<Type> generateTypes(final SchemaContext context) {\r
145         Preconditions.checkArgument(context != null,"Schema Context reference cannot be NULL.");\r
146         Preconditions.checkState(context.getModules() != null,"Schema Context does not contain defined modules.");\r
147         final List<Type> generatedTypes = new ArrayList<>();\r
148         schemaContext = context;\r
149         typeProvider = new TypeProviderImpl(context);\r
150         final Set<Module> modules = context.getModules();\r
151         genTypeBuilders = new HashMap<>();\r
152         for (final Module module : modules) {\r
153 \r
154             generatedTypes.addAll(allGroupingsToGenTypes(module));\r
155 \r
156             if (false == module.getChildNodes().isEmpty()) {\r
157                 generatedTypes.add(moduleToDataType(module));\r
158             }\r
159             generatedTypes.addAll(allTypeDefinitionsToGenTypes(module));\r
160             generatedTypes.addAll(allContainersToGenTypes(module));\r
161             generatedTypes.addAll(allListsToGenTypes(module));\r
162             generatedTypes.addAll(allChoicesToGenTypes(module));\r
163             generatedTypes.addAll(allAugmentsToGenTypes(module));\r
164             generatedTypes.addAll(allRPCMethodsToGenType(module));\r
165             generatedTypes.addAll(allNotificationsToGenType(module));\r
166             generatedTypes.addAll(allIdentitiesToGenTypes(module, context));\r
167 \r
168         }\r
169         return generatedTypes;\r
170     }\r
171 \r
172     /**\r
173      * Resolves generated types from <code>context</code> schema nodes only for\r
174      * modules specified in <code>modules</code>\r
175      *\r
176      * Generated types are created for modules, groupings, types, containers,\r
177      * lists, choices, augments, rpcs, notification, identities.\r
178      *\r
179      * @param context\r
180      *            schema context which contains data about all schema nodes\r
181      *            saved in modules\r
182      * @param modules\r
183      *            set of modules for which schema nodes should be generated\r
184      *            types\r
185      * @return list of types (usually <code>GeneratedType</code> or\r
186      *         <code>GeneratedTransferObject</code>) which:\r
187      *         <ul>\r
188      *         <li>are generated from <code>context</code> schema nodes and</li>\r
189      *         <li>are also part of some of the module in <code>modules</code>\r
190      *         set</li>.\r
191      *         </ul>\r
192      * @throws IllegalArgumentException\r
193      *             <ul>\r
194      *             <li>if param <code>context</code> is null or</li>\r
195      *             <li>if param <code>modules</code> is null</li>\r
196      *             </ul>\r
197      * @throws IllegalStateException\r
198      *             if <code>context</code> contain no modules\r
199      */\r
200     @Override\r
201     public List<Type> generateTypes(final SchemaContext context, final Set<Module> modules) {\r
202         Preconditions.checkArgument(context != null,"Schema Context reference cannot be NULL.");\r
203         Preconditions.checkState(context.getModules() != null,"Schema Context does not contain defined modules.");\r
204         Preconditions.checkArgument(modules != null,"Sef of Modules cannot be NULL.");\r
205 \r
206         final List<Type> filteredGenTypes = new ArrayList<>();\r
207         schemaContext = context;\r
208         typeProvider = new TypeProviderImpl(context);\r
209         final Set<Module> contextModules = context.getModules();\r
210         genTypeBuilders = new HashMap<>();\r
211         for (final Module contextModule : contextModules) {\r
212             final List<Type> generatedTypes = new ArrayList<>();\r
213 \r
214             generatedTypes.addAll(allGroupingsToGenTypes(contextModule));\r
215             if (false == contextModule.getChildNodes().isEmpty()) {\r
216                 generatedTypes.add(moduleToDataType(contextModule));\r
217             }\r
218             generatedTypes.addAll(allTypeDefinitionsToGenTypes(contextModule));\r
219             generatedTypes.addAll(allContainersToGenTypes(contextModule));\r
220             generatedTypes.addAll(allListsToGenTypes(contextModule));\r
221             generatedTypes.addAll(allChoicesToGenTypes(contextModule));\r
222             generatedTypes.addAll(allAugmentsToGenTypes(contextModule));\r
223             generatedTypes.addAll(allRPCMethodsToGenType(contextModule));\r
224             generatedTypes.addAll(allNotificationsToGenType(contextModule));\r
225             generatedTypes.addAll(allIdentitiesToGenTypes(contextModule, context));\r
226 \r
227             if (modules.contains(contextModule)) {\r
228                 filteredGenTypes.addAll(generatedTypes);\r
229             }\r
230         }\r
231         return filteredGenTypes;\r
232     }\r
233 \r
234     /**\r
235      * Converts all extended type definitions of module to the list of\r
236      * <code>Type</code> objects.\r
237      *\r
238      * @param module\r
239      *            module from which is obtained set of type definitions\r
240      * @return list of <code>Type</code> which are generated from extended\r
241      *         definition types (object of type <code>ExtendedType</code>)\r
242      * @throws IllegalArgumentException\r
243      *             <ul>\r
244      *             <li>if module equals null</li>\r
245      *             <li>if name of module equals null</li>\r
246      *             <li>if type definitions of module equal null</li>\r
247      *             </ul>\r
248      *\r
249      */\r
250     private List<Type> allTypeDefinitionsToGenTypes(final Module module) {\r
251         Preconditions.checkArgument(module != null,"Module reference cannot be NULL.");\r
252         Preconditions.checkArgument(module.getName() != null,"Module name cannot be NULL.");\r
253         Preconditions.checkArgument(module.getTypeDefinitions() != null,"Type Definitions for module " + module.getName() + " cannot be NULL.");\r
254 \r
255         final Set<TypeDefinition<?>> typeDefinitions = module.getTypeDefinitions();\r
256         final List<Type> generatedTypes = new ArrayList<>();\r
257         for (final TypeDefinition<?> typedef : typeDefinitions) {\r
258             if (typedef != null) {\r
259                 final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef, typedef);\r
260                 if ((type != null) && !generatedTypes.contains(type)) {\r
261                     generatedTypes.add(type);\r
262                 }\r
263             }\r
264         }\r
265         return generatedTypes;\r
266     }\r
267 \r
268     /**\r
269      * Converts all <b>containers</b> of the module to the list of\r
270      * <code>Type</code> objects.\r
271      *\r
272      * @param module\r
273      *            module from which is obtained DataNodeIterator to iterate over\r
274      *            all containers\r
275      * @return list of <code>Type</code> which are generated from containers\r
276      *         (objects of type <code>ContainerSchemaNode</code>)\r
277      * @throws IllegalArgumentException\r
278      *             <ul>\r
279      *             <li>if the module equals null</li>\r
280      *             <li>if the name of module equals null</li>\r
281      *             <li>if the set of child nodes equals null</li>\r
282      *             </ul>\r
283      *\r
284      */\r
285     private List<Type> allContainersToGenTypes(final Module module) {\r
286         Preconditions.checkArgument(module != null,"Module reference cannot be NULL.");\r
287 \r
288         Preconditions.checkArgument(module.getName() != null,"Module name cannot be NULL.");\r
289 \r
290         if (module.getChildNodes() == null) {\r
291             throw new IllegalArgumentException("Reference to Set of Child Nodes in module " + module.getName()\r
292                     + " cannot be NULL.");\r
293         }\r
294 \r
295         final List<Type> generatedTypes = new ArrayList<>();\r
296         final DataNodeIterator it = new DataNodeIterator(module);\r
297         final List<ContainerSchemaNode> schemaContainers = it.allContainers();\r
298         final String basePackageName = moduleNamespaceToPackageName(module);\r
299         for (final ContainerSchemaNode container : schemaContainers) {\r
300             if (!container.isAddedByUses()) {\r
301                 generatedTypes.add(containerToGenType(basePackageName, container));\r
302             }\r
303         }\r
304         return generatedTypes;\r
305     }\r
306 \r
307     /**\r
308      * Converts all <b>lists</b> of the module to the list of <code>Type</code>\r
309      * objects.\r
310      *\r
311      * @param module\r
312      *            module from which is obtained DataNodeIterator to iterate over\r
313      *            all lists\r
314      * @return list of <code>Type</code> which are generated from lists (objects\r
315      *         of type <code>ListSchemaNode</code>)\r
316      * @throws IllegalArgumentException\r
317      *             <ul>\r
318      *             <li>if the module equals null</li>\r
319      *             <li>if the name of module equals null</li>\r
320      *             <li>if the set of child nodes equals null</li>\r
321      *             </ul>\r
322      *\r
323      */\r
324     private List<Type> allListsToGenTypes(final Module module) {\r
325         Preconditions.checkArgument(module != null,"Module reference cannot be NULL.");\r
326 \r
327         Preconditions.checkArgument(module.getName() != null,"Module name cannot be NULL.");\r
328 \r
329         if (module.getChildNodes() == null) {\r
330             throw new IllegalArgumentException("Reference to Set of Child Nodes in module " + module.getName()\r
331                     + " cannot be NULL.");\r
332         }\r
333 \r
334         final List<Type> generatedTypes = new ArrayList<>();\r
335         final DataNodeIterator it = new DataNodeIterator(module);\r
336         final List<ListSchemaNode> schemaLists = it.allLists();\r
337         final String basePackageName = moduleNamespaceToPackageName(module);\r
338         if (schemaLists != null) {\r
339             for (final ListSchemaNode list : schemaLists) {\r
340                 if (!list.isAddedByUses()) {\r
341                     generatedTypes.addAll(listToGenType(basePackageName, list));\r
342                 }\r
343             }\r
344         }\r
345         return generatedTypes;\r
346     }\r
347 \r
348     /**\r
349      * Converts all <b>choices</b> of the module to the list of\r
350      * <code>Type</code> objects.\r
351      *\r
352      * @param module\r
353      *            module from which is obtained DataNodeIterator to iterate over\r
354      *            all choices\r
355      * @return list of <code>Type</code> which are generated from choices\r
356      *         (objects of type <code>ChoiceNode</code>)\r
357      * @throws IllegalArgumentException\r
358      *             <ul>\r
359      *             <li>if the module equals null</li>\r
360      *             <li>if the name of module equals null</li> *\r
361      *             </ul>\r
362      *\r
363      */\r
364     private List<GeneratedType> allChoicesToGenTypes(final Module module) {\r
365         Preconditions.checkArgument(module != null,"Module reference cannot be NULL.");\r
366         Preconditions.checkArgument(module.getName() != null,"Module name cannot be NULL.");\r
367 \r
368         final DataNodeIterator it = new DataNodeIterator(module);\r
369         final List<ChoiceNode> choiceNodes = it.allChoices();\r
370         final String basePackageName = moduleNamespaceToPackageName(module);\r
371 \r
372         final List<GeneratedType> generatedTypes = new ArrayList<>();\r
373         for (final ChoiceNode choice : choiceNodes) {\r
374             if ((choice != null) && !choice.isAddedByUses()) {\r
375                 generatedTypes.addAll(choiceToGeneratedType(basePackageName, choice));\r
376             }\r
377         }\r
378         return generatedTypes;\r
379     }\r
380 \r
381     /**\r
382      * Converts all <b>augmentation</b> of the module to the list\r
383      * <code>Type</code> objects.\r
384      *\r
385      * @param module\r
386      *            module from which is obtained list of all augmentation objects\r
387      *            to iterate over them\r
388      * @return list of <code>Type</code> which are generated from augments\r
389      *         (objects of type <code>AugmentationSchema</code>)\r
390      * @throws IllegalArgumentException\r
391      *             <ul>\r
392      *             <li>if the module equals null</li>\r
393      *             <li>if the name of module equals null</li>\r
394      *             <li>if the set of child nodes equals null</li>\r
395      *             </ul>\r
396      *\r
397      */\r
398     private List<Type> allAugmentsToGenTypes(final Module module) {\r
399         Preconditions.checkArgument(module != null,"Module reference cannot be NULL.");\r
400         Preconditions.checkArgument(module.getName() != null,"Module name cannot be NULL.");\r
401         if (module.getChildNodes() == null) {\r
402             throw new IllegalArgumentException("Reference to Set of Augmentation Definitions in module "\r
403                     + module.getName() + " cannot be NULL.");\r
404         }\r
405 \r
406         final List<Type> generatedTypes = new ArrayList<>();\r
407         final String basePackageName = moduleNamespaceToPackageName(module);\r
408         final List<AugmentationSchema> augmentations = resolveAugmentations(module);\r
409         for (final AugmentationSchema augment : augmentations) {\r
410             generatedTypes.addAll(augmentationToGenTypes(basePackageName, augment));\r
411         }\r
412         return generatedTypes;\r
413     }\r
414 \r
415     /**\r
416      * Returns list of <code>AugmentationSchema</code> objects. The objects are\r
417      * sorted according to the length of their target path from the shortest to\r
418      * the longest.\r
419      *\r
420      * @param module\r
421      *            module from which is obtained list of all augmentation objects\r
422      * @return list of sorted <code>AugmentationSchema</code> objects obtained\r
423      *         from <code>module</code>\r
424      * @throws IllegalArgumentException\r
425      *             <ul>\r
426      *             <li>if the module equals null</li>\r
427      *             <li>if the set of augmentation equals null</li>\r
428      *             </ul>\r
429      *\r
430      */\r
431     private List<AugmentationSchema> resolveAugmentations(final Module module) {\r
432         Preconditions.checkArgument(module != null,"Module reference cannot be NULL.");\r
433         Preconditions.checkState(module.getAugmentations() != null,"Augmentations Set cannot be NULL.");\r
434 \r
435         final Set<AugmentationSchema> augmentations = module.getAugmentations();\r
436         final List<AugmentationSchema> sortedAugmentations = new ArrayList<>(augmentations);\r
437         Collections.sort(sortedAugmentations, new Comparator<AugmentationSchema>() {\r
438 \r
439             @Override\r
440             public int compare(AugmentationSchema augSchema1, AugmentationSchema augSchema2) {\r
441 \r
442                 if (augSchema1.getTargetPath().getPath().size() > augSchema2.getTargetPath().getPath().size()) {\r
443                     return 1;\r
444                 } else if (augSchema1.getTargetPath().getPath().size() < augSchema2.getTargetPath().getPath().size()) {\r
445                     return -1;\r
446                 }\r
447                 return 0;\r
448 \r
449             }\r
450         });\r
451 \r
452         return sortedAugmentations;\r
453     }\r
454 \r
455     /**\r
456      * Converts whole <b>module</b> to <code>GeneratedType</code> object.\r
457      * Firstly is created the module builder object from which is finally\r
458      * obtained reference to <code>GeneratedType</code> object.\r
459      *\r
460      * @param module\r
461      *            module from which are obtained the module name, child nodes,\r
462      *            uses and is derived package name\r
463      * @return <code>GeneratedType</code> which is internal representation of\r
464      *         the module\r
465      * @throws IllegalArgumentException\r
466      *             if the module equals null\r
467      *\r
468      */\r
469     private GeneratedType moduleToDataType(final Module module) {\r
470         Preconditions.checkArgument(module != null,"Module reference cannot be NULL.");\r
471 \r
472         final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data");\r
473         addImplementedInterfaceFromUses(module, moduleDataTypeBuilder);\r
474         moduleDataTypeBuilder.addImplementsType(Types.typeForClass(DataRoot.class));\r
475 \r
476         final String basePackageName = moduleNamespaceToPackageName(module);\r
477         if (moduleDataTypeBuilder != null) {\r
478             final Set<DataSchemaNode> dataNodes = module.getChildNodes();\r
479             resolveDataSchemaNodes(basePackageName, moduleDataTypeBuilder, dataNodes);\r
480         }\r
481         return moduleDataTypeBuilder.toInstance();\r
482     }\r
483 \r
484     /**\r
485      * Converts all <b>rpcs</b> inputs and outputs substatements of the module\r
486      * to the list of <code>Type</code> objects. In addition are to containers\r
487      * and lists which belong to input or output also part of returning list.\r
488      *\r
489      * @param module\r
490      *            module from which is obtained set of all rpc objects to\r
491      *            iterate over them\r
492      * @return list of <code>Type</code> which are generated from rpcs inputs,\r
493      *         outputs + container and lists which are part of inputs or outputs\r
494      * @throws IllegalArgumentException\r
495      *             <ul>\r
496      *             <li>if the module equals null</li>\r
497      *             <li>if the name of module equals null</li>\r
498      *             <li>if the set of child nodes equals null</li>\r
499      *             </ul>\r
500      *\r
501      */\r
502     private List<Type> allRPCMethodsToGenType(final Module module) {\r
503         Preconditions.checkArgument(module != null,"Module reference cannot be NULL.");\r
504 \r
505         Preconditions.checkArgument(module.getName() != null,"Module name cannot be NULL.");\r
506 \r
507         if (module.getChildNodes() == null) {\r
508             throw new IllegalArgumentException("Reference to Set of RPC Method Definitions in module "\r
509                     + module.getName() + " cannot be NULL.");\r
510         }\r
511 \r
512         final String basePackageName = moduleNamespaceToPackageName(module);\r
513         final Set<RpcDefinition> rpcDefinitions = module.getRpcs();\r
514 \r
515         if (rpcDefinitions.isEmpty()) {\r
516             return Collections.emptyList();\r
517         }\r
518 \r
519         final List<Type> genRPCTypes = new ArrayList<>();\r
520         final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, "Service");\r
521         interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class));\r
522         final Type future = Types.typeForClass(Future.class);\r
523         for (final RpcDefinition rpc : rpcDefinitions) {\r
524             if (rpc != null) {\r
525 \r
526                 String rpcName = parseToClassName(rpc.getQName().getLocalName());\r
527                 String rpcMethodName = parseToValidParamName(rpcName);\r
528                 MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName);\r
529 \r
530                 final List<DataNodeIterator> rpcInOut = new ArrayList<>();\r
531 \r
532                 ContainerSchemaNode input = rpc.getInput();\r
533                 ContainerSchemaNode output = rpc.getOutput();\r
534 \r
535                 if (input != null) {\r
536                     rpcInOut.add(new DataNodeIterator(input));\r
537                     GeneratedTypeBuilder inType = addRawInterfaceDefinition(basePackageName, input, rpcName);\r
538                     addImplementedInterfaceFromUses(input, inType);\r
539                     inType.addImplementsType(DATA_OBJECT);\r
540                     inType.addImplementsType(augmentable(inType));\r
541                     resolveDataSchemaNodes(basePackageName, inType, input.getChildNodes());\r
542                     Type inTypeInstance = inType.toInstance();\r
543                     genRPCTypes.add(inTypeInstance);\r
544                     method.addParameter(inTypeInstance, "input");\r
545                 }\r
546 \r
547                 Type outTypeInstance = Types.typeForClass(Void.class);\r
548                 if (output != null) {\r
549                     rpcInOut.add(new DataNodeIterator(output));\r
550                     GeneratedTypeBuilder outType = addRawInterfaceDefinition(basePackageName, output, rpcName);\r
551                     addImplementedInterfaceFromUses(output, outType);\r
552                     outType.addImplementsType(DATA_OBJECT);\r
553                     outType.addImplementsType(augmentable(outType));\r
554 \r
555                     resolveDataSchemaNodes(basePackageName, outType, output.getChildNodes());\r
556                     outTypeInstance = outType.toInstance();\r
557                     genRPCTypes.add(outTypeInstance);\r
558 \r
559                 }\r
560 \r
561                 final Type rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult.class), outTypeInstance);\r
562                 method.setReturnType(Types.parameterizedTypeFor(future, rpcRes));\r
563                 for (DataNodeIterator it : rpcInOut) {\r
564                     List<ContainerSchemaNode> nContainers = it.allContainers();\r
565                     if ((nContainers != null) && !nContainers.isEmpty()) {\r
566                         for (final ContainerSchemaNode container : nContainers) {\r
567                             if (!container.isAddedByUses()) {\r
568                                 genRPCTypes.add(containerToGenType(basePackageName, container));\r
569                             }\r
570                         }\r
571                     }\r
572                     List<ListSchemaNode> nLists = it.allLists();\r
573                     if ((nLists != null) && !nLists.isEmpty()) {\r
574                         for (final ListSchemaNode list : nLists) {\r
575                             if (!list.isAddedByUses()) {\r
576                                 genRPCTypes.addAll(listToGenType(basePackageName, list));\r
577                             }\r
578                         }\r
579                     }\r
580                 }\r
581             }\r
582         }\r
583         genRPCTypes.add(interfaceBuilder.toInstance());\r
584         return genRPCTypes;\r
585     }\r
586 \r
587     /**\r
588      * Converts all <b>notifications</b> of the module to the list of\r
589      * <code>Type</code> objects. In addition are to this list added containers\r
590      * and lists which are part of this notification.\r
591      *\r
592      * @param module\r
593      *            module from which is obtained set of all notification objects\r
594      *            to iterate over them\r
595      * @return list of <code>Type</code> which are generated from notification\r
596      *         (object of type <code>NotificationDefinition</code>\r
597      * @throws IllegalArgumentException\r
598      *             <ul>\r
599      *             <li>if the module equals null</li>\r
600      *             <li>if the name of module equals null</li>\r
601      *             <li>if the set of child nodes equals null</li>\r
602      *             </ul>\r
603      *\r
604      */\r
605     private List<Type> allNotificationsToGenType(final Module module) {\r
606         Preconditions.checkArgument(module != null,"Module reference cannot be NULL.");\r
607 \r
608         Preconditions.checkArgument(module.getName() != null,"Module name cannot be NULL.");\r
609 \r
610         if (module.getChildNodes() == null) {\r
611             throw new IllegalArgumentException("Reference to Set of Notification Definitions in module "\r
612                     + module.getName() + " cannot be NULL.");\r
613         }\r
614 \r
615         final String basePackageName = moduleNamespaceToPackageName(module);\r
616         final List<Type> genNotifyTypes = new ArrayList<>();\r
617         final Set<NotificationDefinition> notifications = module.getNotifications();\r
618 \r
619         for (final NotificationDefinition notification : notifications) {\r
620             if (notification != null) {\r
621                 DataNodeIterator it = new DataNodeIterator(notification);\r
622 \r
623                 // Containers\r
624                 for (ContainerSchemaNode node : it.allContainers()) {\r
625                     if (!node.isAddedByUses()) {\r
626                         genNotifyTypes.add(containerToGenType(basePackageName, node));\r
627                     }\r
628                 }\r
629                 // Lists\r
630                 for (ListSchemaNode node : it.allLists()) {\r
631                     if (!node.isAddedByUses()) {\r
632                         genNotifyTypes.addAll(listToGenType(basePackageName, node));\r
633                     }\r
634                 }\r
635                 final GeneratedTypeBuilder notificationTypeBuilder = addDefaultInterfaceDefinition(basePackageName,\r
636                         notification);\r
637                 notificationTypeBuilder.addImplementsType(Types\r
638                         .typeForClass(org.opendaylight.yangtools.yang.binding.Notification.class));\r
639                 // Notification object\r
640                 resolveDataSchemaNodes(basePackageName, notificationTypeBuilder, notification.getChildNodes());\r
641                 genNotifyTypes.add(notificationTypeBuilder.toInstance());\r
642             }\r
643         }\r
644         return genNotifyTypes;\r
645     }\r
646 \r
647     /**\r
648      * Converts all <b>identities</b> of the module to the list of\r
649      * <code>Type</code> objects.\r
650      *\r
651      * @param module\r
652      *            module from which is obtained set of all identity objects to\r
653      *            iterate over them\r
654      * @param context\r
655      *            schema context only used as input parameter for method\r
656      *            {@link identityToGenType}\r
657      * @return list of <code>Type</code> which are generated from identities\r
658      *         (object of type <code>IdentitySchemaNode</code>\r
659      *\r
660      */\r
661     private List<Type> allIdentitiesToGenTypes(final Module module, final SchemaContext context) {\r
662         List<Type> genTypes = new ArrayList<>();\r
663 \r
664         final Set<IdentitySchemaNode> schemaIdentities = module.getIdentities();\r
665 \r
666         final String basePackageName = moduleNamespaceToPackageName(module);\r
667 \r
668         if (schemaIdentities != null && !schemaIdentities.isEmpty()) {\r
669             for (final IdentitySchemaNode identity : schemaIdentities) {\r
670                 genTypes.add(identityToGenType(basePackageName, identity, context));\r
671             }\r
672         }\r
673         return genTypes;\r
674     }\r
675 \r
676     /**\r
677      * Converts the <b>identity</b> object to GeneratedType. Firstly it is\r
678      * created transport object builder. If identity contains base identity then\r
679      * reference to base identity is added to superior identity as its extend.\r
680      * If identity doesn't contain base identity then only reference to abstract\r
681      * class {@link org.opendaylight.yangtools.yang.model.api.BaseIdentity\r
682      * BaseIdentity} is added\r
683      *\r
684      * @param basePackageName\r
685      *            string contains the module package name\r
686      * @param identity\r
687      *            IdentitySchemaNode which contains data about identity\r
688      * @param context\r
689      *            SchemaContext which is used to get package and name\r
690      *            information about base of identity\r
691      *\r
692      * @return GeneratedType which is generated from identity (object of type\r
693      *         <code>IdentitySchemaNode</code>\r
694      *\r
695      */\r
696     private GeneratedType identityToGenType(final String basePackageName, final IdentitySchemaNode identity,\r
697             final SchemaContext context) {\r
698         if (identity == null) {\r
699             return null;\r
700         }\r
701 \r
702         final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath());\r
703         final String genTypeName = parseToClassName(identity.getQName().getLocalName());\r
704         final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTypeName);\r
705 \r
706         IdentitySchemaNode baseIdentity = identity.getBaseIdentity();\r
707         if (baseIdentity != null) {\r
708             Module baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity);\r
709 \r
710             final String returnTypePkgName = moduleNamespaceToPackageName(baseIdentityParentModule);\r
711             final String returnTypeName = parseToClassName(baseIdentity.getQName().getLocalName());\r
712 \r
713             GeneratedTransferObject gto = new GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName).toInstance();\r
714             newType.setExtendsType(gto);\r
715         } else {\r
716             newType.setExtendsType(Types.getBaseIdentityTO());\r
717         }\r
718         newType.setAbstract(true);\r
719         return newType.toInstance();\r
720     }\r
721 \r
722     /**\r
723      * Converts all <b>groupings</b> of the module to the list of\r
724      * <code>Type</code> objects. Firstly are groupings sorted according mutual\r
725      * dependencies. At least dependend (indepedent) groupings are in the list\r
726      * saved at first positions. For every grouping the record is added to map\r
727      * {@link BindingGeneratorImpl#allGroupings allGroupings}\r
728      *\r
729      * @param module\r
730      *            module from which is obtained set of all grouping objects to\r
731      *            iterate over them\r
732      * @return list of <code>Type</code> which are generated from groupings\r
733      *         (object of type <code>GroupingDefinition</code>)\r
734      *\r
735      */\r
736     private List<Type> allGroupingsToGenTypes(final Module module) {\r
737         Preconditions.checkArgument(module != null,"Module parameter can not be null");\r
738         final List<Type> genTypes = new ArrayList<>();\r
739         final String basePackageName = moduleNamespaceToPackageName(module);\r
740         final Set<GroupingDefinition> groupings = module.getGroupings();\r
741         List<GroupingDefinition> groupingsSortedByDependencies;\r
742 \r
743         groupingsSortedByDependencies = GroupingDefinitionDependencySort.sort(groupings);\r
744 \r
745         for (final GroupingDefinition grouping : groupingsSortedByDependencies) {\r
746             GeneratedType genType = groupingToGenType(basePackageName, grouping);\r
747             genTypes.add(genType);\r
748             SchemaPath schemaPath = grouping.getPath();\r
749             allGroupings.put(schemaPath, genType);\r
750         }\r
751         return genTypes;\r
752     }\r
753 \r
754     /**\r
755      * Converts individual grouping to GeneratedType. Firstly generated type\r
756      * builder is created and every child node of grouping is resolved to the\r
757      * method.\r
758      *\r
759      * @param basePackageName\r
760      *            string contains the module package name\r
761      * @param grouping\r
762      *            GroupingDefinition which contains data about grouping\r
763      * @return GeneratedType which is generated from grouping (object of type\r
764      *         <code>GroupingDefinition</code>)\r
765      */\r
766     private GeneratedType groupingToGenType(final String basePackageName, GroupingDefinition grouping) {\r
767         if (grouping == null) {\r
768             return null;\r
769         }\r
770 \r
771         final String packageName = packageNameForGeneratedType(basePackageName, grouping.getPath());\r
772         final Set<DataSchemaNode> schemaNodes = grouping.getChildNodes();\r
773         final GeneratedTypeBuilder typeBuilder = addDefaultInterfaceDefinition(packageName, grouping);\r
774 \r
775         resolveDataSchemaNodes(basePackageName, typeBuilder, schemaNodes);\r
776         return typeBuilder.toInstance();\r
777     }\r
778 \r
779     /**\r
780      * Tries to find EnumTypeDefinition in <code>typeDefinition</code>. If base\r
781      * type of <code>typeDefinition</code> is of the type ExtendedType then this\r
782      * method is recursivelly called with this base type.\r
783      *\r
784      * @param typeDefinition\r
785      *            TypeDefinition in which should be EnumTypeDefinition found as\r
786      *            base type\r
787      * @return EnumTypeDefinition if it is found inside\r
788      *         <code>typeDefinition</code> or <code>null</code> in other case\r
789      */\r
790     private EnumTypeDefinition enumTypeDefFromExtendedType(final TypeDefinition<?> typeDefinition) {\r
791         if (typeDefinition != null) {\r
792             if (typeDefinition.getBaseType() instanceof EnumTypeDefinition) {\r
793                 return (EnumTypeDefinition) typeDefinition.getBaseType();\r
794             } else if (typeDefinition.getBaseType() instanceof ExtendedType) {\r
795                 return enumTypeDefFromExtendedType(typeDefinition.getBaseType());\r
796             }\r
797         }\r
798         return null;\r
799     }\r
800 \r
801     /**\r
802      * Adds enumeration builder created from <code>enumTypeDef</code> to\r
803      * <code>typeBuilder</code>.\r
804      *\r
805      * Each <code>enumTypeDef</code> item is added to builder with its name and\r
806      * value.\r
807      *\r
808      * @param enumTypeDef\r
809      *            EnumTypeDefinition contains enum data\r
810      * @param enumName\r
811      *            string contains name which will be assigned to enumeration\r
812      *            builder\r
813      * @param typeBuilder\r
814      *            GeneratedTypeBuilder to which will be enum builder assigned\r
815      * @return enumeration builder which contais data from\r
816      *         <code>enumTypeDef</code>\r
817      */\r
818     private EnumBuilder resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final String enumName,\r
819             final GeneratedTypeBuilder typeBuilder) {\r
820         if ((enumTypeDef != null) && (typeBuilder != null) && (enumTypeDef.getQName() != null)\r
821                 && (enumTypeDef.getQName().getLocalName() != null)) {\r
822 \r
823             final String enumerationName = parseToClassName(enumName);\r
824             final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);\r
825             enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);\r
826 \r
827             return enumBuilder;\r
828         }\r
829         return null;\r
830     }\r
831 \r
832     /**\r
833      * Generates type builder for <code>module</code>.\r
834      *\r
835      * @param module\r
836      *            Module which is source of package name for generated type\r
837      *            builder\r
838      * @param postfix\r
839      *            string which is added to the module class name representation\r
840      *            as suffix\r
841      * @return instance of GeneratedTypeBuilder which represents\r
842      *         <code>module</code>.\r
843      * @throws IllegalArgumentException\r
844      *             if <code>module</code> equals null\r
845      */\r
846     private GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix) {\r
847         Preconditions.checkArgument(module != null,"Module reference cannot be NULL.");\r
848         String packageName = moduleNamespaceToPackageName(module);\r
849         final String moduleName = parseToClassName(module.getName()) + postfix;\r
850 \r
851         return new GeneratedTypeBuilderImpl(packageName, moduleName);\r
852 \r
853     }\r
854 \r
855     /**\r
856      * Converts <code>augSchema</code> to list of <code>Type</code> which\r
857      * contains generated type for augmentation. In addition there are also\r
858      * generated types for all containers, list and choices which are child of\r
859      * <code>augSchema</code> node or a generated types for cases are added if\r
860      * augmented node is choice.\r
861      *\r
862      * @param augmentPackageName\r
863      *            string with the name of the package to which the augmentation\r
864      *            belongs\r
865      * @param augSchema\r
866      *            AugmentationSchema which is contains data about agumentation\r
867      *            (target path, childs...)\r
868      * @return list of <code>Type</code> objects which contains generated type\r
869      *         for augmentation and for container, list and choice child nodes\r
870      * @throws IllegalArgumentException\r
871      *             <ul>\r
872      *             <li>if <code>augmentPackageName</code> equals null</li>\r
873      *             <li>if <code>augSchema</code> equals null</li>\r
874      *             <li>if target path of <code>augSchema</code> equals null</li>\r
875      *             </ul>\r
876      */\r
877     private List<Type> augmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema) {\r
878         Preconditions.checkArgument(augmentPackageName != null,"Package Name cannot be NULL.");\r
879         Preconditions.checkArgument(augSchema != null,"Augmentation Schema cannot be NULL.");\r
880         Preconditions.checkState(augSchema.getTargetPath() != null,"Augmentation Schema does not contain Target Path (Target Path is NULL).");\r
881 \r
882         final List<Type> genTypes = new ArrayList<>();\r
883 \r
884         // EVERY augmented interface will extends Augmentation<T> interface\r
885         // and DataObject interface!!!\r
886         final SchemaPath targetPath = augSchema.getTargetPath();\r
887         final DataSchemaNode targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);\r
888         if ((targetSchemaNode != null) && (targetSchemaNode.getQName() != null)\r
889                 && (targetSchemaNode.getQName().getLocalName() != null)) {\r
890             final Module targetModule = findParentModule(schemaContext, targetSchemaNode);\r
891             final String targetBasePackage = moduleNamespaceToPackageName(targetModule);\r
892             final String targetPackageName = packageNameForGeneratedType(targetBasePackage, targetSchemaNode.getPath());\r
893             final String targetSchemaNodeName = targetSchemaNode.getQName().getLocalName();\r
894             final Set<DataSchemaNode> augChildNodes = augSchema.getChildNodes();\r
895 \r
896             if (!(targetSchemaNode instanceof ChoiceNode)) {\r
897                 final GeneratedTypeBuilder augTypeBuilder = addRawAugmentGenTypeDefinition(augmentPackageName,\r
898                         targetPackageName, targetSchemaNodeName, augSchema);\r
899                 final GeneratedType augType = augTypeBuilder.toInstance();\r
900                 genTypes.add(augType);\r
901             } else {\r
902                 final Type refChoiceType = new ReferencedTypeImpl(targetPackageName,\r
903                         parseToClassName(targetSchemaNodeName));\r
904                 final ChoiceNode choiceTarget = (ChoiceNode) targetSchemaNode;\r
905                 final Set<ChoiceCaseNode> choiceCaseNodes = choiceTarget.getCases();\r
906                 genTypes.addAll(generateTypesFromAugmentedChoiceCases(augmentPackageName, refChoiceType,\r
907                         choiceCaseNodes));\r
908             }\r
909             genTypes.addAll(augmentationBodyToGenTypes(augmentPackageName, augChildNodes));\r
910         }\r
911         return genTypes;\r
912     }\r
913 \r
914     /**\r
915      * Returns a generated type builder for an augmentation.\r
916      *\r
917      * The name of the type builder is equal to the name of augmented node with\r
918      * serial number as suffix.\r
919      *\r
920      * @param augmentPackageName\r
921      *            string with contains the package name to which the augment\r
922      *            belongs\r
923      * @param targetPackageName\r
924      *            string with the package name to which the augmented node\r
925      *            belongs\r
926      * @param targetSchemaNodeName\r
927      *            string with the name of the augmented node\r
928      * @param augSchema\r
929      *            augmentation schema which contains data about the child nodes\r
930      *            and uses of augment\r
931      * @return generated type builder for augment\r
932      */\r
933     private GeneratedTypeBuilder addRawAugmentGenTypeDefinition(final String augmentPackageName,\r
934             final String targetPackageName, final String targetSchemaNodeName, final AugmentationSchema augSchema) {\r
935         final String targetTypeName = parseToClassName(targetSchemaNodeName);\r
936         Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);\r
937         if (augmentBuilders == null) {\r
938             augmentBuilders = new HashMap<>();\r
939             genTypeBuilders.put(augmentPackageName, augmentBuilders);\r
940         }\r
941         final String augIdentifier = getAugmentIdentifier(augSchema.getUnknownSchemaNodes());\r
942 \r
943         final String augTypeName = augIdentifier != null ? parseToClassName(augIdentifier) : augGenTypeName(\r
944                 augmentBuilders, targetTypeName);\r
945         final Type targetTypeRef = new ReferencedTypeImpl(targetPackageName, targetTypeName);\r
946         final Set<DataSchemaNode> augChildNodes = augSchema.getChildNodes();\r
947 \r
948         final GeneratedTypeBuilder augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName);\r
949 \r
950         augTypeBuilder.addImplementsType(DATA_OBJECT);\r
951         augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));\r
952         addImplementedInterfaceFromUses(augSchema, augTypeBuilder);\r
953 \r
954         augSchemaNodeToMethods(augmentPackageName, augTypeBuilder, augChildNodes);\r
955         augmentBuilders.put(augTypeName, augTypeBuilder);\r
956         return augTypeBuilder;\r
957     }\r
958 \r
959     /**\r
960      *\r
961      * @param unknownSchemaNodes\r
962      * @return\r
963      */\r
964     private String getAugmentIdentifier(List<UnknownSchemaNode> unknownSchemaNodes) {\r
965         String ret = null;\r
966         for (UnknownSchemaNode unknownSchemaNode : unknownSchemaNodes) {\r
967             QName nodeType = unknownSchemaNode.getNodeType();\r
968             if (AUGMENT_IDENTIFIER_NAME.equals(nodeType.getLocalName())\r
969                     && YANG_EXT_NAMESPACE.equals(nodeType.getNamespace().toString())) {\r
970                 return unknownSchemaNode.getNodeParameter();\r
971             }\r
972         }\r
973         return ret;\r
974     }\r
975 \r
976     /**\r
977      * Convert a container, list and choice subnodes (and recursivelly their\r
978      * subnodes) of augment to generated types\r
979      *\r
980      * @param augBasePackageName\r
981      *            string with the augment package name\r
982      * @param augChildNodes\r
983      *            set of data schema nodes which represents child nodes of the\r
984      *            augment\r
985      *\r
986      * @return list of <code>Type</code> which represents container, list and\r
987      *         choice subnodes of augment\r
988      */\r
989     private List<Type> augmentationBodyToGenTypes(final String augBasePackageName,\r
990             final Set<DataSchemaNode> augChildNodes) {\r
991         final List<Type> genTypes = new ArrayList<>();\r
992         final List<DataNodeIterator> augSchemaIts = new ArrayList<>();\r
993         for (final DataSchemaNode childNode : augChildNodes) {\r
994             if (childNode instanceof DataNodeContainer) {\r
995                 augSchemaIts.add(new DataNodeIterator((DataNodeContainer) childNode));\r
996 \r
997                 if (childNode instanceof ContainerSchemaNode) {\r
998                     genTypes.add(containerToGenType(augBasePackageName, (ContainerSchemaNode) childNode));\r
999                 } else if (childNode instanceof ListSchemaNode) {\r
1000                     genTypes.addAll(listToGenType(augBasePackageName, (ListSchemaNode) childNode));\r
1001                 }\r
1002             } else if (childNode instanceof ChoiceNode) {\r
1003                 final ChoiceNode choice = (ChoiceNode) childNode;\r
1004                 for (final ChoiceCaseNode caseNode : choice.getCases()) {\r
1005                     augSchemaIts.add(new DataNodeIterator(caseNode));\r
1006                 }\r
1007                 genTypes.addAll(choiceToGeneratedType(augBasePackageName, (ChoiceNode) childNode));\r
1008             }\r
1009         }\r
1010 \r
1011         for (final DataNodeIterator it : augSchemaIts) {\r
1012             final List<ContainerSchemaNode> augContainers = it.allContainers();\r
1013             final List<ListSchemaNode> augLists = it.allLists();\r
1014             final List<ChoiceNode> augChoices = it.allChoices();\r
1015 \r
1016             if (augContainers != null) {\r
1017                 for (final ContainerSchemaNode container : augContainers) {\r
1018                     genTypes.add(containerToGenType(augBasePackageName, container));\r
1019                 }\r
1020             }\r
1021             if (augLists != null) {\r
1022                 for (final ListSchemaNode list : augLists) {\r
1023                     genTypes.addAll(listToGenType(augBasePackageName, list));\r
1024                 }\r
1025             }\r
1026             if (augChoices != null) {\r
1027                 for (final ChoiceNode choice : augChoices) {\r
1028                     genTypes.addAll(choiceToGeneratedType(augBasePackageName, choice));\r
1029                 }\r
1030             }\r
1031         }\r
1032         return genTypes;\r
1033     }\r
1034 \r
1035     /**\r
1036      * Returns first unique name for the augment generated type builder. The\r
1037      * generated type builder name for augment consists from name of augmented\r
1038      * node and serial number of its augmentation.\r
1039      *\r
1040      * @param builders\r
1041      *            map of builders which were created in the package to which the\r
1042      *            augmentation belongs\r
1043      * @param genTypeName\r
1044      *            string with name of augmented node\r
1045      * @return string with unique name for augmentation builder\r
1046      */\r
1047     private String augGenTypeName(final Map<String, GeneratedTypeBuilder> builders, final String genTypeName) {\r
1048         String augTypeName = genTypeName;\r
1049 \r
1050         int index = 1;\r
1051         while ((builders != null) && builders.containsKey(genTypeName + index)) {\r
1052             index++;\r
1053         }\r
1054         augTypeName += index;\r
1055         return augTypeName;\r
1056     }\r
1057 \r
1058     /**\r
1059      * Converts <code>containerNode</code> to generated type. Firstly the\r
1060      * generated type builder is created. The subnodes of\r
1061      * <code>containerNode</code> are added as methods and the instance of\r
1062      * <code>GeneratedType</code> is returned.\r
1063      *\r
1064      * @param basePackageName\r
1065      *            string contains the module package name\r
1066      * @param containerNode\r
1067      *            container schema node with the data about childs nodes and\r
1068      *            schema paths\r
1069      * @return generated type for <code>containerNode</code>\r
1070      */\r
1071     private GeneratedType containerToGenType(final String basePackageName, ContainerSchemaNode containerNode) {\r
1072         if (containerNode == null) {\r
1073             return null;\r
1074         }\r
1075 \r
1076         final String packageName = packageNameForGeneratedType(basePackageName, containerNode.getPath());\r
1077         final Set<DataSchemaNode> schemaNodes = containerNode.getChildNodes();\r
1078         final GeneratedTypeBuilder typeBuilder = addDefaultInterfaceDefinition(packageName, containerNode);\r
1079 \r
1080         resolveDataSchemaNodes(basePackageName, typeBuilder, schemaNodes);\r
1081         return typeBuilder.toInstance();\r
1082     }\r
1083 \r
1084     /**\r
1085      * Adds the methods to <code>typeBuilder</code> which represent subnodes of\r
1086      * node for which <code>typeBuilder</code> was created.\r
1087      *\r
1088      * The subnodes aren't mapped to the methods if they are part of grouping or\r
1089      * augment (in this case are already part of them).\r
1090      *\r
1091      * @param basePackageName\r
1092      *            string contains the module package name\r
1093      * @param typeBuilder\r
1094      *            generated type builder which represents any node. The subnodes\r
1095      *            of this node are added to the <code>typeBuilder</code> as\r
1096      *            methods. The subnode can be of type leaf, leaf-list, list,\r
1097      *            container, choice.\r
1098      * @param schemaNodes\r
1099      *            set of data schema nodes which are the children of the node\r
1100      *            for which <code>typeBuilder</code> was created\r
1101      * @return generated type builder which is the same builder as input\r
1102      *         parameter. The getter methods (representing child nodes) could be\r
1103      *         added to it.\r
1104      */\r
1105     private GeneratedTypeBuilder resolveDataSchemaNodes(final String basePackageName,\r
1106             final GeneratedTypeBuilder typeBuilder, final Set<DataSchemaNode> schemaNodes) {\r
1107         if ((schemaNodes != null) && (typeBuilder != null)) {\r
1108             for (final DataSchemaNode schemaNode : schemaNodes) {\r
1109                 if (schemaNode.isAugmenting() || schemaNode.isAddedByUses()) {\r
1110                     continue;\r
1111                 }\r
1112                 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder);\r
1113             }\r
1114         }\r
1115         return typeBuilder;\r
1116     }\r
1117 \r
1118     /**\r
1119      * Adds the methods to <code>typeBuilder</code> what represents subnodes of\r
1120      * node for which <code>typeBuilder</code> was created.\r
1121      *\r
1122      * @param basePackageName\r
1123      *            string contains the module package name\r
1124      * @param typeBuilder\r
1125      *            generated type builder which represents any node. The subnodes\r
1126      *            of this node are added to the <code>typeBuilder</code> as\r
1127      *            methods. The subnode can be of type leaf, leaf-list, list,\r
1128      *            container, choice.\r
1129      * @param schemaNodes\r
1130      *            set of data schema nodes which are the children of the node\r
1131      *            for which <code>typeBuilder</code> was created\r
1132      * @return generated type builder which is the same object as the input\r
1133      *         parameter <code>typeBuilder</code>. The getter method could be\r
1134      *         added to it.\r
1135      */\r
1136     private GeneratedTypeBuilder augSchemaNodeToMethods(final String basePackageName,\r
1137             final GeneratedTypeBuilder typeBuilder, final Set<DataSchemaNode> schemaNodes) {\r
1138         if ((schemaNodes != null) && (typeBuilder != null)) {\r
1139             for (final DataSchemaNode schemaNode : schemaNodes) {\r
1140                 if (schemaNode.isAugmenting()) {\r
1141                     addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder);\r
1142                 }\r
1143             }\r
1144         }\r
1145         return typeBuilder;\r
1146     }\r
1147 \r
1148     /**\r
1149      * Adds to <code>typeBuilder</code> a method which is derived from\r
1150      * <code>schemaNode</code>.\r
1151      *\r
1152      * @param basePackageName\r
1153      *            string with the module package name\r
1154      * @param schemaNode\r
1155      *            data schema node which is added to <code>typeBuilder</code> as\r
1156      *            a method\r
1157      * @param typeBuilder\r
1158      *            generated type builder to which is <code>schemaNode</code>\r
1159      *            added as a method.\r
1160      */\r
1161     private void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode schemaNode,\r
1162             final GeneratedTypeBuilder typeBuilder) {\r
1163         if (schemaNode != null && typeBuilder != null) {\r
1164             if (schemaNode instanceof LeafSchemaNode) {\r
1165                 resolveLeafSchemaNodeAsMethod(typeBuilder, (LeafSchemaNode) schemaNode);\r
1166             } else if (schemaNode instanceof LeafListSchemaNode) {\r
1167                 resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode);\r
1168             } else if (schemaNode instanceof ContainerSchemaNode) {\r
1169                 resolveContainerSchemaNode(basePackageName, typeBuilder, (ContainerSchemaNode) schemaNode);\r
1170             } else if (schemaNode instanceof ListSchemaNode) {\r
1171                 resolveListSchemaNode(basePackageName, typeBuilder, (ListSchemaNode) schemaNode);\r
1172             } else if (schemaNode instanceof ChoiceNode) {\r
1173                 resolveChoiceSchemaNode(basePackageName, typeBuilder, (ChoiceNode) schemaNode);\r
1174             }\r
1175         }\r
1176     }\r
1177 \r
1178     /**\r
1179      * Creates a getter method for a choice node.\r
1180      *\r
1181      * Firstly generated type builder for choice is created or found in\r
1182      * {@link BindingGeneratorImpl#allGroupings allGroupings}. The package name\r
1183      * in the builder is created as concatenation of module package name and\r
1184      * names of all parent nodes. In the end the getter method for choice is\r
1185      * added to <code>typeBuilder</code> and return type is set to choice\r
1186      * builder.\r
1187      *\r
1188      * @param basePackageName\r
1189      *            string with the module package name\r
1190      * @param typeBuilder\r
1191      *            generated type builder to which is <code>choiceNode</code>\r
1192      *            added as getter method\r
1193      * @param choiceNode\r
1194      *            choice node which is mapped as a getter method\r
1195      * @throws IllegalArgumentException\r
1196      *             <ul>\r
1197      *             <li>if <code>basePackageName</code> equals null</li>\r
1198      *             <li>if <code>typeBuilder</code> equals null</li>\r
1199      *             <li>if <code>choiceNode</code> equals null</li>\r
1200      *             </ul>\r
1201      *\r
1202      */\r
1203     private void resolveChoiceSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder,\r
1204             final ChoiceNode choiceNode) {\r
1205         Preconditions.checkArgument(basePackageName != null,"Base Package Name cannot be NULL.");\r
1206         Preconditions.checkArgument(typeBuilder != null,"Generated Type Builder cannot be NULL.");\r
1207         Preconditions.checkArgument(choiceNode != null,"Choice Schema Node cannot be NULL.");\r
1208 \r
1209         final String choiceName = choiceNode.getQName().getLocalName();\r
1210         if (choiceName != null && !choiceNode.isAddedByUses()) {\r
1211             final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath());\r
1212             final GeneratedTypeBuilder choiceType = addDefaultInterfaceDefinition(packageName, choiceNode);\r
1213             constructGetter(typeBuilder, choiceName, choiceNode.getDescription(), choiceType);\r
1214         }\r
1215     }\r
1216 \r
1217     /**\r
1218      * Converts <code>choiceNode</code> to the list of generated types for\r
1219      * choice and its cases.\r
1220      *\r
1221      * The package names for choice and for its cases are created as\r
1222      * concatenation of the module package (<code>basePackageName</code>) and\r
1223      * names of all parents node.\r
1224      *\r
1225      * @param basePackageName\r
1226      *            string with the module package name\r
1227      * @param choiceNode\r
1228      *            choice node which is mapped to generated type. Also child\r
1229      *            nodes - cases are mapped to generated types.\r
1230      * @return list of generated types which contains generated type for choice\r
1231      *         and generated types for all cases which aren't added do choice\r
1232      *         through <i>uses</i>.\r
1233      * @throws IllegalArgumentException\r
1234      *             <ul>\r
1235      *             <li>if <code>basePackageName</code> equals null</li>\r
1236      *             <li>if <code>choiceNode</code> equals null</li>\r
1237      *             </ul>\r
1238      *\r
1239      */\r
1240     private List<GeneratedType> choiceToGeneratedType(final String basePackageName, final ChoiceNode choiceNode) {\r
1241         Preconditions.checkArgument(basePackageName != null,"Base Package Name cannot be NULL.");\r
1242         Preconditions.checkArgument(choiceNode != null,"Choice Schema Node cannot be NULL.");\r
1243 \r
1244         final List<GeneratedType> generatedTypes = new ArrayList<>();\r
1245         final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath());\r
1246         final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode);\r
1247         choiceTypeBuilder.addImplementsType(DATA_OBJECT);\r
1248         final GeneratedType choiceType = choiceTypeBuilder.toInstance();\r
1249 \r
1250         generatedTypes.add(choiceType);\r
1251         final Set<ChoiceCaseNode> caseNodes = choiceNode.getCases();\r
1252         if ((caseNodes != null) && !caseNodes.isEmpty()) {\r
1253             generatedTypes.addAll(generateTypesFromChoiceCases(basePackageName, choiceType, caseNodes));\r
1254         }\r
1255         return generatedTypes;\r
1256     }\r
1257 \r
1258     /**\r
1259      * Converts <code>caseNodes</code> set to list of corresponding generated\r
1260      * types.\r
1261      *\r
1262      * For every <i>case</i> which isn't added through augment or <i>uses</i> is\r
1263      * created generated type builder. The package names for the builder is\r
1264      * created as concatenation of the module package (\r
1265      * <code>basePackageName</code>) and names of all parents nodes of the\r
1266      * concrete <i>case</i>. There is also relation "<i>implements type</i>"\r
1267      * between every case builder and <i>choice</i> type\r
1268      *\r
1269      * @param basePackageName\r
1270      *            string with the module package name\r
1271      * @param refChoiceType\r
1272      *            type which represents superior <i>case</i>\r
1273      * @param caseNodes\r
1274      *            set of choice case nodes which are mapped to generated types\r
1275      * @return list of generated types for <code>caseNodes</code>.\r
1276      * @throws IllegalArgumentException\r
1277      *             <ul>\r
1278      *             <li>if <code>basePackageName</code> equals null</li>\r
1279      *             <li>if <code>refChoiceType</code> equals null</li>\r
1280      *             <li>if <code>caseNodes</code> equals null</li>\r
1281      *             </ul>\r
1282      *             *\r
1283      */\r
1284     private List<GeneratedType> generateTypesFromChoiceCases(final String basePackageName, final Type refChoiceType,\r
1285             final Set<ChoiceCaseNode> caseNodes) {\r
1286         Preconditions.checkArgument(basePackageName != null,"Base Package Name cannot be NULL.");\r
1287         Preconditions.checkArgument(refChoiceType != null,"Referenced Choice Type cannot be NULL.");\r
1288         Preconditions.checkArgument(caseNodes != null,"Set of Choice Case Nodes cannot be NULL.");\r
1289 \r
1290         final List<GeneratedType> generatedTypes = new ArrayList<>();\r
1291         for (final ChoiceCaseNode caseNode : caseNodes) {\r
1292             if (caseNode != null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) {\r
1293                 final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());\r
1294                 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);\r
1295                 caseTypeBuilder.addImplementsType(refChoiceType);\r
1296 \r
1297                 final Set<DataSchemaNode> childNodes = caseNode.getChildNodes();\r
1298                 if (childNodes != null) {\r
1299                     resolveDataSchemaNodes(basePackageName, caseTypeBuilder, childNodes);\r
1300                 }\r
1301                 generatedTypes.add(caseTypeBuilder.toInstance());\r
1302             }\r
1303         }\r
1304 \r
1305         return generatedTypes;\r
1306     }\r
1307 \r
1308     /**\r
1309      * Generates list of generated types for all the cases of a choice which are\r
1310      * added to the choice through the augment.\r
1311      *\r
1312      *\r
1313      * @param basePackageName\r
1314      *            string contains name of package to which augment belongs. If\r
1315      *            an augmented choice is from an other package (pcg1) than an\r
1316      *            augmenting choice (pcg2) then case's of the augmenting choice\r
1317      *            will belong to pcg2.\r
1318      * @param refChoiceType\r
1319      *            Type which represents the choice to which case belongs. Every\r
1320      *            case has to contain its choice in extend part.\r
1321      * @param caseNodes\r
1322      *            set of choice case nodes for which is checked if are/aren't\r
1323      *            added to choice through augmentation\r
1324      * @return list of generated types which represents augmented cases of\r
1325      *         choice <code>refChoiceType</code>\r
1326      * @throws IllegalArgumentException\r
1327      *             <ul>\r
1328      *             <li>if <code>basePackageName</code> equals null</li>\r
1329      *             <li>if <code>refChoiceType</code> equals null</li>\r
1330      *             <li>if <code>caseNodes</code> equals null</li>\r
1331      *             </ul>\r
1332      */\r
1333     private List<GeneratedType> generateTypesFromAugmentedChoiceCases(final String basePackageName,\r
1334             final Type refChoiceType, final Set<ChoiceCaseNode> caseNodes) {\r
1335         Preconditions.checkArgument(basePackageName != null,"Base Package Name cannot be NULL.");\r
1336         Preconditions.checkArgument(refChoiceType != null,"Referenced Choice Type cannot be NULL.");\r
1337         Preconditions.checkArgument(caseNodes != null,"Set of Choice Case Nodes cannot be NULL.");\r
1338 \r
1339         final List<GeneratedType> generatedTypes = new ArrayList<>();\r
1340         for (final ChoiceCaseNode caseNode : caseNodes) {\r
1341             if (caseNode != null && caseNode.isAugmenting()) {\r
1342                 final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());\r
1343                 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);\r
1344                 caseTypeBuilder.addImplementsType(refChoiceType);\r
1345 \r
1346                 final Set<DataSchemaNode> childNodes = caseNode.getChildNodes();\r
1347                 if (childNodes != null) {\r
1348                     resolveDataSchemaNodes(basePackageName, caseTypeBuilder, childNodes);\r
1349                 }\r
1350                 generatedTypes.add(caseTypeBuilder.toInstance());\r
1351             }\r
1352         }\r
1353 \r
1354         return generatedTypes;\r
1355     }\r
1356 \r
1357     /**\r
1358      * Converts <code>leaf</code> to the getter method which is added to\r
1359      * <code>typeBuilder</code>.\r
1360      *\r
1361      * @param typeBuilder\r
1362      *            generated type builder to which is added getter method as\r
1363      *            <code>leaf</code> mapping\r
1364      * @param leaf\r
1365      *            leaf schema node which is mapped as getter method which is\r
1366      *            added to <code>typeBuilder</code>\r
1367      * @return boolean value\r
1368      *         <ul>\r
1369      *         <li>false - if <code>leaf</code> or <code>typeBuilder</code> are\r
1370      *         null</li>\r
1371      *         <li>true - in other cases</li>\r
1372      *         </ul>\r
1373      */\r
1374     private boolean resolveLeafSchemaNodeAsMethod(final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf) {\r
1375         if ((leaf != null) && (typeBuilder != null)) {\r
1376             final String leafName = leaf.getQName().getLocalName();\r
1377             String leafDesc = leaf.getDescription();\r
1378             if (leafDesc == null) {\r
1379                 leafDesc = "";\r
1380             }\r
1381 \r
1382             final Module parentModule = findParentModule(schemaContext, leaf);\r
1383             if (leafName != null && !leaf.isAddedByUses()) {\r
1384                 final TypeDefinition<?> typeDef = leaf.getType();\r
1385 \r
1386                 Type returnType = null;\r
1387                 if (typeDef instanceof EnumTypeDefinition) {\r
1388                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);\r
1389                     final EnumTypeDefinition enumTypeDef = enumTypeDefFromExtendedType(typeDef);\r
1390                     final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leafName,\r
1391                             typeBuilder);\r
1392 \r
1393                     if (enumBuilder != null) {\r
1394                         returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName());\r
1395                     }\r
1396                     ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);\r
1397                 } else if (typeDef instanceof UnionType) {\r
1398                     GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leafName, leaf, parentModule);\r
1399                     if (genTOBuilder != null) {\r
1400                         returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());\r
1401                     }\r
1402                 } else if (typeDef instanceof BitsTypeDefinition) {\r
1403                     GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leafName, leaf, parentModule);\r
1404                     if (genTOBuilder != null) {\r
1405                         returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());\r
1406                     }\r
1407                 } else {\r
1408                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);\r
1409                 }\r
1410                 if (returnType != null) {\r
1411                     constructGetter(typeBuilder, leafName, leafDesc, returnType);\r
1412                     return true;\r
1413                 }\r
1414             }\r
1415         }\r
1416         return false;\r
1417     }\r
1418 \r
1419     /**\r
1420      * Converts <code>leaf</code> schema node to property of generated TO\r
1421      * builder.\r
1422      *\r
1423      * @param toBuilder\r
1424      *            generated TO builder to which is <code>leaf</code> added as\r
1425      *            property\r
1426      * @param leaf\r
1427      *            leaf schema node which is added to <code>toBuilder</code> as\r
1428      *            property\r
1429      * @param isReadOnly\r
1430      *            boolean value which says if leaf property is|isn't read only\r
1431      * @return boolean value\r
1432      *         <ul>\r
1433      *         <li>false - if <code>leaf</code>, <code>toBuilder</code> or leaf\r
1434      *         name equals null or if leaf is added by <i>uses</i>.</li>\r
1435      *         <li>true - other cases</li>\r
1436      *         </ul>\r
1437      */\r
1438     private boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf,\r
1439             boolean isReadOnly) {\r
1440         if ((leaf != null) && (toBuilder != null)) {\r
1441             final String leafName = leaf.getQName().getLocalName();\r
1442             String leafDesc = leaf.getDescription();\r
1443             if (leafDesc == null) {\r
1444                 leafDesc = "";\r
1445             }\r
1446 \r
1447             if (leafName != null && !leaf.isAddedByUses()) {\r
1448                 final TypeDefinition<?> typeDef = leaf.getType();\r
1449 \r
1450                 // TODO: properly resolve enum types\r
1451                 final Type returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);\r
1452 \r
1453                 if (returnType != null) {\r
1454                     final GeneratedPropertyBuilder propBuilder = toBuilder.addProperty(parseToClassName(leafName));\r
1455 \r
1456                     propBuilder.setReadOnly(isReadOnly);\r
1457                     propBuilder.setReturnType(returnType);\r
1458                     propBuilder.setComment(leafDesc);\r
1459 \r
1460                     toBuilder.addEqualsIdentity(propBuilder);\r
1461                     toBuilder.addHashIdentity(propBuilder);\r
1462                     toBuilder.addToStringProperty(propBuilder);\r
1463 \r
1464                     return true;\r
1465                 }\r
1466             }\r
1467         }\r
1468         return false;\r
1469     }\r
1470 \r
1471     /**\r
1472      * Converts <code>node</code> leaf list schema node to getter method of\r
1473      * <code>typeBuilder</code>.\r
1474      *\r
1475      * @param typeBuilder\r
1476      *            generated type builder to which is <code>node</code> added as\r
1477      *            getter method\r
1478      * @param node\r
1479      *            leaf list schema node which is added to\r
1480      *            <code>typeBuilder</code> as getter method\r
1481      * @return boolean value\r
1482      *         <ul>\r
1483      *         <li>true - if <code>node</code>, <code>typeBuilder</code>,\r
1484      *         nodeName equal null or <code>node</code> is added by <i>uses</i></li>\r
1485      *         <li>false - other cases</li>\r
1486      *         </ul>\r
1487      */\r
1488     private boolean resolveLeafListSchemaNode(final GeneratedTypeBuilder typeBuilder, final LeafListSchemaNode node) {\r
1489         if ((node != null) && (typeBuilder != null)) {\r
1490             final String nodeName = node.getQName().getLocalName();\r
1491             String nodeDesc = node.getDescription();\r
1492             if (nodeDesc == null) {\r
1493                 nodeDesc = "";\r
1494             }\r
1495 \r
1496             if (nodeName != null && !node.isAddedByUses()) {\r
1497                 final TypeDefinition<?> type = node.getType();\r
1498                 final Type listType = Types.listTypeFor(typeProvider.javaTypeForSchemaDefinitionType(type, node));\r
1499 \r
1500                 constructGetter(typeBuilder, nodeName, nodeDesc, listType);\r
1501                 return true;\r
1502             }\r
1503         }\r
1504         return false;\r
1505     }\r
1506 \r
1507     /**\r
1508      * Creates a getter method for a container node.\r
1509      *\r
1510      * Firstly generated type builder for container is created or found in\r
1511      * {@link BindingGeneratorImpl#allGroupings allGroupings}. The package name\r
1512      * in the builder is created as concatenation of module package name and\r
1513      * names of all parent nodes. In the end the getter method for container is\r
1514      * added to <code>typeBuilder</code> and return type is set to container\r
1515      * type builder.\r
1516      *\r
1517      * @param basePackageName\r
1518      *            string with the module package name\r
1519      * @param typeBuilder\r
1520      *            generated type builder to which is <code>containerNode</code>\r
1521      *            added as getter method\r
1522      * @param containerNode\r
1523      *            container schema node which is mapped as getter method to\r
1524      *            <code>typeBuilder</code>\r
1525      * @return boolean value\r
1526      *         <ul>\r
1527      *         <li>false - if <code>containerNode</code>,\r
1528      *         <code>typeBuilder</code>, container node name equal null or\r
1529      *         <code>containerNode</code> is added by uses</li>\r
1530      *         <li>true - other cases</li>\r
1531      *         </ul>\r
1532      */\r
1533     private boolean resolveContainerSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder,\r
1534             final ContainerSchemaNode containerNode) {\r
1535         if ((containerNode != null) && (typeBuilder != null)) {\r
1536             final String nodeName = containerNode.getQName().getLocalName();\r
1537 \r
1538             if (nodeName != null && !containerNode.isAddedByUses()) {\r
1539                 final String packageName = packageNameForGeneratedType(basePackageName, containerNode.getPath());\r
1540 \r
1541                 final GeneratedTypeBuilder rawGenType = addDefaultInterfaceDefinition(packageName, containerNode);\r
1542                 constructGetter(typeBuilder, nodeName, containerNode.getDescription(), rawGenType);\r
1543 \r
1544                 return true;\r
1545             }\r
1546         }\r
1547         return false;\r
1548     }\r
1549 \r
1550     /**\r
1551      * Creates a getter method for a list node.\r
1552      *\r
1553      * Firstly generated type builder for list is created or found in\r
1554      * {@link BindingGeneratorImpl#allGroupings allGroupings}. The package name\r
1555      * in the builder is created as concatenation of module package name and\r
1556      * names of all parent nodes. In the end the getter method for list is added\r
1557      * to <code>typeBuilder</code> and return type is set to list type builder.\r
1558      *\r
1559      * @param basePackageName\r
1560      *            string with the module package name\r
1561      * @param typeBuilder\r
1562      *            generated type builder to which is <code></code> added as\r
1563      *            getter method\r
1564      * @param listNode\r
1565      *            list schema node which is mapped as getter method to\r
1566      *            <code>typeBuilder</code>\r
1567      * @return boolean value\r
1568      *         <ul>\r
1569      *         <li>false - if <code>listNode</code>, <code>typeBuilder</code>,\r
1570      *         list node name equal null or <code>listNode</code> is added by\r
1571      *         uses</li>\r
1572      *         <li>true - other cases</li>\r
1573      *         </ul>\r
1574      */\r
1575     private boolean resolveListSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder,\r
1576             final ListSchemaNode listNode) {\r
1577         if ((listNode != null) && (typeBuilder != null)) {\r
1578             final String listName = listNode.getQName().getLocalName();\r
1579 \r
1580             if (listName != null && !listNode.isAddedByUses()) {\r
1581                 final String packageName = packageNameForGeneratedType(basePackageName, listNode.getPath());\r
1582                 final GeneratedTypeBuilder rawGenType = addDefaultInterfaceDefinition(packageName, listNode);\r
1583                 constructGetter(typeBuilder, listName, listNode.getDescription(), Types.listTypeFor(rawGenType));\r
1584                 return true;\r
1585             }\r
1586         }\r
1587         return false;\r
1588     }\r
1589 \r
1590     /**\r
1591      * Instantiates generated type builder with <code>packageName</code> and\r
1592      * <code>schemaNode</code>.\r
1593      *\r
1594      * The new builder always implements\r
1595      * {@link org.opendaylight.yangtools.yang.binding.DataObject DataObject}.<br />\r
1596      * If <code>schemaNode</code> is instance of GroupingDefinition it also\r
1597      * implements {@link org.opendaylight.yangtools.yang.binding.Augmentable\r
1598      * Augmentable}.<br />\r
1599      * If <code>schemaNode</code> is instance of\r
1600      * {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer\r
1601      * DataNodeContainer} it can also implement nodes which are specified in\r
1602      * <i>uses</i>.\r
1603      *\r
1604      * @param packageName\r
1605      *            string with the name of the package to which\r
1606      *            <code>schemaNode</code> belongs.\r
1607      * @param schemaNode\r
1608      *            schema node for which is created generated type builder\r
1609      * @return generated type builder <code>schemaNode</code>\r
1610      */\r
1611     private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode) {\r
1612         final GeneratedTypeBuilder builder = addRawInterfaceDefinition(packageName, schemaNode, "");\r
1613         builder.addImplementsType(DATA_OBJECT);\r
1614         if (!(schemaNode instanceof GroupingDefinition)) {\r
1615             builder.addImplementsType(augmentable(builder));\r
1616         }\r
1617 \r
1618         if (schemaNode instanceof DataNodeContainer) {\r
1619             addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, builder);\r
1620         }\r
1621 \r
1622         return builder;\r
1623     }\r
1624 \r
1625     /**\r
1626      * Wraps the calling of the same overloaded method.\r
1627      *\r
1628      * @param packageName\r
1629      *            string with the package name to which returning generated type\r
1630      *            builder belongs\r
1631      * @param schemaNode\r
1632      *            schema node which provide data about the schema node name\r
1633      * @return generated type builder for <code>schemaNode</code>\r
1634      */\r
1635     private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode) {\r
1636         return addRawInterfaceDefinition(packageName, schemaNode, "");\r
1637     }\r
1638 \r
1639     /**\r
1640      * Returns reference to generated type builder for specified\r
1641      * <code>schemaNode</code> with <code>packageName</code>.\r
1642      *\r
1643      * Firstly the generated type builder is searched in\r
1644      * {@link BindingGeneratorImpl#genTypeBuilders genTypeBuilders}. If it isn't\r
1645      * found it is created and added to <code>genTypeBuilders</code>.\r
1646      *\r
1647      * @param packageName\r
1648      *            string with the package name to which returning generated type\r
1649      *            builder belongs\r
1650      * @param schemaNode\r
1651      *            schema node which provide data about the schema node name\r
1652      * @return generated type builder for <code>schemaNode</code>\r
1653      * @throws IllegalArgumentException\r
1654      *             <ul>\r
1655      *             <li>if <code>schemaNode</code> equals null</li>\r
1656      *             <li>if <code>packageName</code> equals null</li>\r
1657      *             <li>if Q name of schema node is null</li>\r
1658      *             <li>if schema node name is nul</li>\r
1659      *             </ul>\r
1660      *\r
1661      */\r
1662     private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode,\r
1663             final String prefix) {\r
1664         Preconditions.checkArgument(schemaNode != null,"Data Schema Node cannot be NULL.");\r
1665         Preconditions.checkArgument(packageName != null,"Package Name for Generated Type cannot be NULL.");\r
1666         Preconditions.checkArgument(schemaNode.getQName() != null,"QName for Data Schema Node cannot be NULL.");\r
1667         final String schemaNodeName = schemaNode.getQName().getLocalName();\r
1668         Preconditions.checkArgument(schemaNodeName != null,"Local Name of QName for Data Schema Node cannot be NULL.");\r
1669 \r
1670         final String genTypeName;\r
1671         if (prefix == null) {\r
1672             genTypeName = parseToClassName(schemaNodeName);\r
1673         } else {\r
1674             genTypeName = prefix + parseToClassName(schemaNodeName);\r
1675         }\r
1676 \r
1677         final GeneratedTypeBuilder newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);\r
1678         if (!genTypeBuilders.containsKey(packageName)) {\r
1679             final Map<String, GeneratedTypeBuilder> builders = new HashMap<>();\r
1680             builders.put(genTypeName, newType);\r
1681             genTypeBuilders.put(packageName, builders);\r
1682         } else {\r
1683             final Map<String, GeneratedTypeBuilder> builders = genTypeBuilders.get(packageName);\r
1684             if (!builders.containsKey(genTypeName)) {\r
1685                 builders.put(genTypeName, newType);\r
1686             }\r
1687         }\r
1688         return newType;\r
1689     }\r
1690 \r
1691     /**\r
1692      * Creates the name of the getter method from <code>methodName</code>.\r
1693      *\r
1694      * @param methodName\r
1695      *            string with the name of the getter method\r
1696      * @return string with the name of the getter method for\r
1697      *         <code>methodName</code> in JAVA method format\r
1698      */\r
1699     private String getterMethodName(final String methodName,Type returnType) {\r
1700         final StringBuilder method = new StringBuilder();\r
1701         if(BOOLEAN.equals(returnType)) {\r
1702             method.append("is");\r
1703         } else {\r
1704             method.append("get");\r
1705         }\r
1706         method.append(parseToClassName(methodName));\r
1707         return method.toString();\r
1708     }\r
1709 \r
1710     /**\r
1711      * Creates the name of the setter method from <code>methodName</code>.\r
1712      *\r
1713      * @param methodName\r
1714      *            string with the name of the setter method\r
1715      * @return string with the name of the setter method for\r
1716      *         <code>methodName</code> in JAVA method format\r
1717      */\r
1718     private String setterMethodName(final String methodName) {\r
1719         final StringBuilder method = new StringBuilder();\r
1720         method.append("set");\r
1721         method.append(parseToClassName(methodName));\r
1722         return method.toString();\r
1723     }\r
1724 \r
1725     /**\r
1726      * Created a method signature builder as part of\r
1727      * <code>interfaceBuilder</code>.\r
1728      *\r
1729      * The method signature builder is created for the getter method of\r
1730      * <code>schemaNodeName</code>. Also <code>comment</code> and\r
1731      * <code>returnType</code> information are added to the builder.\r
1732      *\r
1733      * @param interfaceBuilder\r
1734      *            generated type builder for which the getter method should be\r
1735      *            created\r
1736      * @param schemaNodeName\r
1737      *            string with schema node name. The name will be the part of the\r
1738      *            getter method name.\r
1739      * @param comment\r
1740      *            string with comment for the getter method\r
1741      * @param returnType\r
1742      *            type which represents the return type of the getter method\r
1743      * @return method signature builder which represents the getter method of\r
1744      *         <code>interfaceBuilder</code>\r
1745      */\r
1746     private MethodSignatureBuilder constructGetter(final GeneratedTypeBuilder interfaceBuilder,\r
1747             final String schemaNodeName, final String comment, final Type returnType) {\r
1748 \r
1749         final MethodSignatureBuilder getMethod = interfaceBuilder.addMethod(getterMethodName(schemaNodeName,returnType));\r
1750 \r
1751         getMethod.setComment(comment);\r
1752         getMethod.setReturnType(returnType);\r
1753 \r
1754         return getMethod;\r
1755     }\r
1756 \r
1757     private List<Type> listToGenType(final String basePackageName, final ListSchemaNode list) {\r
1758         Preconditions.checkArgument(basePackageName != null,"Package Name for Generated Type cannot be NULL.");\r
1759         Preconditions.checkArgument(list != null,"List Schema Node cannot be NULL.");\r
1760 \r
1761         final String packageName = packageNameForGeneratedType(basePackageName, list.getPath());\r
1762         // final GeneratedTypeBuilder typeBuilder =\r
1763         // resolveListTypeBuilder(packageName, list);\r
1764         final GeneratedTypeBuilder typeBuilder = addDefaultInterfaceDefinition(packageName, list);\r
1765 \r
1766         final List<String> listKeys = listKeys(list);\r
1767         GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(packageName, list);\r
1768 \r
1769         if (genTOBuilder != null) {\r
1770             ParameterizedType identifierMarker = Types.parameterizedTypeFor(Types.typeForClass(Identifier.class),\r
1771                     typeBuilder);\r
1772             ParameterizedType identifiableMarker = Types.parameterizedTypeFor(Types.typeForClass(Identifiable.class),\r
1773                     genTOBuilder);\r
1774             genTOBuilder.addImplementsType(identifierMarker);\r
1775             typeBuilder.addImplementsType(identifiableMarker);\r
1776         }\r
1777         final Set<DataSchemaNode> schemaNodes = list.getChildNodes();\r
1778 \r
1779         for (final DataSchemaNode schemaNode : schemaNodes) {\r
1780             if (schemaNode.isAugmenting()) {\r
1781                 continue;\r
1782             }\r
1783             addSchemaNodeToListBuilders(basePackageName, schemaNode, typeBuilder, genTOBuilder, listKeys);\r
1784         }\r
1785         return typeBuildersToGenTypes(typeBuilder, genTOBuilder);\r
1786     }\r
1787 \r
1788     /**\r
1789      * Adds <code>schemaNode</code> to <code>typeBuilder</code> as getter method\r
1790      * or to <code>genTOBuilder</code> as property.\r
1791      *\r
1792      * @param basePackageName\r
1793      *            string contains the module package name\r
1794      * @param schemaNode\r
1795      *            data schema node which should be added as getter method to\r
1796      *            <code>typeBuilder</code> or as a property to\r
1797      *            <code>genTOBuilder</code> if is part of the list key\r
1798      * @param typeBuilder\r
1799      *            generated type builder for the list schema node\r
1800      * @param genTOBuilder\r
1801      *            generated TO builder for the list keys\r
1802      * @param listKeys\r
1803      *            list of string which contains names of the list keys\r
1804      * @throws IllegalArgumentException\r
1805      *             <ul>\r
1806      *             <li>if <code>schemaNode</code> equals null</li>\r
1807      *             <li>if <code>typeBuilder</code> equals null</li>\r
1808      *             </ul>\r
1809      */\r
1810     private void addSchemaNodeToListBuilders(final String basePackageName, final DataSchemaNode schemaNode,\r
1811             final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final List<String> listKeys) {\r
1812         Preconditions.checkArgument(schemaNode != null,"Data Schema Node cannot be NULL.");\r
1813 \r
1814         Preconditions.checkArgument(typeBuilder != null,"Generated Type Builder cannot be NULL.");\r
1815 \r
1816         if (schemaNode instanceof LeafSchemaNode) {\r
1817             final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode;\r
1818             final String leafName = leaf.getQName().getLocalName();\r
1819             if (!listKeys.contains(leafName)) {\r
1820                 resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);\r
1821             } else {\r
1822                 resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true);\r
1823             }\r
1824         } else if (schemaNode instanceof LeafListSchemaNode) {\r
1825             resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode);\r
1826         } else if (schemaNode instanceof ContainerSchemaNode) {\r
1827             resolveContainerSchemaNode(basePackageName, typeBuilder, (ContainerSchemaNode) schemaNode);\r
1828         } else if (schemaNode instanceof ListSchemaNode) {\r
1829             resolveListSchemaNode(basePackageName, typeBuilder, (ListSchemaNode) schemaNode);\r
1830         }\r
1831     }\r
1832 \r
1833     private List<Type> typeBuildersToGenTypes(final GeneratedTypeBuilder typeBuilder, GeneratedTOBuilder genTOBuilder) {\r
1834         final List<Type> genTypes = new ArrayList<>();\r
1835         Preconditions.checkArgument(typeBuilder != null,"Generated Type Builder cannot be NULL.");\r
1836 \r
1837         if (genTOBuilder != null) {\r
1838             final GeneratedTransferObject genTO = genTOBuilder.toInstance();\r
1839             constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO);\r
1840             genTypes.add(genTO);\r
1841         }\r
1842         genTypes.add(typeBuilder.toInstance());\r
1843         return genTypes;\r
1844     }\r
1845 \r
1846     /**\r
1847      * Selects the names of the list keys from <code>list</code> and returns\r
1848      * them as the list of the strings\r
1849      *\r
1850      * @param list\r
1851      *            of string with names of the list keys\r
1852      * @return list of string which represents names of the list keys. If the\r
1853      *         <code>list</code> contains no keys then the empty list is\r
1854      *         returned.\r
1855      */\r
1856     private List<String> listKeys(final ListSchemaNode list) {\r
1857         final List<String> listKeys = new ArrayList<>();\r
1858 \r
1859         if (list.getKeyDefinition() != null) {\r
1860             final List<QName> keyDefinitions = list.getKeyDefinition();\r
1861 \r
1862             for (final QName keyDefinition : keyDefinitions) {\r
1863                 listKeys.add(keyDefinition.getLocalName());\r
1864             }\r
1865         }\r
1866         return listKeys;\r
1867     }\r
1868 \r
1869     /**\r
1870      * Generates for the <code>list</code> which contains any list keys special\r
1871      * generated TO builder.\r
1872      *\r
1873      * @param packageName\r
1874      *            string with package name to which the list belongs\r
1875      * @param list\r
1876      *            list schema node which is source of data about the list name\r
1877      * @return generated TO builder which represents the keys of the\r
1878      *         <code>list</code> or null if <code>list</code> is null or list of\r
1879      *         key definitions is null or empty.\r
1880      */\r
1881     private GeneratedTOBuilder resolveListKeyTOBuilder(final String packageName, final ListSchemaNode list) {\r
1882         GeneratedTOBuilder genTOBuilder = null;\r
1883         if ((list.getKeyDefinition() != null) && (!list.getKeyDefinition().isEmpty())) {\r
1884             if (list != null) {\r
1885                 final String listName = list.getQName().getLocalName() + "Key";\r
1886                 genTOBuilder = schemaNodeToTransferObjectBuilder(packageName, listName);\r
1887             }\r
1888         }\r
1889         return genTOBuilder;\r
1890 \r
1891     }\r
1892 \r
1893     /**\r
1894      * Builds generated TO builders for <code>typeDef</code> of type\r
1895      * {@link org.opendaylight.yangtools.yang.model.util.UnionType UnionType} or\r
1896      * {@link org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition\r
1897      * BitsTypeDefinition} which are also added to <code>typeBuilder</code> as\r
1898      * enclosing transfer object.\r
1899      *\r
1900      * If more then one generated TO builder is created for enclosing then all\r
1901      * of the generated TO builders are added to <code>typeBuilder</code> as\r
1902      * enclosing transfer objects.\r
1903      *\r
1904      * @param typeDef\r
1905      *            type definition which can be of type <code>UnionType</code> or\r
1906      *            <code>BitsTypeDefinition</code>\r
1907      * @param typeBuilder\r
1908      *            generated type builder to which is added generated TO created\r
1909      *            from <code>typeDef</code>\r
1910      * @param leafName\r
1911      *            string with name for generated TO builder\r
1912      * @return generated TO builder for <code>typeDef</code>\r
1913      */\r
1914     private GeneratedTOBuilder addTOToTypeBuilder(TypeDefinition<?> typeDef, GeneratedTypeBuilder typeBuilder,\r
1915             String leafName, LeafSchemaNode leaf, Module parentModule) {\r
1916         final String classNameFromLeaf = parseToClassName(leafName);\r
1917         List<GeneratedTOBuilder> genTOBuilders = new ArrayList<>();\r
1918         final String packageName = typeBuilder.getFullyQualifiedName();\r
1919         if (typeDef instanceof UnionTypeDefinition) {\r
1920             genTOBuilders.addAll(((TypeProviderImpl) typeProvider).provideGeneratedTOBuildersForUnionTypeDef(\r
1921                     packageName, typeDef, classNameFromLeaf, leaf));\r
1922         } else if (typeDef instanceof BitsTypeDefinition) {\r
1923             genTOBuilders.add(((TypeProviderImpl) typeProvider).provideGeneratedTOBuilderForBitsTypeDefinition(\r
1924                     packageName, typeDef, classNameFromLeaf));\r
1925         }\r
1926         if (genTOBuilders != null && !genTOBuilders.isEmpty()) {\r
1927             for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {\r
1928                 typeBuilder.addEnclosingTransferObject(genTOBuilder);\r
1929             }\r
1930             return genTOBuilders.get(0);\r
1931         }\r
1932         return null;\r
1933 \r
1934     }\r
1935 \r
1936     /**\r
1937      * Adds the implemented types to type builder.\r
1938      *\r
1939      * The method passes through the list of <i>uses</i> in\r
1940      * {@code dataNodeContainer}. For every <i>use</i> is obtained coresponding\r
1941      * generated type from {@link BindingGeneratorImpl#allGroupings\r
1942      * allGroupings} which is adde as <i>implements type</i> to\r
1943      * <code>builder</code>\r
1944      *\r
1945      * @param dataNodeContainer\r
1946      *            element which contains the list of used YANG groupings\r
1947      * @param builder\r
1948      *            builder to which are added implemented types according to\r
1949      *            <code>dataNodeContainer</code>\r
1950      * @return generated type builder with all implemented types\r
1951      */\r
1952     private GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer,\r
1953             final GeneratedTypeBuilder builder) {\r
1954         for (UsesNode usesNode : dataNodeContainer.getUses()) {\r
1955             if (usesNode.getGroupingPath() != null) {\r
1956                 GeneratedType genType = allGroupings.get(usesNode.getGroupingPath());\r
1957                 if (genType == null) {\r
1958                     throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for "\r
1959                             + builder.getName());\r
1960                 }\r
1961                 builder.addImplementsType(genType);\r
1962             }\r
1963         }\r
1964         return builder;\r
1965     }\r
1966 \r
1967 }\r