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