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