Fixed deserialization of IdentityRefs in Restconf URI.
[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());
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().add(Annotation.createSieAnnotation(sie.getQName(), sie.getExportedOsgiClassName
214                 ()));
215
216         return sieTemplate;
217     }
218
219     public static AbstractFactoryTemplate abstractFactoryTemplateFromMbe(
220             ModuleMXBeanEntry mbe) {
221         AbstractFactoryAttributesProcessor attrProcessor = new AbstractFactoryAttributesProcessor();
222         attrProcessor.processAttributes(mbe.getAttributes(),
223                 mbe.getPackageName());
224
225         Collection<String> transformed = Collections2.transform(mbe
226                 .getProvidedServices().keySet(),
227                 new Function<String, String>() {
228
229                     @Override
230                     public String apply(String input) {
231                         return input + ".class";
232                     }
233                 });
234
235         return new AbstractFactoryTemplate(getHeaderFromEntry(mbe),
236                 mbe.getPackageName(), mbe.getAbstractFactoryName(),
237                 mbe.getGloballyUniqueName(), mbe.getFullyQualifiedName(mbe
238                         .getStubModuleName()), attrProcessor.getFields(),
239                 Lists.newArrayList(transformed));
240     }
241
242     public static AbstractModuleTemplate abstractModuleTemplateFromMbe(
243             ModuleMXBeanEntry mbe) {
244         AbstractModuleAttributesProcessor attrProcessor = new AbstractModuleAttributesProcessor();
245         attrProcessor.processAttributes(mbe.getAttributes(),
246                 mbe.getPackageName());
247
248         List<ModuleField> moduleFields = attrProcessor.getModuleFields();
249         List<String> implementedIfcs = Lists.newArrayList(
250                 Module.class.getCanonicalName(),
251                 mbe.getFullyQualifiedName(mbe.getMXBeanInterfaceName()));
252
253         for (String implementedService : mbe.getProvidedServices().keySet()) {
254             implementedIfcs.add(implementedService);
255         }
256
257         boolean generateRuntime = false;
258         String registratorFullyQualifiedName = null;
259         if (mbe.getRuntimeBeans() != null
260                 && mbe.getRuntimeBeans().isEmpty() == false) {
261             generateRuntime = true;
262             RuntimeBeanEntry rootEntry = RuntimeRegistratorFtlTemplate
263                     .findRoot(mbe.getRuntimeBeans());
264             registratorFullyQualifiedName = rootEntry
265                     .getPackageName()
266                     .concat(".")
267                     .concat(RuntimeRegistratorFtlTemplate.getJavaNameOfRuntimeRegistrator(rootEntry));
268             implementedIfcs.add(RuntimeBeanRegistratorAwareModule.class
269                     .getCanonicalName());
270         }
271
272         AbstractModuleTemplate abstractModuleTemplate = new AbstractModuleTemplate(
273                 getHeaderFromEntry(mbe), mbe.getPackageName(),
274                 mbe.getAbstractModuleName(), implementedIfcs, moduleFields,
275                 attrProcessor.getMethods(), generateRuntime,
276                 registratorFullyQualifiedName);
277
278         if (mbe.getNullableDescription() != null)
279             abstractModuleTemplate.getAnnotations().add(
280                     Annotation.createDescriptionAnnotation(mbe
281                             .getNullableDescription()));
282         return abstractModuleTemplate;
283     }
284
285     public static StubFactoryTemplate stubFactoryTemplateFromMbe(
286             ModuleMXBeanEntry mbe) {
287         return new StubFactoryTemplate(getHeaderFromEntry(mbe),
288                 mbe.getPackageName(), mbe.getStubFactoryName(),
289                 mbe.getFullyQualifiedName(mbe.getAbstractFactoryName()),
290                 mbe.getStubModuleName());
291     }
292
293     public static StubModuleTemplate stubModuleTemplateFromMbe(
294             ModuleMXBeanEntry mbe) {
295         return new StubModuleTemplate(getHeaderFromEntry(mbe),
296                 mbe.getPackageName(), mbe.getStubModuleName(),
297                 mbe.getFullyQualifiedName(mbe.getAbstractModuleName()));
298     }
299
300     public static GeneralInterfaceTemplate mXBeanInterfaceTemplateFromMbe(
301             ModuleMXBeanEntry mbe) {
302         MXBeanInterfaceAttributesProcessor attrProcessor = new MXBeanInterfaceAttributesProcessor();
303         attrProcessor.processAttributes(mbe.getAttributes());
304         GeneralInterfaceTemplate ifcTemplate = new GeneralInterfaceTemplate(
305                 getHeaderFromEntry(mbe), mbe.getPackageName(),
306                 mbe.getMXBeanInterfaceName(), Lists.<String> newArrayList(),
307                 attrProcessor.getMethods());
308         ifcTemplate.setJavadoc(mbe.getNullableDescription());
309         return ifcTemplate;
310     }
311
312     public static Map<String, GeneralClassTemplate> tOsFromMbe(
313             ModuleMXBeanEntry mbe) {
314         Map<String, GeneralClassTemplate> retVal = Maps.newHashMap();
315         TOAttributesProcessor processor = new TOAttributesProcessor();
316         processor.processAttributes(mbe.getAttributes());
317         for (org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory.TOAttributesProcessor.TOInternal to : processor
318                 .getTOs()) {
319             List<Constructor> constructors = Lists.newArrayList();
320             constructors.add(new Constructor(to.getName(), "super();"));
321
322             Header header = getHeaderFromEntry(mbe);
323             retVal.put(
324                     to.getType(),
325                     new GeneralClassTemplate(header, mbe.getPackageName(), to
326                             .getName(), Collections.<String> emptyList(),
327                             Collections.<String> emptyList(), to.getFields(),
328                             to.getMethods(), false, false, constructors));
329         }
330         return retVal;
331     }
332
333     public static Map<String, GeneralClassTemplate> tOsFromRbe(
334             RuntimeBeanEntry rbe) {
335         Map<String, GeneralClassTemplate> retVal = Maps.newHashMap();
336         TOAttributesProcessor processor = new TOAttributesProcessor();
337         Map<String, AttributeIfc> yangPropertiesToTypesMap = Maps.newHashMap(rbe.getYangPropertiesToTypesMap());
338
339         // Add TOs from output parameters
340         for (Rpc rpc : rbe.getRpcs()) {
341             AttributeIfc returnType = rpc.getReturnType();
342
343             if (returnType == VoidAttribute.getInstance())
344                 continue;
345             if (returnType instanceof JavaAttribute)
346                 continue;
347             if (returnType instanceof ListAttribute && returnType.getOpenType() instanceof SimpleType)
348                 continue;
349
350             Preconditions.checkState(yangPropertiesToTypesMap.containsKey(returnType.getAttributeYangName()) == false,
351                     "Duplicate TO %s for %s", returnType.getAttributeYangName(), rbe);
352             yangPropertiesToTypesMap.put(returnType.getAttributeYangName(), returnType);
353         }
354
355         processor.processAttributes(yangPropertiesToTypesMap);
356         for (org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory.TOAttributesProcessor.TOInternal to : processor
357                 .getTOs()) {
358             List<Constructor> constructors = Lists.newArrayList();
359             constructors.add(new Constructor(to.getName(), "super();"));
360
361             // TODO header
362             retVal.put(
363                     to.getType(),
364                     new GeneralClassTemplate(null, rbe.getPackageName(), to
365                             .getName(), Collections.<String> emptyList(),
366                             Collections.<String> emptyList(), to.getFields(),
367                             to.getMethods(), false, false, constructors));
368         }
369         return retVal;
370     }
371
372     private static Header getHeaderFromEntry(AbstractEntry mbe) {
373         return new Header(mbe.getYangModuleName(), mbe.getYangModuleLocalname());
374     }
375
376     // TODO refactor attribute processors
377
378     private static class TOAttributesProcessor {
379
380         private final List<TOInternal> tos = Lists.newArrayList();
381
382         void processAttributes(Map<String, AttributeIfc> attributes) {
383             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
384                 AttributeIfc attributeIfc = attrEntry.getValue();
385                 if (attributeIfc instanceof TOAttribute) {
386                     createTOInternal((TOAttribute) attributeIfc);
387                 }
388                 if (attributeIfc instanceof ListAttribute) {
389                     AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
390                             .getInnerAttribute();
391                     if (innerAttr instanceof TOAttribute) {
392                         createTOInternal((TOAttribute) innerAttr);
393                     }
394                 }
395             }
396         }
397
398         private void createTOInternal(TOAttribute toAttribute) {
399
400             Map<String, AttributeIfc> attrs = toAttribute.getCapitalizedPropertiesToTypesMap();
401             // recursive processing of TO's attributes
402             processAttributes(attrs);
403
404             tos.add(new TOInternal(toAttribute.getType(), attrs));
405         }
406
407         List<TOInternal> getTOs() {
408             return tos;
409         }
410
411         private static class TOInternal {
412             private final String fullyQualifiedName, name;
413             private List<Field> fields;
414             private List<MethodDefinition> methods;
415
416             public TOInternal(Type type, Map<String, AttributeIfc> attrs) {
417                 this(type.getFullyQualifiedName(), type.getName(), attrs, type.getPackageName());
418             }
419
420             public TOInternal(String fullyQualifiedName, String name,
421                     Map<String, AttributeIfc> attrs, String packageName) {
422                 this.fullyQualifiedName = fullyQualifiedName;
423                 this.name = name;
424                 processAttrs(attrs, packageName);
425             }
426
427             private void processAttrs(Map<String, AttributeIfc> attrs, String packageName) {
428                 fields = Lists.newArrayList();
429                 methods = Lists.newArrayList();
430
431                 for (Entry<String, AttributeIfc> attrEntry : attrs.entrySet()) {
432                     String innerName = attrEntry.getKey();
433                     String varName = BindingGeneratorUtil
434                             .parseToValidParamName(attrEntry.getKey());
435
436                     String fullyQualifiedName;
437                     if (attrEntry.getValue() instanceof TypedAttribute) {
438                         Type type = ((TypedAttribute) attrEntry.getValue()).getType();
439                         fullyQualifiedName = serializeType(type);
440                     } else {
441                         fullyQualifiedName = FullyQualifiedNameHelper
442                                 .getFullyQualifiedName(packageName, attrEntry.getValue().getUpperCaseCammelCase());
443                     }
444                     fields.add(new Field(fullyQualifiedName, varName));
445
446                     String getterName = "get" + innerName;
447                     MethodDefinition getter = new MethodDefinition(
448                             fullyQualifiedName, getterName,
449                             Collections.<Field> emptyList(), "return "
450                                     + varName + ";");
451
452                     String setterName = "set" + innerName;
453                     MethodDefinition setter = new MethodDefinition("void",
454                             setterName, Lists.newArrayList(new Field(
455                                     fullyQualifiedName, varName)), "this."
456                                     + varName + " = " + varName + ";");
457                     methods.add(getter);
458                     methods.add(setter);
459                 }
460
461             }
462
463             String getType() {
464                 return fullyQualifiedName;
465             }
466
467             String getName() {
468                 return name;
469             }
470
471             List<Field> getFields() {
472                 return fields;
473             }
474
475             List<MethodDefinition> getMethods() {
476                 return methods;
477             }
478         }
479     }
480
481     private static class MXBeanInterfaceAttributesProcessor {
482         private final List<MethodDeclaration> methods = Lists.newArrayList();
483
484         void processAttributes(Map<String, AttributeIfc> attributes) {
485             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
486                 String returnType;
487                 AttributeIfc attributeIfc = attrEntry.getValue();
488
489                 if (attributeIfc instanceof TypedAttribute) {
490                     TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
491                     returnType = serializeType(typedAttribute.getType());
492                 } else {
493                     throw new UnsupportedOperationException(
494                             "Attribute not supported: "
495                                     + attributeIfc.getClass());
496                 }
497
498                 String getterName = "get"
499                         + attributeIfc.getUpperCaseCammelCase();
500                 MethodDeclaration getter = new MethodDeclaration(returnType,
501                         getterName, Collections.<Field> emptyList());
502
503                 String varName = BindingGeneratorUtil
504                         .parseToValidParamName(attrEntry.getKey());
505                 String setterName = "set"
506                         + attributeIfc.getUpperCaseCammelCase();
507                 MethodDeclaration setter = new MethodDeclaration("void",
508                         setterName, Lists.newArrayList(new Field(returnType,
509                                 varName)));
510                 methods.add(getter);
511                 methods.add(setter);
512
513                 if (attributeIfc.getNullableDescription() != null) {
514                     setter.setJavadoc(attrEntry.getValue()
515                             .getNullableDescription());
516                 }
517             }
518         }
519
520         List<MethodDeclaration> getMethods() {
521             return methods;
522         }
523     }
524
525     private static class AbstractFactoryAttributesProcessor {
526
527         private final List<Field> fields = Lists.newArrayList();
528         private static final String STRING_FULLY_QUALIFIED_NAME = "java.util.List";
529
530         void processAttributes(Map<String, AttributeIfc> attributes,
531                 String packageName) {
532             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
533                 String type;
534                 AttributeIfc attributeIfc = attrEntry.getValue();
535
536                 if (attributeIfc instanceof TypedAttribute) {
537                     TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
538                     type = serializeType(typedAttribute.getType());
539                 } else if (attributeIfc instanceof TOAttribute) {
540                     String fullyQualifiedName = FullyQualifiedNameHelper
541                             .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
542
543                     type = fullyQualifiedName;
544                 } else if (attributeIfc instanceof ListAttribute) {  //FIXME: listAttribute might extend TypedAttribute
545                     String fullyQualifiedName = null;
546                     AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
547                             .getInnerAttribute();
548                     if (innerAttr instanceof JavaAttribute) {
549                         fullyQualifiedName = ((JavaAttribute) innerAttr)
550                                 .getType().getFullyQualifiedName();
551                     } else if (innerAttr instanceof TOAttribute) {
552                         fullyQualifiedName = FullyQualifiedNameHelper
553                                 .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
554                     }
555
556                     type = STRING_FULLY_QUALIFIED_NAME.concat("<")
557                             .concat(fullyQualifiedName).concat(">");
558
559                 } else {
560                     throw new UnsupportedOperationException(
561                             "Attribute not supported: "
562                                     + attributeIfc.getClass());
563                 }
564
565                 fields.add(new Field(type, attributeIfc
566                         .getUpperCaseCammelCase()));
567             }
568         }
569
570         List<Field> getFields() {
571             return fields;
572         }
573     }
574
575     private static class AbstractModuleAttributesProcessor {
576
577         private static final String STRING_FULLY_QUALIFIED_NAME = "java.util.List";
578
579         private final List<ModuleField> moduleFields = Lists.newArrayList();
580         private final List<MethodDefinition> methods = Lists.newArrayList();
581
582         void processAttributes(Map<String, AttributeIfc> attributes,
583                 String packageName) {
584             for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
585                 String type;
586                 AttributeIfc attributeIfc = attrEntry.getValue();
587
588                 if (attributeIfc instanceof TypedAttribute) {
589                     TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
590                     type = serializeType(typedAttribute.getType());
591                 } else if (attributeIfc instanceof TOAttribute) {
592                     String fullyQualifiedName = FullyQualifiedNameHelper
593                             .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
594
595                     type = fullyQualifiedName;
596                 } else if (attributeIfc instanceof ListAttribute) {
597                     String fullyQualifiedName = null;
598                     AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
599                             .getInnerAttribute();
600                     if (innerAttr instanceof JavaAttribute) {
601                         fullyQualifiedName = ((JavaAttribute) innerAttr)
602                                 .getType().getFullyQualifiedName();
603                     } else if (innerAttr instanceof TOAttribute) {
604                         fullyQualifiedName = FullyQualifiedNameHelper
605                                 .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
606                     }
607
608                     type = STRING_FULLY_QUALIFIED_NAME.concat("<")
609                             .concat(fullyQualifiedName).concat(">");
610                 } else {
611                     throw new UnsupportedOperationException(
612                             "Attribute not supported: "
613                                     + attributeIfc.getClass());
614                 }
615
616                 boolean isDependency = false;
617                 Dependency dependency = null;
618                 Annotation overrideAnnotation = new Annotation("Override",
619                         Collections.<Parameter> emptyList());
620                 List<Annotation> annotations = Lists
621                         .newArrayList(overrideAnnotation);
622
623                 if (attributeIfc instanceof AbstractDependencyAttribute) {
624                     isDependency = true;
625                     dependency = ((AbstractDependencyAttribute) attributeIfc)
626                             .getDependency();
627                     annotations.add(Annotation
628                             .createRequireIfcAnnotation(dependency.getSie()));
629                 }
630
631                 String varName = BindingGeneratorUtil
632                         .parseToValidParamName(attrEntry.getKey());
633                 moduleFields.add(new ModuleField(type, varName, attributeIfc
634                         .getUpperCaseCammelCase(), attributeIfc
635                         .getNullableDefault(), isDependency, dependency));
636
637                 String getterName = "get"
638                         + attributeIfc.getUpperCaseCammelCase();
639                 MethodDefinition getter = new MethodDefinition(type,
640                         getterName, Collections.<Field> emptyList(),
641                         Lists.newArrayList(overrideAnnotation), "return "
642                                 + varName + ";");
643
644                 String setterName = "set"
645                         + attributeIfc.getUpperCaseCammelCase();
646
647                 if (attributeIfc.getNullableDescription() != null) {
648                     annotations.add(Annotation
649                             .createDescriptionAnnotation(attributeIfc.getNullableDescription()));
650                 }
651
652                 MethodDefinition setter = new MethodDefinition("void",
653                         setterName,
654                         Lists.newArrayList(new Field(type, varName)),
655                         annotations, "this." + varName + " = " + varName + ";");
656                 setter.setJavadoc(attributeIfc.getNullableDescription());
657
658                 methods.add(getter);
659                 methods.add(setter);
660             }
661         }
662
663         List<ModuleField> getModuleFields() {
664             return moduleFields;
665         }
666
667         List<MethodDefinition> getMethods() {
668             return methods;
669         }
670
671     }
672
673 }