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