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