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