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