Added support for list, leaf-list and container in output under rpc node in yang...
[controller.git] / opendaylight / config / yang-jmx-generator-plugin / src / main / java / org / opendaylight / controller / config / yangjmxgenerator / plugin / ftl / TemplateFactory.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.config.yangjmxgenerator.plugin.ftl;
9
10 import com.google.common.base.Function;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.Collections2;
13 import com.google.common.collect.Lists;
14 import com.google.common.collect.Maps;
15 import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
16 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
17 import org.opendaylight.controller.config.api.runtime.RuntimeBean;
18 import org.opendaylight.controller.config.spi.Module;
19 import org.opendaylight.controller.config.yangjmxgenerator.AbstractEntry;
20 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
21 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
22 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc;
23 import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry;
24 import org.opendaylight.controller.config.yangjmxgenerator.attribute.*;
25 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute.Dependency;
26 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.*;
27 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation.Parameter;
28 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
29 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
30 import org.opendaylight.yangtools.sal.binding.model.api.Type;
31
32 import javax.management.openmbean.SimpleType;
33 import java.util.*;
34 import java.util.Map.Entry;
35
36 public class TemplateFactory {
37
38     public static Map<String, FtlTemplate> getFtlTemplates(
39             ModuleMXBeanEntry entry) {
40         Map<String, FtlTemplate> result = new HashMap<>();
41
42         result.putAll(TemplateFactory.tOsFromMbe(entry));
43
44         // IFC
45         result.put(entry.getMXBeanInterfaceName() + ".java",
46                 TemplateFactory.mXBeanInterfaceTemplateFromMbe(entry));
47
48         // ABS fact
49         result.put(entry.getAbstractFactoryName() + ".java",
50                 TemplateFactory.abstractFactoryTemplateFromMbe(entry));
51
52         // ABS module
53         result.put(entry.getAbstractModuleName() + ".java",
54                 TemplateFactory.abstractModuleTemplateFromMbe(entry));
55
56         return result;
57     }
58
59     public static Map<String, FtlTemplate> getFtlStubTemplates(
60             ModuleMXBeanEntry entry) {
61         Map<String, FtlTemplate> result = new HashMap<>();
62         // STUB fact
63         result.put(entry.getStubFactoryName() + ".java",
64                 TemplateFactory.stubFactoryTemplateFromMbe(entry));
65
66         result.put(entry.getStubModuleName() + ".java",
67                 TemplateFactory.stubModuleTemplateFromMbe(entry));
68         return result;
69     }
70
71     public static Map<String, FtlTemplate> getFtlTemplates(
72             ServiceInterfaceEntry entry) {
73
74         Map<String, FtlTemplate> result = new HashMap<>();
75         result.put(entry.getTypeName() + ".java",
76                 TemplateFactory.serviceInterfaceFromSie(entry));
77
78         return result;
79     }
80
81     /**
82      * Get map of file name as key, FtlFile instance representing runtime mx
83      * bean as value that should be persisted from this instance.
84      */
85     public static Map<String, FtlTemplate> getTOAndMXInterfaceFtlFiles(
86             RuntimeBeanEntry entry) {
87         Map<String, FtlTemplate> result = new HashMap<>();
88         { // create GeneralInterfaceFtlFile for runtime MXBean. Attributes will
89           // be transformed to getter methods
90             String mxBeanTypeName = entry.getJavaNameOfRuntimeMXBean();
91             List<String> extendedInterfaces = Arrays.asList(RuntimeBean.class
92                     .getCanonicalName());
93             List<MethodDeclaration> methods = new ArrayList<>();
94
95             // convert attributes to getters
96             for (AttributeIfc attributeIfc : entry.getAttributes()) {
97                 String returnType = null;
98                 returnType = getReturnType(entry, attributeIfc);
99                 String getterName = "get"
100                         + attributeIfc.getUpperCaseCammelCase();
101                 MethodDeclaration getter = new MethodDeclaration(returnType,
102                         getterName, Collections.<Field> emptyList());
103                 methods.add(getter);
104             }
105
106             // add rpc methods
107             for (Rpc rpc : entry.getRpcs()) {
108                 // convert JavaAttribute parameters into fields
109                 List<Field> fields = new ArrayList<>();
110                 for (JavaAttribute ja : rpc.getParameters()) {
111                     Field field = new Field(Collections.<String> emptyList(),
112                             ja.getType().getFullyQualifiedName(),
113                             ja.getLowerCaseCammelCase());
114                     fields.add(field);
115                 }
116                 MethodDeclaration operation = new MethodDeclaration(
117                         getReturnType(entry, rpc.getReturnType()), rpc.getName(), fields);
118                 methods.add(operation);
119             }
120
121             // FIXME header
122             GeneralInterfaceTemplate runtimeMxBeanIfc = new GeneralInterfaceTemplate(
123                     null, entry.getPackageName(), mxBeanTypeName,
124                     extendedInterfaces, methods);
125
126             result.put(runtimeMxBeanIfc.getTypeDeclaration().getName()
127                     + ".java", runtimeMxBeanIfc);
128         }
129
130         result.putAll(TemplateFactory.tOsFromRbe(entry));
131
132         return result;
133     }
134
135     private static String getReturnType(RuntimeBeanEntry entry, AttributeIfc attributeIfc) {
136         String returnType;
137         if (attributeIfc instanceof TypedAttribute) {
138             returnType = ((TypedAttribute) attributeIfc).getType()
139                     .getFullyQualifiedName();
140         } else if (attributeIfc instanceof TOAttribute) {
141             String fullyQualifiedName = FullyQualifiedNameHelper
142                     .getFullyQualifiedName(entry.getPackageName(),
143                             attributeIfc.getUpperCaseCammelCase());
144
145             returnType = fullyQualifiedName;
146         } else if (attributeIfc instanceof ListAttribute) {
147             AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
148                     .getInnerAttribute();
149
150             String innerTpe = innerAttr instanceof TypedAttribute ? ((TypedAttribute) innerAttr)
151                     .getType().getFullyQualifiedName()
152                     : FullyQualifiedNameHelper.getFullyQualifiedName(
153                             entry.getPackageName(),
154                             attributeIfc.getUpperCaseCammelCase());
155
156             returnType = "java.util.List<" + innerTpe + ">";
157         } else if (attributeIfc == VoidAttribute.getInstance()) {
158             return "void";
159         } else {
160             throw new UnsupportedOperationException(
161                     "Attribute not supported: "
162                             + attributeIfc.getClass());
163         }
164         return returnType;
165     }
166
167     public static GeneralInterfaceTemplate serviceInterfaceFromSie(
168             ServiceInterfaceEntry sie) {
169
170         List<String> extendedInterfaces = Lists
171                 .newArrayList(AbstractServiceInterface.class.getCanonicalName());
172         if (sie.getBase().isPresent()) {
173             extendedInterfaces.add(sie.getBase().get().getFullyQualifiedName());
174         }
175
176         // FIXME header
177         GeneralInterfaceTemplate sieTemplate = new GeneralInterfaceTemplate(
178                 getHeaderFromEntry(sie), sie.getPackageName(),
179                 sie.getTypeName(), extendedInterfaces,
180                 Lists.<MethodDeclaration> newArrayList());
181         sieTemplate.setJavadoc(sie.getNullableDescription());
182
183         if (sie.getNullableDescription() != null)
184             sieTemplate.getAnnotations().add(
185                     Annotation.createDescriptionAnnotation(sie
186                             .getNullableDescription()));
187         sieTemplate.getAnnotations().add(Annotation.createSieAnnotation(sie.getQName(), sie.getExportedOsgiClassName
188                 ()));
189
190         return sieTemplate;
191     }
192
193     public static AbstractFactoryTemplate abstractFactoryTemplateFromMbe(
194             ModuleMXBeanEntry mbe) {
195         AbstractFactoryAttributesProcessor attrProcessor = new AbstractFactoryAttributesProcessor();
196         attrProcessor.processAttributes(mbe.getAttributes(),
197                 mbe.getPackageName());
198
199         Collection<String> transformed = Collections2.transform(mbe
200                 .getProvidedServices().keySet(),
201                 new Function<String, String>() {
202
203                     @Override
204                     public String apply(String input) {
205                         return input + ".class";
206                     }
207                 });
208
209         return new AbstractFactoryTemplate(getHeaderFromEntry(mbe),
210                 mbe.getPackageName(), mbe.getAbstractFactoryName(),
211                 mbe.getGloballyUniqueName(), mbe.getFullyQualifiedName(mbe
212                         .getStubModuleName()), attrProcessor.getFields(),
213                 Lists.newArrayList(transformed));
214     }
215
216     public static AbstractModuleTemplate abstractModuleTemplateFromMbe(
217             ModuleMXBeanEntry mbe) {
218         AbstractModuleAttributesProcessor attrProcessor = new AbstractModuleAttributesProcessor();
219         attrProcessor.processAttributes(mbe.getAttributes(),
220                 mbe.getPackageName());
221
222         List<ModuleField> moduleFields = attrProcessor.getModuleFields();
223         List<String> implementedIfcs = Lists.newArrayList(
224                 Module.class.getCanonicalName(),
225                 mbe.getFullyQualifiedName(mbe.getMXBeanInterfaceName()));
226
227         for (String implementedService : mbe.getProvidedServices().keySet()) {
228             implementedIfcs.add(implementedService);
229         }
230
231         boolean generateRuntime = false;
232         String registratorFullyQualifiedName = null;
233         if (mbe.getRuntimeBeans() != null
234                 && mbe.getRuntimeBeans().isEmpty() == false) {
235             generateRuntime = true;
236             RuntimeBeanEntry rootEntry = RuntimeRegistratorFtlTemplate
237                     .findRoot(mbe.getRuntimeBeans());
238             registratorFullyQualifiedName = rootEntry
239                     .getPackageName()
240                     .concat(".")
241                     .concat(RuntimeRegistratorFtlTemplate.getJavaNameOfRuntimeRegistrator(rootEntry));
242             implementedIfcs.add(RuntimeBeanRegistratorAwareModule.class
243                     .getCanonicalName());
244         }
245
246         AbstractModuleTemplate abstractModuleTemplate = new AbstractModuleTemplate(
247                 getHeaderFromEntry(mbe), mbe.getPackageName(),
248                 mbe.getAbstractModuleName(), implementedIfcs, moduleFields,
249                 attrProcessor.getMethods(), generateRuntime,
250                 registratorFullyQualifiedName);
251
252         if (mbe.getNullableDescription() != null)
253             abstractModuleTemplate.getAnnotations().add(
254                     Annotation.createDescriptionAnnotation(mbe
255                             .getNullableDescription()));
256         return abstractModuleTemplate;
257     }
258
259     public static StubFactoryTemplate stubFactoryTemplateFromMbe(
260             ModuleMXBeanEntry mbe) {
261         return new StubFactoryTemplate(getHeaderFromEntry(mbe),
262                 mbe.getPackageName(), mbe.getStubFactoryName(),
263                 mbe.getFullyQualifiedName(mbe.getAbstractFactoryName()),
264                 mbe.getStubModuleName());
265     }
266
267     public static StubModuleTemplate stubModuleTemplateFromMbe(
268             ModuleMXBeanEntry mbe) {
269         return new StubModuleTemplate(getHeaderFromEntry(mbe),
270                 mbe.getPackageName(), mbe.getStubModuleName(),
271                 mbe.getFullyQualifiedName(mbe.getAbstractModuleName()));
272     }
273
274     public static GeneralInterfaceTemplate mXBeanInterfaceTemplateFromMbe(
275             ModuleMXBeanEntry mbe) {
276         MXBeanInterfaceAttributesProcessor attrProcessor = new MXBeanInterfaceAttributesProcessor();
277         attrProcessor.processAttributes(mbe.getAttributes(),
278                 mbe.getPackageName());
279         GeneralInterfaceTemplate ifcTemplate = new GeneralInterfaceTemplate(
280                 getHeaderFromEntry(mbe), mbe.getPackageName(),
281                 mbe.getMXBeanInterfaceName(), Lists.<String> newArrayList(),
282                 attrProcessor.getMethods());
283         ifcTemplate.setJavadoc(mbe.getNullableDescription());
284         return ifcTemplate;
285     }
286
287     public static Map<String, GeneralClassTemplate> tOsFromMbe(
288             ModuleMXBeanEntry mbe) {
289         Map<String, GeneralClassTemplate> retVal = Maps.newHashMap();
290         TOAttributesProcessor processor = new TOAttributesProcessor();
291         processor.processAttributes(mbe.getAttributes(), mbe.getPackageName());
292         for (org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory.TOAttributesProcessor.TOInternal to : processor
293                 .getTOs()) {
294             List<Constructor> constructors = Lists.newArrayList();
295             constructors.add(new Constructor(to.getName(), "super();"));
296
297             Header header = getHeaderFromEntry(mbe);
298             retVal.put(
299                     to.getType(),
300                     new GeneralClassTemplate(header, mbe.getPackageName(), to
301                             .getName(), Collections.<String> emptyList(),
302                             Collections.<String> emptyList(), to.getFields(),
303                             to.getMethods(), false, false, constructors));
304         }
305         return retVal;
306     }
307
308     public static Map<String, GeneralClassTemplate> tOsFromRbe(
309             RuntimeBeanEntry rbe) {
310         Map<String, GeneralClassTemplate> retVal = Maps.newHashMap();
311         TOAttributesProcessor processor = new TOAttributesProcessor();
312         Map<String, AttributeIfc> yangPropertiesToTypesMap = Maps.newHashMap(rbe.getYangPropertiesToTypesMap());
313
314         // Add TOs from output parameters
315         for (Rpc rpc : rbe.getRpcs()) {
316             AttributeIfc returnType = rpc.getReturnType();
317
318             if (returnType == VoidAttribute.getInstance())
319                 continue;
320             if (returnType instanceof JavaAttribute)
321                 continue;
322             if (returnType instanceof ListAttribute && returnType.getOpenType() instanceof SimpleType)
323                 continue;
324
325             Preconditions.checkState(yangPropertiesToTypesMap.containsKey(returnType.getAttributeYangName()) == false,
326                     "Duplicate TO %s for %s", returnType.getAttributeYangName(), rbe);
327             yangPropertiesToTypesMap.put(returnType.getAttributeYangName(), returnType);
328         }
329
330         processor.processAttributes(yangPropertiesToTypesMap, rbe.getPackageName());
331         for (org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory.TOAttributesProcessor.TOInternal to : processor
332                 .getTOs()) {
333             List<Constructor> constructors = Lists.newArrayList();
334             constructors.add(new Constructor(to.getName(), "super();"));
335
336             // TODO header
337             retVal.put(
338                     to.getType(),
339                     new GeneralClassTemplate(null, rbe.getPackageName(), to
340                             .getName(), Collections.<String> emptyList(),
341                             Collections.<String> emptyList(), to.getFields(),
342                             to.getMethods(), false, false, constructors));
343         }
344         return retVal;
345     }
346
347     private static Header getHeaderFromEntry(AbstractEntry mbe) {
348         return new Header(mbe.getYangModuleName(), mbe.getYangModuleLocalname());
349     }
350
351     // TODO refactor attribute processors
352
353     private static class TOAttributesProcessor {
354
355         private final List<TOInternal> tos = Lists.newArrayList();
356
357         void processAttributes(Map<String, AttributeIfc> attributes,
358                 String packageName) {
359             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
360                 AttributeIfc attributeIfc = attrEntry.getValue();
361                 if (attributeIfc instanceof TOAttribute) {
362                     createTOInternal(packageName, attributeIfc);
363                 }
364                 if (attributeIfc instanceof ListAttribute) {
365                     AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
366                             .getInnerAttribute();
367                     if (innerAttr instanceof TOAttribute) {
368                         createTOInternal(packageName, innerAttr);
369                     }
370                 }
371             }
372         }
373
374         private void createTOInternal(String packageName,
375                 AttributeIfc attributeIfc) {
376             String fullyQualifiedName = FullyQualifiedNameHelper
377                     .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
378
379             String type = fullyQualifiedName;
380             String name = attributeIfc.getUpperCaseCammelCase();
381             Map<String, AttributeIfc> attrs = ((TOAttribute) attributeIfc)
382                     .getCapitalizedPropertiesToTypesMap();
383             // recursive processing
384             processAttributes(attrs, packageName);
385
386             tos.add(new TOInternal(type, name, attrs, packageName));
387         }
388
389         List<TOInternal> getTOs() {
390             return tos;
391         }
392
393         private static class TOInternal {
394             private final String type, name;
395             private List<Field> fields;
396             private List<MethodDefinition> methods;
397
398             public TOInternal(String type, String name,
399                     Map<String, AttributeIfc> attrs, String packageName) {
400                 super();
401                 this.type = type;
402                 this.name = name;
403                 processAttrs(attrs, packageName);
404             }
405
406             private void processAttrs(Map<String, AttributeIfc> attrs,
407                     String packageName) {
408                 fields = Lists.newArrayList();
409                 methods = Lists.newArrayList();
410
411                 for (Entry<String, AttributeIfc> attrEntry : attrs.entrySet()) {
412                     String innerName = attrEntry.getKey();
413                     String varName = BindingGeneratorUtil
414                             .parseToValidParamName(attrEntry.getKey());
415
416                     String fullyQualifiedName = null;
417                     if (attrEntry.getValue() instanceof TypedAttribute) {
418                         Type innerType = ((TypedAttribute) attrEntry.getValue())
419                                 .getType();
420                         fullyQualifiedName = innerType.getFullyQualifiedName();
421                     } else if (attrEntry.getValue() instanceof ListAttribute) {
422                         AttributeIfc innerAttr = ((ListAttribute) attrEntry
423                                 .getValue()).getInnerAttribute();
424
425                         String innerTpe = innerAttr instanceof TypedAttribute ? ((TypedAttribute) innerAttr)
426                                 .getType().getFullyQualifiedName()
427                                 : FullyQualifiedNameHelper
428                                         .getFullyQualifiedName(packageName, attrEntry.getValue().getUpperCaseCammelCase());
429
430                         fullyQualifiedName = "java.util.List<" + innerTpe + ">";
431                     } else
432                         fullyQualifiedName = FullyQualifiedNameHelper
433                                 .getFullyQualifiedName(packageName, attrEntry.getValue().getUpperCaseCammelCase());
434
435                     fields.add(new Field(fullyQualifiedName, varName));
436
437                     String getterName = "get" + innerName;
438                     MethodDefinition getter = new MethodDefinition(
439                             fullyQualifiedName, getterName,
440                             Collections.<Field> emptyList(), "return "
441                                     + varName + ";");
442
443                     String setterName = "set" + innerName;
444                     MethodDefinition setter = new MethodDefinition("void",
445                             setterName, Lists.newArrayList(new Field(
446                                     fullyQualifiedName, varName)), "this."
447                                     + varName + " = " + varName + ";");
448                     methods.add(getter);
449                     methods.add(setter);
450                 }
451
452             }
453
454             String getType() {
455                 return type;
456             }
457
458             String getName() {
459                 return name;
460             }
461
462             List<Field> getFields() {
463                 return fields;
464             }
465
466             List<MethodDefinition> getMethods() {
467                 return methods;
468             }
469         }
470     }
471
472     private static class MXBeanInterfaceAttributesProcessor {
473         private static final String STRING_FULLY_QUALIFIED_NAME = "java.util.List";
474         private final List<MethodDeclaration> methods = Lists.newArrayList();
475
476         void processAttributes(Map<String, AttributeIfc> attributes,
477                 String packageName) {
478             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
479                 String returnType;
480                 AttributeIfc attributeIfc = attrEntry.getValue();
481
482                 if (attributeIfc instanceof TypedAttribute) {
483                     returnType = ((TypedAttribute) attributeIfc).getType()
484                             .getFullyQualifiedName();
485                 } else if (attributeIfc instanceof TOAttribute) {
486                     String fullyQualifiedName = FullyQualifiedNameHelper
487                             .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
488
489                     returnType = fullyQualifiedName;
490                 } else if (attributeIfc instanceof ListAttribute) {
491                     String fullyQualifiedName = null;
492
493                     AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
494                             .getInnerAttribute();
495                     if (innerAttr instanceof JavaAttribute) {
496                         fullyQualifiedName = ((JavaAttribute) innerAttr)
497                                 .getType().getFullyQualifiedName();
498                     } else if (innerAttr instanceof TOAttribute) {
499                         fullyQualifiedName = FullyQualifiedNameHelper
500                                 .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
501                     }
502
503                     returnType = STRING_FULLY_QUALIFIED_NAME.concat("<")
504                             .concat(fullyQualifiedName).concat(">");
505                 } else {
506                     throw new UnsupportedOperationException(
507                             "Attribute not supported: "
508                                     + attributeIfc.getClass());
509                 }
510
511                 String getterName = "get"
512                         + attributeIfc.getUpperCaseCammelCase();
513                 MethodDeclaration getter = new MethodDeclaration(returnType,
514                         getterName, Collections.<Field> emptyList());
515
516                 String varName = BindingGeneratorUtil
517                         .parseToValidParamName(attrEntry.getKey());
518                 String setterName = "set"
519                         + attributeIfc.getUpperCaseCammelCase();
520                 MethodDeclaration setter = new MethodDeclaration("void",
521                         setterName, Lists.newArrayList(new Field(returnType,
522                                 varName)));
523                 methods.add(getter);
524                 methods.add(setter);
525
526                 if (attributeIfc.getNullableDescription() != null) {
527                     setter.setJavadoc(attrEntry.getValue()
528                             .getNullableDescription());
529                 }
530             }
531         }
532
533         List<MethodDeclaration> getMethods() {
534             return methods;
535         }
536     }
537
538     private static class AbstractFactoryAttributesProcessor {
539
540         private final List<Field> fields = Lists.newArrayList();
541         private static final String STRING_FULLY_QUALIFIED_NAME = "java.util.List";
542
543         void processAttributes(Map<String, AttributeIfc> attributes,
544                 String packageName) {
545             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
546                 String type;
547                 AttributeIfc attributeIfc = attrEntry.getValue();
548
549                 if (attributeIfc instanceof TypedAttribute) {
550                     type = ((TypedAttribute) attributeIfc).getType()
551                             .getFullyQualifiedName();
552                 } else if (attributeIfc instanceof TOAttribute) {
553                     String fullyQualifiedName = FullyQualifiedNameHelper
554                             .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
555
556                     type = fullyQualifiedName;
557                 } else if (attributeIfc instanceof ListAttribute) {
558                     String fullyQualifiedName = null;
559                     AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
560                             .getInnerAttribute();
561                     if (innerAttr instanceof JavaAttribute) {
562                         fullyQualifiedName = ((JavaAttribute) innerAttr)
563                                 .getType().getFullyQualifiedName();
564                     } else if (innerAttr instanceof TOAttribute) {
565                         fullyQualifiedName = FullyQualifiedNameHelper
566                                 .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
567                     }
568
569                     type = STRING_FULLY_QUALIFIED_NAME.concat("<")
570                             .concat(fullyQualifiedName).concat(">");
571
572                 } else {
573                     throw new UnsupportedOperationException(
574                             "Attribute not supported: "
575                                     + attributeIfc.getClass());
576                 }
577
578                 fields.add(new Field(type, attributeIfc
579                         .getUpperCaseCammelCase()));
580             }
581         }
582
583         List<Field> getFields() {
584             return fields;
585         }
586     }
587
588     private static class AbstractModuleAttributesProcessor {
589
590         private static final String STRING_FULLY_QUALIFIED_NAME = "java.util.List";
591
592         private final List<ModuleField> moduleFields = Lists.newArrayList();
593         private final List<MethodDefinition> methods = Lists.newArrayList();
594
595         void processAttributes(Map<String, AttributeIfc> attributes,
596                 String packageName) {
597             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
598                 String type;
599                 AttributeIfc attributeIfc = attrEntry.getValue();
600
601                 if (attributeIfc instanceof TypedAttribute) {
602                     type = ((TypedAttribute) attributeIfc).getType()
603                             .getFullyQualifiedName();
604                 } else if (attributeIfc instanceof TOAttribute) {
605                     String fullyQualifiedName = FullyQualifiedNameHelper
606                             .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
607
608                     type = fullyQualifiedName;
609                 } else if (attributeIfc instanceof ListAttribute) {
610                     String fullyQualifiedName = null;
611                     AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
612                             .getInnerAttribute();
613                     if (innerAttr instanceof JavaAttribute) {
614                         fullyQualifiedName = ((JavaAttribute) innerAttr)
615                                 .getType().getFullyQualifiedName();
616                     } else if (innerAttr instanceof TOAttribute) {
617                         fullyQualifiedName = FullyQualifiedNameHelper
618                                 .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
619                     }
620
621                     type = STRING_FULLY_QUALIFIED_NAME.concat("<")
622                             .concat(fullyQualifiedName).concat(">");
623                 } else {
624                     throw new UnsupportedOperationException(
625                             "Attribute not supported: "
626                                     + attributeIfc.getClass());
627                 }
628
629                 boolean isDependency = false;
630                 Dependency dependency = null;
631                 Annotation overrideAnnotation = new Annotation("Override",
632                         Collections.<Parameter> emptyList());
633                 List<Annotation> annotations = Lists
634                         .newArrayList(overrideAnnotation);
635
636                 if (attributeIfc instanceof DependencyAttribute) {
637                     isDependency = true;
638                     dependency = ((DependencyAttribute) attributeIfc)
639                             .getDependency();
640                     annotations.add(Annotation
641                             .createRequireIfcAnnotation(dependency.getSie()));
642                 }
643
644                 String varName = BindingGeneratorUtil
645                         .parseToValidParamName(attrEntry.getKey());
646                 moduleFields.add(new ModuleField(type, varName, attributeIfc
647                         .getUpperCaseCammelCase(), attributeIfc
648                         .getNullableDefault(), isDependency, dependency));
649
650                 String getterName = "get"
651                         + attributeIfc.getUpperCaseCammelCase();
652                 MethodDefinition getter = new MethodDefinition(type,
653                         getterName, Collections.<Field> emptyList(),
654                         Lists.newArrayList(overrideAnnotation), "return "
655                                 + varName + ";");
656
657                 String setterName = "set"
658                         + attributeIfc.getUpperCaseCammelCase();
659
660                 if (attributeIfc.getNullableDescription() != null) {
661                     annotations.add(Annotation
662                             .createDescriptionAnnotation(attributeIfc.getNullableDescription()));
663                 }
664
665                 MethodDefinition setter = new MethodDefinition("void",
666                         setterName,
667                         Lists.newArrayList(new Field(type, varName)),
668                         annotations, "this." + varName + " = " + varName + ";");
669                 setter.setJavadoc(attributeIfc.getNullableDescription());
670
671                 methods.add(getter);
672                 methods.add(setter);
673             }
674         }
675
676         List<ModuleField> getModuleFields() {
677             return moduleFields;
678         }
679
680         List<MethodDefinition> getMethods() {
681             return methods;
682         }
683
684     }
685
686 }