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