6700b470faee489b0789dfde840b4a1e65c47448
[controller.git] / opendaylight / sal / yang-prototype / code-generator / binding-generator-impl / src / main / java / org / opendaylight / controller / 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.controller.sal.binding.generator.impl;
9
10 import static org.opendaylight.controller.binding.generator.util.BindingGeneratorUtil.*;
11 import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.findDataSchemaNode;
12 import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.findParentModule;
13
14 import java.util.concurrent.Future;
15
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.Comparator;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23
24 import org.opendaylight.controller.binding.generator.util.ReferencedTypeImpl;
25 import org.opendaylight.controller.binding.generator.util.Types;
26 import org.opendaylight.controller.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
27 import org.opendaylight.controller.binding.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
28 import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator;
29 import org.opendaylight.controller.sal.binding.generator.spi.TypeProvider;
30 import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
31 import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
32 import org.opendaylight.controller.sal.binding.model.api.Type;
33 import org.opendaylight.controller.sal.binding.model.api.type.builder.EnumBuilder;
34 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
35 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTOBuilder;
36 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
37 import org.opendaylight.controller.sal.binding.model.api.type.builder.MethodSignatureBuilder;
38 import org.opendaylight.controller.sal.binding.yang.types.TypeProviderImpl;
39 import org.opendaylight.controller.yang.binding.Notification;
40 import org.opendaylight.controller.yang.common.QName;
41 import org.opendaylight.controller.yang.common.RpcResult;
42 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
43 import org.opendaylight.controller.yang.model.api.ChoiceCaseNode;
44 import org.opendaylight.controller.yang.model.api.ChoiceNode;
45 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
46 import org.opendaylight.controller.yang.model.api.DataNodeContainer;
47 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
48 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
49 import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
50 import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
51 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
52 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
53 import org.opendaylight.controller.yang.model.api.Module;
54 import org.opendaylight.controller.yang.model.api.NotificationDefinition;
55 import org.opendaylight.controller.yang.model.api.RpcDefinition;
56 import org.opendaylight.controller.yang.model.api.SchemaContext;
57 import org.opendaylight.controller.yang.model.api.SchemaNode;
58 import org.opendaylight.controller.yang.model.api.SchemaPath;
59 import org.opendaylight.controller.yang.model.api.TypeDefinition;
60 import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition;
61 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition;
62 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair;
63 import org.opendaylight.controller.yang.model.util.DataNodeIterator;
64 import org.opendaylight.controller.yang.model.util.ExtendedType;
65 import org.opendaylight.controller.yang.model.util.SchemaContextUtil;
66 import org.opendaylight.controller.yang.model.util.UnionType;
67
68 public final class BindingGeneratorImpl implements BindingGenerator {
69
70     private Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders;
71     private TypeProvider typeProvider;
72     private SchemaContext schemaContext;
73
74     public BindingGeneratorImpl() {
75         super();
76     }
77
78     @Override
79     public List<Type> generateTypes(final SchemaContext context) {
80         if (context == null) {
81             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
82         }
83         if (context.getModules() == null) {
84             throw new IllegalStateException("Schema Context does not contain defined modules!");
85         }
86
87         final List<Type> generatedTypes = new ArrayList<>();
88         schemaContext = context;
89         typeProvider = new TypeProviderImpl(context);
90         final Set<Module> modules = context.getModules();
91         genTypeBuilders = new HashMap<>();
92         for (final Module module : modules) {
93             generatedTypes.add(moduleToDataType(module));
94             generatedTypes.addAll(allTypeDefinitionsToGenTypes(module));
95             generatedTypes.addAll(allContainersToGenTypes(module));
96             generatedTypes.addAll(allListsToGenTypes(module));
97             generatedTypes.addAll(allChoicesToGenTypes(module));
98             generatedTypes.addAll(allAugmentsToGenTypes(module));
99             generatedTypes.addAll(allRPCMethodsToGenType(module));
100             generatedTypes.addAll(allNotificationsToGenType(module));
101             generatedTypes.addAll(allIdentitiesToGenTypes(module, context));
102             generatedTypes.addAll(allGroupingsToGenTypes(module));
103         }
104         return generatedTypes;
105     }
106
107     @Override
108     public List<Type> generateTypes(final SchemaContext context, final Set<Module> modules) {
109         if (context == null) {
110             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
111         }
112         if (context.getModules() == null) {
113             throw new IllegalStateException("Schema Context does not contain defined modules!");
114         }
115         if (modules == null) {
116             throw new IllegalArgumentException("Sef of Modules cannot be NULL!");
117         }
118
119         final List<Type> filteredGenTypes = new ArrayList<>();
120         schemaContext = context;
121         typeProvider = new TypeProviderImpl(context);
122         final Set<Module> contextModules = context.getModules();
123         genTypeBuilders = new HashMap<>();
124         for (final Module contextModule : contextModules) {
125             final List<Type> generatedTypes = new ArrayList<>();
126
127             generatedTypes.add(moduleToDataType(contextModule));
128             generatedTypes.addAll(allTypeDefinitionsToGenTypes(contextModule));
129             generatedTypes.addAll(allContainersToGenTypes(contextModule));
130             generatedTypes.addAll(allListsToGenTypes(contextModule));
131             generatedTypes.addAll(allChoicesToGenTypes(contextModule));
132             generatedTypes.addAll(allAugmentsToGenTypes(contextModule));
133             generatedTypes.addAll(allRPCMethodsToGenType(contextModule));
134             generatedTypes.addAll(allNotificationsToGenType(contextModule));
135             generatedTypes.addAll(allIdentitiesToGenTypes(contextModule, context));
136             generatedTypes.addAll(allGroupingsToGenTypes(contextModule));
137
138             if (modules.contains(contextModule)) {
139                 filteredGenTypes.addAll(generatedTypes);
140             }
141         }
142         return filteredGenTypes;
143     }
144
145     private List<Type> allTypeDefinitionsToGenTypes(final Module module) {
146         if (module == null) {
147             throw new IllegalArgumentException("Module reference cannot be NULL!");
148         }
149         if (module.getName() == null) {
150             throw new IllegalArgumentException("Module name cannot be NULL!");
151         }
152         if (module.getTypeDefinitions() == null) {
153             throw new IllegalArgumentException("Type Definitions for module " + module.getName() + " cannot be NULL!");
154         }
155
156         final Set<TypeDefinition<?>> typeDefinitions = module.getTypeDefinitions();
157         final List<Type> generatedTypes = new ArrayList<>();
158         for (final TypeDefinition<?> typedef : typeDefinitions) {
159             if (typedef != null) {
160                 final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef);
161                 if ((type != null) && !generatedTypes.contains(type)) {
162                     generatedTypes.add(type);
163                 }
164             }
165         }
166         return generatedTypes;
167     }
168
169     private List<Type> allContainersToGenTypes(final Module module) {
170         if (module == null) {
171             throw new IllegalArgumentException("Module reference cannot be NULL!");
172         }
173
174         if (module.getName() == null) {
175             throw new IllegalArgumentException("Module name cannot be NULL!");
176         }
177
178         if (module.getChildNodes() == null) {
179             throw new IllegalArgumentException("Reference to Set of Child Nodes in module " + module.getName()
180                     + " cannot be NULL!");
181         }
182
183         final List<Type> generatedTypes = new ArrayList<>();
184         final DataNodeIterator it = new DataNodeIterator(module);
185         final List<ContainerSchemaNode> schemaContainers = it.allContainers();
186         final String basePackageName = moduleNamespaceToPackageName(module);
187         for (final ContainerSchemaNode container : schemaContainers) {
188             generatedTypes.add(containerToGenType(basePackageName, container));
189         }
190         return generatedTypes;
191     }
192
193     private List<Type> allListsToGenTypes(final Module module) {
194         if (module == null) {
195             throw new IllegalArgumentException("Module reference cannot be NULL!");
196         }
197
198         if (module.getName() == null) {
199             throw new IllegalArgumentException("Module name cannot be NULL!");
200         }
201
202         if (module.getChildNodes() == null) {
203             throw new IllegalArgumentException("Reference to Set of Child Nodes in module " + module.getName()
204                     + " cannot be NULL!");
205         }
206
207         final List<Type> generatedTypes = new ArrayList<>();
208         final DataNodeIterator it = new DataNodeIterator(module);
209         final List<ListSchemaNode> schemaLists = it.allLists();
210         final String basePackageName = moduleNamespaceToPackageName(module);
211         if (schemaLists != null) {
212             for (final ListSchemaNode list : schemaLists) {
213                 generatedTypes.addAll(listToGenType(basePackageName, list));
214             }
215         }
216         return generatedTypes;
217     }
218
219     private List<GeneratedType> allChoicesToGenTypes(final Module module) {
220         if (module == null) {
221             throw new IllegalArgumentException("Module reference cannot be NULL!");
222         }
223         if (module.getName() == null) {
224             throw new IllegalArgumentException("Module name cannot be NULL!");
225         }
226
227         final DataNodeIterator it = new DataNodeIterator(module);
228         final List<ChoiceNode> choiceNodes = it.allChoices();
229         final String basePackageName = moduleNamespaceToPackageName(module);
230
231         final List<GeneratedType> generatedTypes = new ArrayList<>();
232         for (final ChoiceNode choice : choiceNodes) {
233             if (choice != null) {
234                 generatedTypes.addAll(choiceToGeneratedType(basePackageName, choice));
235             }
236         }
237         return generatedTypes;
238     }
239
240     private List<Type> allAugmentsToGenTypes(final Module module) {
241         if (module == null) {
242             throw new IllegalArgumentException("Module reference cannot be NULL!");
243         }
244         if (module.getName() == null) {
245             throw new IllegalArgumentException("Module name cannot be NULL!");
246         }
247         if (module.getChildNodes() == null) {
248             throw new IllegalArgumentException("Reference to Set of Augmentation Definitions in module "
249                     + module.getName() + " cannot be NULL!");
250         }
251
252         final List<Type> generatedTypes = new ArrayList<>();
253         final String basePackageName = moduleNamespaceToPackageName(module);
254         final List<AugmentationSchema> augmentations = resolveAugmentations(module);
255         for (final AugmentationSchema augment : augmentations) {
256             generatedTypes.addAll(augmentationToGenTypes(basePackageName, augment));
257         }
258         return generatedTypes;
259     }
260
261     private List<AugmentationSchema> resolveAugmentations(final Module module) {
262         if (module == null) {
263             throw new IllegalArgumentException("Module reference cannot be NULL!");
264         }
265         if (module.getAugmentations() == null) {
266             throw new IllegalStateException("Augmentations Set cannot be NULL!");
267         }
268
269         final Set<AugmentationSchema> augmentations = module.getAugmentations();
270         final List<AugmentationSchema> sortedAugmentations = new ArrayList<>(augmentations);
271         Collections.sort(sortedAugmentations, new Comparator<AugmentationSchema>() {
272
273             @Override
274             public int compare(AugmentationSchema augSchema1, AugmentationSchema augSchema2) {
275
276                 if (augSchema1.getTargetPath().getPath().size() > augSchema2.getTargetPath().getPath().size()) {
277                     return 1;
278                 } else if (augSchema1.getTargetPath().getPath().size() < augSchema2.getTargetPath().getPath().size()) {
279                     return -1;
280                 }
281                 return 0;
282
283             }
284         });
285
286         return sortedAugmentations;
287     }
288
289     private GeneratedType moduleToDataType(final Module module) {
290         if (module == null) {
291             throw new IllegalArgumentException("Module reference cannot be NULL!");
292         }
293
294         final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data");
295
296         final String basePackageName = moduleNamespaceToPackageName(module);
297         if (moduleDataTypeBuilder != null) {
298             final Set<DataSchemaNode> dataNodes = module.getChildNodes();
299             resolveDataSchemaNodes(basePackageName, moduleDataTypeBuilder, dataNodes);
300         }
301         return moduleDataTypeBuilder.toInstance();
302     }
303
304     private List<Type> allRPCMethodsToGenType(final Module module) {
305         if (module == null) {
306             throw new IllegalArgumentException("Module reference cannot be NULL!");
307         }
308
309         if (module.getName() == null) {
310             throw new IllegalArgumentException("Module name cannot be NULL!");
311         }
312
313         if (module.getChildNodes() == null) {
314             throw new IllegalArgumentException("Reference to Set of RPC Method Definitions in module "
315                     + module.getName() + " cannot be NULL!");
316         }
317
318         final String basePackageName = moduleNamespaceToPackageName(module);
319         final Set<RpcDefinition> rpcDefinitions = module.getRpcs();
320         final List<Type> genRPCTypes = new ArrayList<>();
321         final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, "Service");
322         final Type future = Types.typeForClass(Future.class);
323         for (final RpcDefinition rpc : rpcDefinitions) {
324             if (rpc != null) {
325
326                 String rpcName = parseToClassName(rpc.getQName().getLocalName());
327                 String rpcMethodName = parseToValidParamName(rpcName);
328                 MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName);
329
330                 final List<DataNodeIterator> rpcInOut = new ArrayList<>();
331
332                 ContainerSchemaNode input = rpc.getInput();
333                 ContainerSchemaNode output = rpc.getOutput();
334
335                 if (input != null) {
336                     rpcInOut.add(new DataNodeIterator(input));
337                     GeneratedTypeBuilder inType = addRawInterfaceDefinition(basePackageName, input, rpcName);
338                     resolveDataSchemaNodes(basePackageName, inType, input.getChildNodes());
339                     Type inTypeInstance = inType.toInstance();
340                     genRPCTypes.add(inTypeInstance);
341                     method.addParameter(inTypeInstance, "input");
342                 }
343
344                 Type outTypeInstance = Types.typeForClass(Void.class);
345                 if (output != null) {
346                     rpcInOut.add(new DataNodeIterator(output));
347
348                     GeneratedTypeBuilder outType = addRawInterfaceDefinition(basePackageName, output, rpcName);
349                     resolveDataSchemaNodes(basePackageName, outType, output.getChildNodes());
350                     outTypeInstance = outType.toInstance();
351                     genRPCTypes.add(outTypeInstance);
352
353                 }
354
355                 final Type rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult.class), outTypeInstance);
356                 method.setReturnType(Types.parameterizedTypeFor(future, rpcRes));
357                 for (DataNodeIterator it : rpcInOut) {
358                     List<ContainerSchemaNode> nContainers = it.allContainers();
359                     if ((nContainers != null) && !nContainers.isEmpty()) {
360                         for (final ContainerSchemaNode container : nContainers) {
361                             genRPCTypes.add(containerToGenType(basePackageName, container));
362                         }
363                     }
364                     List<ListSchemaNode> nLists = it.allLists();
365                     if ((nLists != null) && !nLists.isEmpty()) {
366                         for (final ListSchemaNode list : nLists) {
367                             genRPCTypes.addAll(listToGenType(basePackageName, list));
368                         }
369                     }
370                 }
371             }
372         }
373         genRPCTypes.add(interfaceBuilder.toInstance());
374         return genRPCTypes;
375     }
376
377     private List<Type> allNotificationsToGenType(final Module module) {
378         if (module == null) {
379             throw new IllegalArgumentException("Module reference cannot be NULL!");
380         }
381
382         if (module.getName() == null) {
383             throw new IllegalArgumentException("Module name cannot be NULL!");
384         }
385
386         if (module.getChildNodes() == null) {
387             throw new IllegalArgumentException("Reference to Set of Notification Definitions in module "
388                     + module.getName() + " cannot be NULL!");
389         }
390
391         final String basePackageName = moduleNamespaceToPackageName(module);
392         final List<Type> genNotifyTypes = new ArrayList<>();
393         final Set<NotificationDefinition> notifications = module.getNotifications();
394
395         for (final NotificationDefinition notification : notifications) {
396             if (notification != null) {
397                 DataNodeIterator it = new DataNodeIterator(notification);
398
399                 // Containers
400                 for (ContainerSchemaNode node : it.allContainers()) {
401                     genNotifyTypes.add(containerToGenType(basePackageName, node));
402                 }
403                 // Lists
404                 for (ListSchemaNode node : it.allLists()) {
405                     genNotifyTypes.addAll(listToGenType(basePackageName, node));
406                 }
407                 final GeneratedTypeBuilder notificationTypeBuilder = addDefaultInterfaceDefinition(basePackageName,
408                         notification);
409                 notificationTypeBuilder.addImplementsType(Types.typeForClass(Notification.class));
410                 // Notification object
411                 resolveDataSchemaNodes(basePackageName, notificationTypeBuilder, notification.getChildNodes());
412                 genNotifyTypes.add(notificationTypeBuilder.toInstance());
413             }
414         }
415         return genNotifyTypes;
416     }
417
418     private List<Type> allIdentitiesToGenTypes(final Module module, final SchemaContext context) {
419         List<Type> genTypes = new ArrayList<>();
420
421         final Set<IdentitySchemaNode> schemaIdentities = module.getIdentities();
422
423         final String basePackageName = moduleNamespaceToPackageName(module);
424
425         if (schemaIdentities != null && !schemaIdentities.isEmpty()) {
426             for (final IdentitySchemaNode identity : schemaIdentities) {
427                 genTypes.add(identityToGenType(basePackageName, identity, context));
428             }
429         }
430         return genTypes;
431     }
432
433     private GeneratedType identityToGenType(final String basePackageName, final IdentitySchemaNode identity,
434             final SchemaContext context) {
435         if (identity == null) {
436             return null;
437         }
438
439         final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath());
440         final String genTypeName = parseToClassName(identity.getQName().getLocalName());
441         final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTypeName);
442
443         IdentitySchemaNode baseIdentity = identity.getBaseIdentity();
444         if (baseIdentity != null) {
445             Module baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity);
446
447             final String returnTypePkgName = moduleNamespaceToPackageName(baseIdentityParentModule);
448             final String returnTypeName = parseToClassName(baseIdentity.getQName().getLocalName());
449
450             GeneratedTransferObject gto = new GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName).toInstance();
451             newType.setExtendsType(gto);
452         } else {
453             newType.setExtendsType(Types.getBaseIdentityTO());
454         }
455         newType.setAbstract(true);
456         return newType.toInstance();
457     }
458
459     private List<Type> allGroupingsToGenTypes(final Module module) {
460         final List<Type> genTypes = new ArrayList<>();
461         final String basePackageName = moduleNamespaceToPackageName(module);
462         final Set<GroupingDefinition> groupings = module.getGroupings();
463         if (groupings != null && !groupings.isEmpty()) {
464             for (final GroupingDefinition grouping : groupings) {
465                 genTypes.add(groupingToGenType(basePackageName, grouping));
466             }
467         }
468         return genTypes;
469     }
470
471     private GeneratedType groupingToGenType(final String basePackageName, GroupingDefinition grouping) {
472         if (grouping == null) {
473             return null;
474         }
475
476         final String packageName = packageNameForGeneratedType(basePackageName, grouping.getPath());
477         final Set<DataSchemaNode> schemaNodes = grouping.getChildNodes();
478         final GeneratedTypeBuilder typeBuilder = addDefaultInterfaceDefinition(packageName, grouping);
479
480         resolveDataSchemaNodes(basePackageName, typeBuilder, schemaNodes);
481         return typeBuilder.toInstance();
482     }
483
484     private EnumTypeDefinition enumTypeDefFromExtendedType(final TypeDefinition<?> typeDefinition) {
485         if (typeDefinition != null) {
486             if (typeDefinition.getBaseType() instanceof EnumTypeDefinition) {
487                 return (EnumTypeDefinition) typeDefinition.getBaseType();
488             } else if (typeDefinition.getBaseType() instanceof ExtendedType) {
489                 return enumTypeDefFromExtendedType(typeDefinition.getBaseType());
490             }
491         }
492         return null;
493     }
494
495     private EnumBuilder resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final String enumName,
496             final GeneratedTypeBuilder typeBuilder) {
497         if ((enumTypeDef != null) && (typeBuilder != null) && (enumTypeDef.getQName() != null)
498                 && (enumTypeDef.getQName().getLocalName() != null)) {
499
500             final String enumerationName = parseToClassName(enumName);
501             final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
502
503             if (enumBuilder != null) {
504                 final List<EnumPair> enums = enumTypeDef.getValues();
505                 if (enums != null) {
506                     int listIndex = 0;
507                     for (final EnumPair enumPair : enums) {
508                         if (enumPair != null) {
509                             final String enumPairName = parseToClassName(enumPair.getName());
510                             Integer enumPairValue = enumPair.getValue();
511
512                             if (enumPairValue == null) {
513                                 enumPairValue = listIndex;
514                             }
515                             enumBuilder.addValue(enumPairName, enumPairValue);
516                             listIndex++;
517                         }
518                     }
519                 }
520                 return enumBuilder;
521             }
522         }
523         return null;
524     }
525
526     private GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix) {
527         if (module == null) {
528             throw new IllegalArgumentException("Module reference cannot be NULL!");
529         }
530         String packageName = moduleNamespaceToPackageName(module);
531         final String moduleName = parseToClassName(module.getName()) + postfix;
532
533         return new GeneratedTypeBuilderImpl(packageName, moduleName);
534
535     }
536
537     private List<Type> augmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema) {
538         if (augmentPackageName == null) {
539             throw new IllegalArgumentException("Package Name cannot be NULL!");
540         }
541         if (augSchema == null) {
542             throw new IllegalArgumentException("Augmentation Schema cannot be NULL!");
543         }
544         if (augSchema.getTargetPath() == null) {
545             throw new IllegalStateException("Augmentation Schema does not contain Target Path (Target Path is NULL).");
546         }
547
548         final List<Type> genTypes = new ArrayList<>();
549
550         // EVERY augmented interface will extends Augmentation<T> interface
551         // and DataObject interface!!!
552         final SchemaPath targetPath = augSchema.getTargetPath();
553         final DataSchemaNode targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
554         if ((targetSchemaNode != null) && (targetSchemaNode.getQName() != null)
555                 && (targetSchemaNode.getQName().getLocalName() != null)) {
556             final Module targetModule = findParentModule(schemaContext, targetSchemaNode);
557             final String targetBasePackage = moduleNamespaceToPackageName(targetModule);
558             final String targetPackageName = packageNameForGeneratedType(targetBasePackage, targetSchemaNode.getPath());
559             final String targetSchemaNodeName = targetSchemaNode.getQName().getLocalName();
560             final Set<DataSchemaNode> augChildNodes = augSchema.getChildNodes();
561
562             if (!(targetSchemaNode instanceof ChoiceNode)) {
563                 final GeneratedTypeBuilder augTypeBuilder = addRawAugmentGenTypeDefinition(augmentPackageName,
564                         targetPackageName, targetSchemaNodeName, augSchema);
565                 final GeneratedType augType = augTypeBuilder.toInstance();
566                 genTypes.add(augType);
567             } else {
568                 final Type refChoiceType = new ReferencedTypeImpl(targetPackageName,
569                         parseToClassName(targetSchemaNodeName));
570                 final ChoiceNode choiceTarget = (ChoiceNode) targetSchemaNode;
571                 final Set<ChoiceCaseNode> choiceCaseNodes = choiceTarget.getCases();
572                 genTypes.addAll(augmentCasesToGenTypes(augmentPackageName, refChoiceType, choiceCaseNodes));
573             }
574             genTypes.addAll(augmentationBodyToGenTypes(augmentPackageName, augChildNodes));
575         }
576         return genTypes;
577     }
578
579     private List<GeneratedType> augmentCasesToGenTypes(final String augmentPackageName, final Type refChoiceType,
580             final Set<ChoiceCaseNode> choiceCaseNodes) {
581         if (augmentPackageName == null) {
582             throw new IllegalArgumentException("Augment Package Name string cannot be NULL!");
583         }
584         if (choiceCaseNodes == null) {
585             throw new IllegalArgumentException("Set of Choice Case Nodes cannot be NULL!");
586         }
587         final List<GeneratedType> genTypes = generateTypesFromAugmentedChoiceCases(augmentPackageName, refChoiceType,
588                 choiceCaseNodes);
589         return genTypes;
590     }
591
592     private GeneratedTypeBuilder addRawAugmentGenTypeDefinition(final String augmentPackageName,
593             final String targetPackageName, final String targetSchemaNodeName, final AugmentationSchema augSchema) {
594         final String targetTypeName = parseToClassName(targetSchemaNodeName);
595         Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);
596         if (augmentBuilders == null) {
597             augmentBuilders = new HashMap<>();
598             genTypeBuilders.put(augmentPackageName, augmentBuilders);
599         }
600
601         final String augTypeName = augGenTypeName(augmentBuilders, targetTypeName);
602         final Type targetTypeRef = new ReferencedTypeImpl(targetPackageName, targetTypeName);
603         final Set<DataSchemaNode> augChildNodes = augSchema.getChildNodes();
604
605         final GeneratedTypeBuilder augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName);
606
607         augTypeBuilder.addImplementsType(Types.DATA_OBJECT);
608         augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
609
610         augSchemaNodeToMethods(augmentPackageName, augTypeBuilder, augChildNodes);
611         augmentBuilders.put(augTypeName, augTypeBuilder);
612         return augTypeBuilder;
613     }
614
615     private List<Type> augmentationBodyToGenTypes(final String augBasePackageName,
616             final Set<DataSchemaNode> augChildNodes) {
617         final List<Type> genTypes = new ArrayList<>();
618         final List<DataNodeIterator> augSchemaIts = new ArrayList<>();
619         for (final DataSchemaNode childNode : augChildNodes) {
620             if (childNode instanceof DataNodeContainer) {
621                 augSchemaIts.add(new DataNodeIterator((DataNodeContainer) childNode));
622
623                 if (childNode instanceof ContainerSchemaNode) {
624                     genTypes.add(containerToGenType(augBasePackageName, (ContainerSchemaNode) childNode));
625                 } else if (childNode instanceof ListSchemaNode) {
626                     genTypes.addAll(listToGenType(augBasePackageName, (ListSchemaNode) childNode));
627                 }
628             } else if (childNode instanceof ChoiceNode) {
629                 final ChoiceNode choice = (ChoiceNode) childNode;
630                 for (final ChoiceCaseNode caseNode : choice.getCases()) {
631                     augSchemaIts.add(new DataNodeIterator(caseNode));
632                 }
633                 genTypes.addAll(choiceToGeneratedType(augBasePackageName, (ChoiceNode) childNode));
634             }
635         }
636
637         for (final DataNodeIterator it : augSchemaIts) {
638             final List<ContainerSchemaNode> augContainers = it.allContainers();
639             final List<ListSchemaNode> augLists = it.allLists();
640             final List<ChoiceNode> augChoices = it.allChoices();
641
642             if (augContainers != null) {
643                 for (final ContainerSchemaNode container : augContainers) {
644                     genTypes.add(containerToGenType(augBasePackageName, container));
645                 }
646             }
647             if (augLists != null) {
648                 for (final ListSchemaNode list : augLists) {
649                     genTypes.addAll(listToGenType(augBasePackageName, list));
650                 }
651             }
652             if (augChoices != null) {
653                 for (final ChoiceNode choice : augChoices) {
654                     genTypes.addAll(choiceToGeneratedType(augBasePackageName, choice));
655                 }
656             }
657         }
658         return genTypes;
659     }
660
661     private String augGenTypeName(final Map<String, GeneratedTypeBuilder> builders, final String genTypeName) {
662         String augTypeName = genTypeName;
663
664         int index = 1;
665         while ((builders != null) && builders.containsKey(genTypeName + index)) {
666             index++;
667         }
668         augTypeName += index;
669         return augTypeName;
670     }
671
672     private GeneratedType containerToGenType(final String basePackageName, ContainerSchemaNode containerNode) {
673         if (containerNode == null) {
674             return null;
675         }
676
677         final String packageName = packageNameForGeneratedType(basePackageName, containerNode.getPath());
678         final Set<DataSchemaNode> schemaNodes = containerNode.getChildNodes();
679         final GeneratedTypeBuilder typeBuilder = addDefaultInterfaceDefinition(packageName, containerNode);
680
681         resolveDataSchemaNodes(basePackageName, typeBuilder, schemaNodes);
682         return typeBuilder.toInstance();
683     }
684
685     private GeneratedTypeBuilder resolveDataSchemaNodes(final String basePackageName,
686             final GeneratedTypeBuilder typeBuilder, final Set<DataSchemaNode> schemaNodes) {
687         if ((schemaNodes != null) && (typeBuilder != null)) {
688             for (final DataSchemaNode schemaNode : schemaNodes) {
689                 if (schemaNode.isAugmenting()) {
690                     continue;
691                 }
692                 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder);
693             }
694         }
695         return typeBuilder;
696     }
697
698     private GeneratedTypeBuilder augSchemaNodeToMethods(final String basePackageName,
699             final GeneratedTypeBuilder typeBuilder, final Set<DataSchemaNode> schemaNodes) {
700         if ((schemaNodes != null) && (typeBuilder != null)) {
701             for (final DataSchemaNode schemaNode : schemaNodes) {
702                 if (schemaNode.isAugmenting()) {
703                     addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder);
704                 }
705             }
706         }
707         return typeBuilder;
708     }
709
710     private void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode schemaNode,
711             final GeneratedTypeBuilder typeBuilder) {
712         if (schemaNode != null && typeBuilder != null) {
713             if (schemaNode instanceof LeafSchemaNode) {
714                 resolveLeafSchemaNodeAsMethod(typeBuilder, (LeafSchemaNode) schemaNode);
715             } else if (schemaNode instanceof LeafListSchemaNode) {
716                 resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode);
717             } else if (schemaNode instanceof ContainerSchemaNode) {
718                 resolveContainerSchemaNode(basePackageName, typeBuilder, (ContainerSchemaNode) schemaNode);
719             } else if (schemaNode instanceof ListSchemaNode) {
720                 resolveListSchemaNode(basePackageName, typeBuilder, (ListSchemaNode) schemaNode);
721             } else if (schemaNode instanceof ChoiceNode) {
722                 resolveChoiceSchemaNode(basePackageName, typeBuilder, (ChoiceNode) schemaNode);
723             }
724         }
725     }
726
727     private void resolveChoiceSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder,
728             final ChoiceNode choiceNode) {
729         if (basePackageName == null) {
730             throw new IllegalArgumentException("Base Package Name cannot be NULL!");
731         }
732         if (typeBuilder == null) {
733             throw new IllegalArgumentException("Generated Type Builder cannot be NULL!");
734         }
735         if (choiceNode == null) {
736             throw new IllegalArgumentException("Choice Schema Node cannot be NULL!");
737         }
738
739         final String choiceName = choiceNode.getQName().getLocalName();
740         if (choiceName != null) {
741             final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath());
742             final GeneratedTypeBuilder choiceType = addDefaultInterfaceDefinition(packageName, choiceNode);
743             constructGetter(typeBuilder, choiceName, choiceNode.getDescription(), choiceType);
744         }
745     }
746
747     private List<GeneratedType> choiceToGeneratedType(final String basePackageName, final ChoiceNode choiceNode) {
748         if (basePackageName == null) {
749             throw new IllegalArgumentException("Base Package Name cannot be NULL!");
750         }
751         if (choiceNode == null) {
752             throw new IllegalArgumentException("Choice Schema Node cannot be NULL!");
753         }
754
755         final List<GeneratedType> generatedTypes = new ArrayList<>();
756         final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath());
757         final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode);
758         choiceTypeBuilder.addImplementsType(Types.DATA_OBJECT);
759         final GeneratedType choiceType = choiceTypeBuilder.toInstance();
760
761         generatedTypes.add(choiceType);
762         final Set<ChoiceCaseNode> caseNodes = choiceNode.getCases();
763         if ((caseNodes != null) && !caseNodes.isEmpty()) {
764             generatedTypes.addAll(generateTypesFromChoiceCases(basePackageName, choiceType, caseNodes));
765         }
766         return generatedTypes;
767     }
768
769     private List<GeneratedType> generateTypesFromChoiceCases(final String basePackageName, final Type refChoiceType,
770             final Set<ChoiceCaseNode> caseNodes) {
771         if (basePackageName == null) {
772             throw new IllegalArgumentException("Base Package Name cannot be NULL!");
773         }
774         if (refChoiceType == null) {
775             throw new IllegalArgumentException("Referenced Choice Type cannot be NULL!");
776         }
777         if (caseNodes == null) {
778             throw new IllegalArgumentException("Set of Choice Case Nodes cannot be NULL!");
779         }
780
781         final List<GeneratedType> generatedTypes = new ArrayList<>();
782         for (final ChoiceCaseNode caseNode : caseNodes) {
783             if (caseNode != null && !caseNode.isAddedByUses()) {
784                 final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
785                 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
786                 caseTypeBuilder.addImplementsType(refChoiceType);
787
788                 final Set<DataSchemaNode> childNodes = caseNode.getChildNodes();
789                 if (childNodes != null) {
790                     resolveDataSchemaNodes(basePackageName, caseTypeBuilder, childNodes);
791                 }
792                 generatedTypes.add(caseTypeBuilder.toInstance());
793             }
794         }
795
796         return generatedTypes;
797     }
798
799     private List<GeneratedType> generateTypesFromAugmentedChoiceCases(final String basePackageName,
800             final Type refChoiceType, final Set<ChoiceCaseNode> caseNodes) {
801         if (basePackageName == null) {
802             throw new IllegalArgumentException("Base Package Name cannot be NULL!");
803         }
804         if (refChoiceType == null) {
805             throw new IllegalArgumentException("Referenced Choice Type cannot be NULL!");
806         }
807         if (caseNodes == null) {
808             throw new IllegalArgumentException("Set of Choice Case Nodes cannot be NULL!");
809         }
810
811         final List<GeneratedType> generatedTypes = new ArrayList<>();
812         for (final ChoiceCaseNode caseNode : caseNodes) {
813             if (caseNode != null && caseNode.isAugmenting()) {
814                 final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
815                 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
816                 caseTypeBuilder.addImplementsType(refChoiceType);
817
818                 final Set<DataSchemaNode> childNodes = caseNode.getChildNodes();
819                 if (childNodes != null) {
820                     resolveDataSchemaNodes(basePackageName, caseTypeBuilder, childNodes);
821                 }
822                 generatedTypes.add(caseTypeBuilder.toInstance());
823             }
824         }
825
826         return generatedTypes;
827     }
828
829     private boolean resolveLeafSchemaNodeAsMethod(final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf) {
830         if ((leaf != null) && (typeBuilder != null)) {
831             final String leafName = leaf.getQName().getLocalName();
832             String leafDesc = leaf.getDescription();
833             if (leafDesc == null) {
834                 leafDesc = "";
835             }
836
837             if (leafName != null) {
838                 final TypeDefinition<?> typeDef = leaf.getType();
839
840                 Type returnType = null;
841                 if (typeDef instanceof EnumTypeDefinition) {
842                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef);
843                     final EnumTypeDefinition enumTypeDef = enumTypeDefFromExtendedType(typeDef);
844                     final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leafName,
845                             typeBuilder);
846
847                     if (enumBuilder != null) {
848                         returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName());
849                     }
850                     ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
851                 } else if (typeDef instanceof UnionType) {
852                     GeneratedTOBuilder genTOBuilder = addEnclosedTOToTypeBuilder(typeDef, typeBuilder, leafName);
853                     if (genTOBuilder != null) {
854                         returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());
855                     }
856                 } else if (typeDef instanceof BitsTypeDefinition) {
857                     GeneratedTOBuilder genTOBuilder = addEnclosedTOToTypeBuilder(typeDef, typeBuilder, leafName);
858                     if (genTOBuilder != null) {
859                         returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());
860                     }
861                 } else {
862                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef);
863                 }
864                 if (returnType != null) {
865                     constructGetter(typeBuilder, leafName, leafDesc, returnType);
866                     return true;
867                 }
868             }
869         }
870         return false;
871     }
872
873     private boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf,
874             boolean isReadOnly) {
875         if ((leaf != null) && (toBuilder != null)) {
876             final String leafName = leaf.getQName().getLocalName();
877             String leafDesc = leaf.getDescription();
878             if (leafDesc == null) {
879                 leafDesc = "";
880             }
881
882             if (leafName != null) {
883                 final TypeDefinition<?> typeDef = leaf.getType();
884
885                 // TODO: properly resolve enum types
886                 final Type returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef);
887
888                 if (returnType != null) {
889                     final GeneratedPropertyBuilder propBuilder = toBuilder.addProperty(parseToClassName(leafName));
890
891                     propBuilder.setReadOnly(isReadOnly);
892                     propBuilder.setReturnType(returnType);
893                     propBuilder.setComment(leafDesc);
894
895                     toBuilder.addEqualsIdentity(propBuilder);
896                     toBuilder.addHashIdentity(propBuilder);
897                     toBuilder.addToStringProperty(propBuilder);
898
899                     return true;
900                 }
901             }
902         }
903         return false;
904     }
905
906     private boolean resolveLeafListSchemaNode(final GeneratedTypeBuilder typeBuilder, final LeafListSchemaNode node) {
907         if ((node != null) && (typeBuilder != null)) {
908             final String nodeName = node.getQName().getLocalName();
909             String nodeDesc = node.getDescription();
910             if (nodeDesc == null) {
911                 nodeDesc = "";
912             }
913
914             if (nodeName != null) {
915                 final TypeDefinition<?> type = node.getType();
916                 final Type listType = Types.listTypeFor(typeProvider.javaTypeForSchemaDefinitionType(type));
917
918                 constructGetter(typeBuilder, nodeName, nodeDesc, listType);
919                 return true;
920             }
921         }
922         return false;
923     }
924
925     private boolean resolveContainerSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder,
926             final ContainerSchemaNode containerNode) {
927         if ((containerNode != null) && (typeBuilder != null)) {
928             final String nodeName = containerNode.getQName().getLocalName();
929
930             if (nodeName != null) {
931                 final String packageName = packageNameForGeneratedType(basePackageName, containerNode.getPath());
932
933                 final GeneratedTypeBuilder rawGenType = addDefaultInterfaceDefinition(packageName, containerNode);
934                 constructGetter(typeBuilder, nodeName, containerNode.getDescription(), rawGenType);
935
936                 return true;
937             }
938         }
939         return false;
940     }
941
942     private boolean resolveListSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder,
943             final ListSchemaNode schemaNode) {
944         if ((schemaNode != null) && (typeBuilder != null)) {
945             final String listName = schemaNode.getQName().getLocalName();
946
947             if (listName != null) {
948                 final String packageName = packageNameForGeneratedType(basePackageName, schemaNode.getPath());
949                 final GeneratedTypeBuilder rawGenType = addDefaultInterfaceDefinition(packageName, schemaNode);
950                 constructGetter(typeBuilder, listName, schemaNode.getDescription(), Types.listTypeFor(rawGenType));
951                 return true;
952             }
953         }
954         return false;
955     }
956
957     /**
958      * Method instantiates new Generated Type Builder and sets the implements
959      * definitions of Data Object and Augmentable.
960      * 
961      * @param packageName
962      *            Generated Type Package Name
963      * @param schemaNode
964      *            Schema Node definition
965      * @return Generated Type Builder instance for Schema Node definition
966      */
967     private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode) {
968         final GeneratedTypeBuilder builder = addRawInterfaceDefinition(packageName, schemaNode, "");
969         builder.addImplementsType(Types.DATA_OBJECT);
970         builder.addImplementsType(Types.augmentableTypeFor(builder));
971         return builder;
972     }
973
974     /**
975      * 
976      * @param packageName
977      * @param schemaNode
978      * @return
979      */
980     private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode) {
981         return addRawInterfaceDefinition(packageName, schemaNode, "");
982     }
983
984     private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
985             final String prefix) {
986         if (schemaNode == null) {
987             throw new IllegalArgumentException("Data Schema Node cannot be NULL!");
988         }
989         if (packageName == null) {
990             throw new IllegalArgumentException("Package Name for Generated Type cannot be NULL!");
991         }
992         if (schemaNode.getQName() == null) {
993             throw new IllegalArgumentException("QName for Data Schema Node cannot be NULL!");
994         }
995         final String schemaNodeName = schemaNode.getQName().getLocalName();
996         if (schemaNodeName == null) {
997             throw new IllegalArgumentException("Local Name of QName for Data Schema Node cannot be NULL!");
998         }
999
1000         final String genTypeName;
1001         if (prefix == null) {
1002             genTypeName = parseToClassName(schemaNodeName);
1003         } else {
1004             genTypeName = prefix + parseToClassName(schemaNodeName);
1005         }
1006
1007         final GeneratedTypeBuilder newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
1008         if (!genTypeBuilders.containsKey(packageName)) {
1009             final Map<String, GeneratedTypeBuilder> builders = new HashMap<>();
1010             builders.put(genTypeName, newType);
1011             genTypeBuilders.put(packageName, builders);
1012         } else {
1013             final Map<String, GeneratedTypeBuilder> builders = genTypeBuilders.get(packageName);
1014             if (!builders.containsKey(genTypeName)) {
1015                 builders.put(genTypeName, newType);
1016             }
1017         }
1018         return newType;
1019     }
1020
1021     private String getterMethodName(final String methodName) {
1022         final StringBuilder method = new StringBuilder();
1023         method.append("get");
1024         method.append(parseToClassName(methodName));
1025         return method.toString();
1026     }
1027
1028     private String setterMethodName(final String methodName) {
1029         final StringBuilder method = new StringBuilder();
1030         method.append("set");
1031         method.append(parseToClassName(methodName));
1032         return method.toString();
1033     }
1034
1035     private MethodSignatureBuilder constructGetter(final GeneratedTypeBuilder interfaceBuilder,
1036             final String schemaNodeName, final String comment, final Type returnType) {
1037         final MethodSignatureBuilder getMethod = interfaceBuilder.addMethod(getterMethodName(schemaNodeName));
1038
1039         getMethod.setComment(comment);
1040         getMethod.setReturnType(returnType);
1041
1042         return getMethod;
1043     }
1044
1045     private MethodSignatureBuilder constructSetter(final GeneratedTypeBuilder interfaceBuilder,
1046             final String schemaNodeName, final String comment, final Type parameterType) {
1047         final MethodSignatureBuilder setMethod = interfaceBuilder.addMethod(setterMethodName(schemaNodeName));
1048
1049         setMethod.setComment(comment);
1050         setMethod.addParameter(parameterType, parseToValidParamName(schemaNodeName));
1051         setMethod.setReturnType(Types.voidType());
1052
1053         return setMethod;
1054     }
1055
1056     private List<Type> listToGenType(final String basePackageName, final ListSchemaNode list) {
1057         if (basePackageName == null) {
1058             throw new IllegalArgumentException("Package Name for Generated Type cannot be NULL!");
1059         }
1060         if (list == null) {
1061             throw new IllegalArgumentException("List Schema Node cannot be NULL!");
1062         }
1063
1064         final String packageName = packageNameForGeneratedType(basePackageName, list.getPath());
1065         final GeneratedTypeBuilder typeBuilder = resolveListTypeBuilder(packageName, list);
1066         final List<String> listKeys = listKeys(list);
1067         GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(packageName, list, listKeys);
1068
1069         final Set<DataSchemaNode> schemaNodes = list.getChildNodes();
1070
1071         for (final DataSchemaNode schemaNode : schemaNodes) {
1072             if (schemaNode.isAugmenting()) {
1073                 continue;
1074             }
1075             addSchemaNodeToListBuilders(basePackageName, schemaNode, typeBuilder, genTOBuilder, listKeys);
1076         }
1077         return typeBuildersToGenTypes(typeBuilder, genTOBuilder);
1078     }
1079
1080     private void addSchemaNodeToListBuilders(final String basePackageName, final DataSchemaNode schemaNode,
1081             final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final List<String> listKeys) {
1082         if (schemaNode == null) {
1083             throw new IllegalArgumentException("Data Schema Node cannot be NULL!");
1084         }
1085
1086         if (typeBuilder == null) {
1087             throw new IllegalArgumentException("Generated Type Builder cannot be NULL!");
1088         }
1089
1090         if (schemaNode instanceof LeafSchemaNode) {
1091             final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode;
1092             if (!isPartOfListKey(leaf, listKeys)) {
1093                 resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
1094             } else {
1095                 resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true);
1096             }
1097         } else if (schemaNode instanceof LeafListSchemaNode) {
1098             resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode);
1099         } else if (schemaNode instanceof ContainerSchemaNode) {
1100             resolveContainerSchemaNode(basePackageName, typeBuilder, (ContainerSchemaNode) schemaNode);
1101         } else if (schemaNode instanceof ListSchemaNode) {
1102             resolveListSchemaNode(basePackageName, typeBuilder, (ListSchemaNode) schemaNode);
1103         }
1104     }
1105
1106     private List<Type> typeBuildersToGenTypes(final GeneratedTypeBuilder typeBuilder, GeneratedTOBuilder genTOBuilder) {
1107         final List<Type> genTypes = new ArrayList<>();
1108         if (typeBuilder == null) {
1109             throw new IllegalArgumentException("Generated Type Builder cannot be NULL!");
1110         }
1111
1112         if (genTOBuilder != null) {
1113             final GeneratedTransferObject genTO = genTOBuilder.toInstance();
1114             constructGetter(typeBuilder, genTO.getName(), "Returns Primary Key of Yang List Type", genTO);
1115             genTypes.add(genTO);
1116         }
1117         genTypes.add(typeBuilder.toInstance());
1118         return genTypes;
1119     }
1120
1121     /**
1122      * @param list
1123      * @return
1124      */
1125     private GeneratedTOBuilder resolveListKey(final String packageName, final ListSchemaNode list) {
1126         final String listName = list.getQName().getLocalName() + "Key";
1127         return schemaNodeToTransferObjectBuilder(packageName, list, listName);
1128     }
1129
1130     private boolean isPartOfListKey(final LeafSchemaNode leaf, final List<String> keys) {
1131         if ((leaf != null) && (keys != null) && (leaf.getQName() != null)) {
1132             final String leafName = leaf.getQName().getLocalName();
1133             if (keys.contains(leafName)) {
1134                 return true;
1135             }
1136         }
1137         return false;
1138     }
1139
1140     private List<String> listKeys(final ListSchemaNode list) {
1141         final List<String> listKeys = new ArrayList<>();
1142
1143         if (list.getKeyDefinition() != null) {
1144             final List<QName> keyDefinitions = list.getKeyDefinition();
1145
1146             for (final QName keyDefinition : keyDefinitions) {
1147                 listKeys.add(keyDefinition.getLocalName());
1148             }
1149         }
1150         return listKeys;
1151     }
1152
1153     private GeneratedTypeBuilder resolveListTypeBuilder(final String packageName, final ListSchemaNode list) {
1154         if (packageName == null) {
1155             throw new IllegalArgumentException("Package Name for Generated Type cannot be NULL!");
1156         }
1157         if (list == null) {
1158             throw new IllegalArgumentException("List Schema Node cannot be NULL!");
1159         }
1160
1161         final String schemaNodeName = list.getQName().getLocalName();
1162         final String genTypeName = parseToClassName(schemaNodeName);
1163
1164         GeneratedTypeBuilder typeBuilder = null;
1165         final Map<String, GeneratedTypeBuilder> builders = genTypeBuilders.get(packageName);
1166         if (builders != null) {
1167             typeBuilder = builders.get(genTypeName);
1168         }
1169         if (typeBuilder == null) {
1170             typeBuilder = addDefaultInterfaceDefinition(packageName, list);
1171         }
1172         return typeBuilder;
1173     }
1174
1175     private GeneratedTOBuilder resolveListKeyTOBuilder(final String packageName, final ListSchemaNode list,
1176             final List<String> listKeys) {
1177         GeneratedTOBuilder genTOBuilder = null;
1178         if (listKeys.size() > 0) {
1179             genTOBuilder = resolveListKey(packageName, list);
1180         }
1181         return genTOBuilder;
1182     }
1183
1184     private GeneratedTOBuilder addEnclosedTOToTypeBuilder(TypeDefinition<?> typeDef, GeneratedTypeBuilder typeBuilder,
1185             String leafName) {
1186         String className = parseToClassName(leafName);
1187         GeneratedTOBuilder genTOBuilder = null;
1188         if (typeDef instanceof UnionType) {
1189             genTOBuilder = ((TypeProviderImpl) typeProvider).addUnionGeneratedTypeDefinition(
1190                     typeBuilder.getFullyQualifiedName(), typeDef, className);
1191         } else if (typeDef instanceof BitsTypeDefinition) {
1192             genTOBuilder = ((TypeProviderImpl) typeProvider).bitsTypedefToTransferObject(
1193                     typeBuilder.getFullyQualifiedName(), typeDef, className);
1194         }
1195         if (genTOBuilder != null) {
1196             typeBuilder.addEnclosingTransferObject(genTOBuilder);
1197             return genTOBuilder;
1198         }
1199         return null;
1200
1201     }
1202
1203 }