Fixing sonar issues 2
[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.ExtendedType;
57 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
58 import org.opendaylight.yangtools.yang.model.util.UnionType;
59 import static com.google.common.base.Preconditions.*;
60 import static extension org.opendaylight.yangtools.binding.generator.util.Types.*;
61 import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.*;
62 import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.*;
63 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.*;
64 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort
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 = enumTypeDefFromExtendedType(typeDef);
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, 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 }