View Javadoc
1   package org.nuiton.eugene.java;
2   
3   /*
4    * #%L
5    * EUGene :: Java templates
6    * %%
7    * Copyright (C) 2012 - 2015 CodeLutin
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * #L%
23   */
24  
25  /*{generator option: parentheses = false}*/
26  /*{generator option: writeString = +}*/
27  
28  import com.google.common.base.Function;
29  import com.google.common.collect.ImmutableMap;
30  import com.google.common.collect.ImmutableSet;
31  import com.google.common.collect.Lists;
32  import com.google.common.collect.Maps;
33  import org.apache.commons.collections4.CollectionUtils;
34  import org.apache.commons.lang3.StringUtils;
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  import org.codehaus.plexus.component.annotations.Component;
38  import org.nuiton.eugene.GeneratorUtil;
39  import org.nuiton.eugene.Template;
40  import org.nuiton.eugene.models.extension.tagvalue.provider.TagValueMetadatasProvider;
41  import org.nuiton.eugene.models.object.ObjectModel;
42  import org.nuiton.eugene.models.object.ObjectModelAttribute;
43  import org.nuiton.eugene.models.object.ObjectModelClass;
44  import org.nuiton.eugene.models.object.ObjectModelClassifier;
45  import org.nuiton.eugene.models.object.ObjectModelInterface;
46  import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
47  import org.nuiton.eugene.models.object.ObjectModelOperation;
48  import org.nuiton.eugene.models.object.ObjectModelPackage;
49  import org.nuiton.util.beans.Binder;
50  import org.nuiton.util.beans.BinderFactory;
51  
52  import java.beans.PropertyChangeListener;
53  import java.beans.PropertyChangeSupport;
54  import java.io.Serializable;
55  import java.util.ArrayList;
56  import java.util.Collection;
57  import java.util.Collections;
58  import java.util.HashSet;
59  import java.util.List;
60  import java.util.Set;
61  
62  /**
63   * Generates a bean and a helper class around it.
64   *
65   * Generates also a model initializer contract which permits you to interact with all classes of your model.
66   *
67   * For example:
68   * <pre>
69   *     GeneratedBoat
70   *     Boat (extends GeneratedBoat)
71   *     GeneratedBoatHelper
72   *     BoatHelper (extends AbstractBoats)
73   * </pre>
74   *
75   * @author Tony Chemit - chemit@codelutin.com
76   * @since 3.0
77   */
78  @Component(role = Template.class, hint = "org.nuiton.eugene.java.BeanTransformer")
79  public class BeanTransformer extends ObjectModelTransformerToJava {
80  
81      /** Logger. */
82      private static final Log log = LogFactory.getLog(BeanTransformer.class);
83  
84      ImmutableMap<ObjectModelClass, String> classesNameTranslation;
85  
86      ImmutableMap<ObjectModelClass, String> helpersNameTranslation;
87      ImmutableSet<ObjectModelClass> classes;
88  
89      ImmutableSet<ObjectModelClass> helpers;
90      protected boolean useJava8;
91  
92      protected final EugeneJavaTagValues javaTemplatesTagValues;
93      protected final BeanTransformerTagValues beanTagValues;
94  
95      public BeanTransformer() {
96          javaTemplatesTagValues = new EugeneJavaTagValues();
97          beanTagValues = new BeanTransformerTagValues();
98      }
99  
100     @Override
101     public void transformFromModel(ObjectModel model) {
102         super.transformFromModel(model);
103 
104         useJava8 = javaTemplatesTagValues.isUseJava8(model);
105         ImmutableMap.Builder<ObjectModelClass, String> classesNameTranslationBuilder = new ImmutableMap.Builder<>();
106         ImmutableMap.Builder<ObjectModelClass, String> helpersNameTranslationBuilder = new ImmutableMap.Builder<>();
107         ImmutableSet.Builder<ObjectModelClass> classesBuilder = new ImmutableSet.Builder<>();
108         ImmutableSet.Builder<ObjectModelClass> helpersBuilder = new ImmutableSet.Builder<>();
109 
110         for (ObjectModelClass aClass : model.getClasses()) {
111 
112             ObjectModelPackage aPackage = model.getPackage(aClass.getPackageName());
113             if (javaTemplatesTagValues.isBean(aClass, aPackage)) {
114 
115                 classesBuilder.add(aClass);
116 
117                 String classNamePrefix = beanTagValues.getClassNamePrefixTagValue(aClass, aPackage, model);
118                 String classNameSuffix = beanTagValues.getClassNameSuffixTagValue(aClass, aPackage, model);
119 
120                 String generateName = generateName(classNamePrefix, aClass.getName(), classNameSuffix);
121                 classesNameTranslationBuilder.put(aClass, generateName);
122 
123                 boolean canGenerateHelper = beanTagValues.isGenerateHelper(aClass, aPackage, model);
124 
125                 if (canGenerateHelper) {
126 
127                     helpersBuilder.add(aClass);
128 
129                     String helperNamePrefix = beanTagValues.getHelperClassNamePrefixTagValue(aClass, aPackage, model);
130                     String helperNameSuffix = beanTagValues.getHelperClassNameSuffixTagValue(aClass, aPackage, model);
131 
132                     String generateHelperName = generateName(helperNamePrefix, aClass.getName(), helperNameSuffix);
133                     helpersNameTranslationBuilder.put(aClass, generateHelperName);
134 
135                 }
136 
137             }
138         }
139 
140         classes = classesBuilder.build();
141         helpers = helpersBuilder.build();
142         classesNameTranslation = classesNameTranslationBuilder.build();
143         helpersNameTranslation = helpersNameTranslationBuilder.build();
144 
145         ImmutableMap<String, ObjectModelClass> beanClassesByFqn = Maps.uniqueIndex(classes, new Function<ObjectModelClass, String>() {
146 
147             @Override
148             public String apply(ObjectModelClass input) {
149                 return input.getQualifiedName();
150             }
151         });
152         List<String> beanClassesFqn = new ArrayList<>(beanClassesByFqn.keySet());
153         Collections.sort(beanClassesFqn);
154 
155         String defaultPackageName = getDefaultPackageName();
156 
157         String modelBeanInitializeClassName = model.getName() + "ModelInitializer";
158         boolean generateModelInitializer = !getResourcesHelper().isJavaFileInClassPath(defaultPackageName + "." + modelBeanInitializeClassName);
159         if (generateModelInitializer) {
160 
161             ObjectModelInterface anInterface = createInterface(modelBeanInitializeClassName, defaultPackageName);
162 
163             addOperation(anInterface, "start", "void");
164             addOperation(anInterface, "end", "void");
165 
166             for (String fqn : beanClassesFqn) {
167                 ObjectModelClass beanClass = beanClassesByFqn.get(fqn);
168                 String beanName = classesNameTranslation.get(beanClass);
169                 addImport(anInterface, beanName);
170                 addOperation(anInterface, "init" + beanName, "void");
171 
172             }
173         }
174 
175         String modelInitializerRunnerClassName = model.getName() + "ModelInitializerRunner";
176         boolean generateInitializerRunnerClassName = !getResourcesHelper().isJavaFileInClassPath(defaultPackageName + "." + modelInitializerRunnerClassName);
177         if (generateInitializerRunnerClassName) {
178 
179             ObjectModelClass aClass = createClass(modelInitializerRunnerClassName, defaultPackageName);
180 
181             StringBuilder bodyBuilder = new StringBuilder();
182             bodyBuilder.append(""
183 /*{
184         initializer.start();}*/
185             );
186             for (String fqn : beanClassesFqn) {
187                 ObjectModelClass beanClass = beanClassesByFqn.get(fqn);
188                 String beanName = classesNameTranslation.get(beanClass);
189                 addImport(aClass, beanName);
190                 bodyBuilder.append(""
191 /*{
192         initializer.init<%=beanName%>();}*/
193                 );
194 
195             }
196 
197             bodyBuilder.append(""
198 /*{
199         initializer.end();}*/
200             );
201             ObjectModelOperation operation = addOperation(aClass, "init", "void", ObjectModelJavaModifier.STATIC);
202             addParameter(operation, modelBeanInitializeClassName, "initializer");
203             setOperationBody(operation, bodyBuilder.toString());
204         }
205 
206     }
207 
208     @Override
209     public void transformFromClass(ObjectModelClass input) {
210 
211         ObjectModelPackage aPackage = getPackage(input);
212 
213         if (classes.contains(input)) {
214 
215             String prefix = getConstantPrefix(input);
216             setConstantPrefix(prefix);
217 
218             String className = classesNameTranslation.get(input);
219             String generatedClassName = "Generated" + className;
220 
221             boolean generateClass = notFoundInClassPath(input, className);
222             if (generateClass) {
223                 generateClass(input, className, generatedClassName);
224             }
225 
226             boolean generateGeneratedClass = canGenerateAbstractClass(input, generatedClassName);
227             if (generateGeneratedClass) {
228                 generateGeneratedClass(aPackage, input, generatedClassName);
229             }
230 
231             boolean generateHelper = helpers.contains(input);
232             if (generateHelper) {
233 
234                 String helperClassName = helpersNameTranslation.get(input);
235                 String generatedHelperClassName = "Generated" + helperClassName;
236 
237                 if (notFoundInClassPath(input, helperClassName)) {
238 
239                     generateHelper(input, generatedHelperClassName, helperClassName);
240                 }
241 
242                 if (canGenerateAbstractClass(input, generatedHelperClassName)) {
243 
244                     generateGeneratedHelper(aPackage, input, className, generatedHelperClassName);
245                 }
246 
247             }
248 
249         }
250 
251     }
252 
253     protected ObjectModelClass generateClass(ObjectModelClass input,
254                                              String className,
255                                              String abstractClassName) {
256 
257         ObjectModelClass output;
258 
259         if (input.isAbstract()) {
260             output = createAbstractClass(className, input.getPackageName());
261         } else {
262             output = createClass(className, input.getPackageName());
263         }
264 
265         setSuperClass(output, abstractClassName);
266 
267         if (log.isDebugEnabled()) {
268             log.debug("will generate " + output.getQualifiedName());
269         }
270 
271         addSerializable(input, output, true);
272 
273         return output;
274     }
275 
276     protected ObjectModelClass generateGeneratedClass(ObjectModelPackage aPackage,
277                                                       ObjectModelClass input,
278                                                       String className) {
279 
280         String superClass = null;
281 
282         // test if a super class has bean stereotype
283         boolean superClassIsBean = false;
284         Collection<ObjectModelClass> superclasses = input.getSuperclasses();
285         if (CollectionUtils.isNotEmpty(superclasses)) {
286             for (ObjectModelClass superclass : superclasses) {
287                 superClassIsBean = classes.contains(superclass);
288                 if (superClassIsBean) {
289                     superClass = superclass.getPackageName() + "." + classesNameTranslation.get(superclass);
290                     break;
291                 }
292                 superClass = superclass.getQualifiedName();
293             }
294         }
295 
296         if (!superClassIsBean) {
297 
298             // try to find a super class by tag-value
299             superClass = beanTagValues.getSuperClassTagValue(input, aPackage, model);
300             if (superClass != null) {
301 
302                 // will act as if super class is a bean
303                 superClassIsBean = true;
304             }
305         }
306 
307         ObjectModelClass output;
308 
309         output = createAbstractClass(className, input.getPackageName());
310 
311         if (superClass != null) {
312             setSuperClass(output, superClass);
313         }
314         if (log.isDebugEnabled()) {
315             log.debug("will generate " + output.getQualifiedName());
316         }
317 
318         boolean serializableFound;
319 
320         serializableFound = addInterfaces(input, output, null);
321 
322         generateI18nBlockAndConstants(aPackage, input, output);
323 
324         addSerializable(input, output, serializableFound || superClassIsBean);
325 
326         // Get available properties
327         List<ObjectModelAttribute> properties = getProperties(input);
328 
329         boolean usePCS = beanTagValues.isGeneratePropertyChangeSupport(input, aPackage, model);
330         boolean generateBooleanGetMethods = eugeneTagValues.isGenerateBooleanGetMethods(input, aPackage, model);
331         boolean generateNotEmptyCollections = beanTagValues.isGenerateNotEmptyCollections(input, aPackage, model);
332 
333         // Add properties field + javabean methods
334         for (ObjectModelAttribute attr : properties) {
335 
336             createProperty(output,
337                            attr,
338                            usePCS,
339                            generateBooleanGetMethods,
340                            generateNotEmptyCollections);
341         }
342 
343         if (!superClassIsBean) {
344             addDefaultMethodForNoneBeanSuperClass(output, usePCS, properties);
345         }
346         return output;
347     }
348 
349     protected void generateHelper(ObjectModelClass aClass, String abstractClassName, String defaultClassName) {
350 
351         String packageName = aClass.getPackageName();
352 
353         ObjectModelClass output = createClass(defaultClassName, packageName);
354         setSuperClass(output, packageName + "." + abstractClassName);
355         if (log.isDebugEnabled()) {
356             log.debug("will generate " + output.getQualifiedName());
357         }
358 
359     }
360 
361     protected void generateGeneratedHelper(ObjectModelPackage aPackage,
362                                            ObjectModelClass aClass,
363                                            String typeName,
364                                            String abstractClassName) {
365 
366         ObjectModelClass output = createAbstractClass(abstractClassName, aPackage.getName());
367         String superClassName = getGeneratedHelperSuperClassName(aPackage, aClass);
368 
369         if (StringUtils.isNotBlank(superClassName)) {
370             setSuperClass(output, superClassName);
371         }
372 
373         if (log.isDebugEnabled()) {
374             log.debug("will generate " + output.getQualifiedName());
375         }
376 
377         addImport(output, Binder.class);
378         addImport(output, BinderFactory.class);
379 
380         ObjectModelOperation operation = addOperation(
381                 output,
382                 "typeOf" + typeName,
383                 "<BeanType extends " + typeName + "> Class<BeanType>",
384                 ObjectModelJavaModifier.STATIC,
385                 ObjectModelJavaModifier.PUBLIC
386         );
387         setOperationBody(operation, ""
388     /*{
389         return (Class<BeanType>) <%=typeName%>.class;
390     }*/
391         );
392 
393         boolean generateConstructors = beanTagValues.isGenerateHelperConstructors(aClass, aPackage, model) && !aClass.isAbstract();
394         if (generateConstructors) {
395             generateGeneratedHelperConstructors(output, typeName);
396         }
397 
398         generateGeneratedHelperCopyMethods(output, typeName);
399 
400         boolean generatePredicates = beanTagValues.isGenerateHelperPredicates(aClass, aPackage, model);
401         if (generatePredicates) {
402             generateGeneratedHelperPredicates(aClass, output, typeName);
403         }
404 
405         boolean generateFunctions = beanTagValues.isGenerateHelperFunctions(aClass, aPackage, model);
406         if (generateFunctions) {
407             generateGeneratedHelperFunctions(aClass, output, typeName);
408         }
409 
410     }
411 
412     protected void generateGeneratedHelperConstructors(ObjectModelClass output, String typeName) {
413 
414         ObjectModelOperation operation = addOperation(
415                 output,
416                 "new" + typeName,
417                 typeName,
418                 ObjectModelJavaModifier.STATIC,
419                 ObjectModelJavaModifier.PUBLIC
420         );
421         setOperationBody(operation, ""
422     /*{
423         return new <%=typeName%>();
424     }*/
425         );
426 
427         operation = addOperation(
428                 output,
429                 "new" + typeName,
430                 "<BeanType extends " + typeName + "> BeanType",
431                 ObjectModelJavaModifier.STATIC,
432                 ObjectModelJavaModifier.PUBLIC
433         );
434         addParameter(operation, "BeanType", "source");
435         setOperationBody(operation, ""
436     /*{
437         Class<BeanType> sourceType = typeOf<%=typeName%>();
438         Binder<BeanType, BeanType> binder = BinderFactory.newBinder(sourceType);
439         BeanType result = new<%=typeName%>(source, binder);
440         return result;
441     }*/
442         );
443 
444         operation = addOperation(
445                 output,
446                 "new" + typeName,
447                 "<BeanType extends " + typeName + "> BeanType",
448                 ObjectModelJavaModifier.STATIC,
449                 ObjectModelJavaModifier.PUBLIC
450         );
451         addParameter(operation, "BeanType", "source");
452         addParameter(operation, "Binder<BeanType, BeanType>", "binder");
453         setOperationBody(operation, ""
454     /*{
455         BeanType result = (BeanType) new<%=typeName%>();
456         binder.copy(source, result);
457         return result;
458     }*/
459         );
460 
461     }
462 
463     protected void generateGeneratedHelperCopyMethods(ObjectModelClass output, String typeName) {
464 
465         ObjectModelOperation operation = addOperation(
466                 output,
467                 "copy" + typeName,
468                 "<BeanType extends " + typeName + "> void",
469                 ObjectModelJavaModifier.STATIC,
470                 ObjectModelJavaModifier.PUBLIC
471         );
472         addParameter(operation, "BeanType", "source");
473         addParameter(operation, "BeanType", "target");
474         setOperationBody(operation, ""
475     /*{
476         Class<BeanType> sourceType = typeOf<%=typeName%>();
477         Binder<BeanType, BeanType> binder = BinderFactory.newBinder(sourceType);
478         binder.copy(source, target);
479     }*/
480         );
481 
482         operation = addOperation(
483                 output,
484                 "copy" + typeName,
485                 "<BeanType extends " + typeName + "> void",
486                 ObjectModelJavaModifier.STATIC,
487                 ObjectModelJavaModifier.PUBLIC
488         );
489         addParameter(operation, "BeanType", "source");
490         addParameter(operation, "BeanType", "target");
491         addParameter(operation, "Binder<BeanType, BeanType>", "binder");
492         setOperationBody(operation, ""
493     /*{
494         binder.copy(source, target);
495     }*/
496         );
497 
498     }
499 
500     protected void generateGeneratedHelperPredicates(ObjectModelClass input, ObjectModelClass output, String typeName) {
501 
502         boolean atLeastOnePropertyFound = false;
503         for (ObjectModelAttribute attribute : getProperties(input)) {
504 
505             boolean multiple = JavaGeneratorUtil.isNMultiplicity(attribute);
506 
507             if (multiple) {
508                 continue;
509             }
510 
511             atLeastOnePropertyFound = true;
512             String attrName = getAttributeName(attribute);
513             String attrType = getAttributeTypeWithGeneric(attribute);
514             addImport(output, attrType);
515 
516             String simpleType = JavaGeneratorUtil.getSimpleName(attrType);
517 
518             String capitalizeAttrName = JavaGeneratorUtil.capitalizeJavaBeanPropertyName(attrName);
519             String newPreficateMethodName = "new" + capitalizeAttrName + "Predicate";
520 
521             ObjectModelOperation operation;
522 
523 
524             operation = addOperation(
525                     output,
526                     newPreficateMethodName,
527                     "<BeanType extends " + typeName + "> Predicate<BeanType>",
528                     ObjectModelJavaModifier.STATIC,
529                     ObjectModelJavaModifier.PUBLIC
530             );
531             addParameter(operation, simpleType, attrName);
532             String getterName = getGetterName(attribute, attrName);
533 
534             if (useJava8) {
535                 setOperationBody(operation, ""
536     /*{
537         return o -> Objects.equals(<%=attrName%>, o.<%=getterName%>());
538 
539     }*/
540                 );
541             } else {
542                 setOperationBody(operation, ""
543     /*{
544         final <%=simpleType%> $tmp = <%=attrName%>;
545         return new Predicate<BeanType>() {
546 
547             @Override
548             public boolean apply(BeanType input) {
549                 return Objects.equal($tmp, input.<%=getterName%>());
550             }
551         };
552 
553     }*/
554                 );
555             }
556 
557             operation = addOperation(
558                     output,
559                     "filterBy" + capitalizeAttrName,
560                     "<BeanType extends " + typeName + "> List<BeanType>",
561                     ObjectModelJavaModifier.STATIC,
562                     ObjectModelJavaModifier.PUBLIC
563             );
564             addParameter(operation, "Collection<BeanType>", "$source");
565             addParameter(operation, simpleType, attrName);
566 
567             if (useJava8) {
568                 setOperationBody(operation, ""
569     /*{
570         return $source.stream().filter(<%=newPreficateMethodName%>(<%=attrName%>)).collect(Collectors.toList());
571     }*/
572                 );
573             } else {
574                 addImport(output, Collection.class);
575                 addImport(output, List.class);
576                 addImport(output, Lists.class);
577                 setOperationBody(operation, ""
578     /*{
579         return Lists.newArrayList(Iterables.filter($source, <%=newPreficateMethodName%>(<%=attrName%>)));
580     }*/
581                 );
582             }
583         }
584 
585         if (atLeastOnePropertyFound) {
586             if (useJava8) {
587 
588                 addImport(output, Collection.class);
589                 addImport(output, List.class);
590                 addImport(output, "java.util.Objects");
591                 addImport(output, "java.util.function.Predicate");
592                 addImport(output, "java.util.stream.Collectors");
593             } else {
594                 addImport(output, com.google.common.base.Objects.class);
595                 addImport(output, com.google.common.base.Predicate.class);
596                 addImport(output, com.google.common.collect.Iterables.class);
597             }
598             addImport(output, Iterable.class);
599         }
600 
601     }
602 
603     protected void generateGeneratedHelperFunctions(ObjectModelClass input, ObjectModelClass output, String typeName) {
604 
605         boolean atLeastOnePropertyFound = false;
606         for (ObjectModelAttribute attribute : getProperties(input)) {
607 
608             boolean multiple = JavaGeneratorUtil.isNMultiplicity(attribute);
609 
610             if (multiple) {
611                 continue;
612             }
613 
614             atLeastOnePropertyFound = true;
615 
616             String attrName = getAttributeName(attribute);
617             String attrType = getAttributeTypeWithGeneric(attribute);
618             addImport(output, attrType);
619 
620             String simpleType = JavaGeneratorUtil.getSimpleName(attrType);
621             simpleType = wrapPrimitiveType(simpleType);
622             String capitalizeAttrName = JavaGeneratorUtil.capitalizeJavaBeanPropertyName(attrName);
623             String getterName = getGetterName(attribute, attrName);
624 
625             String newFunctionMethodName = "new" + capitalizeAttrName + "Function";
626             String getFunctionMethodName = "get" + capitalizeAttrName + "Function";
627             String functionTypeName = "Function<BeanType, " + simpleType + ">";
628 
629             String functionFieldName = JavaGeneratorUtil.convertVariableNameToConstantName(capitalizeAttrName + "Function");
630             addAttribute(
631                     output,
632                     functionFieldName,
633                     "Function<" + typeName + ", " + simpleType + ">",
634                     useJava8 ? typeName + "::" + getterName : newFunctionMethodName + "()",
635                     ObjectModelJavaModifier.FINAL,
636                     ObjectModelJavaModifier.STATIC,
637                     useJava8 ? ObjectModelJavaModifier.PUBLIC : ObjectModelJavaModifier.PROTECTED
638             );
639 
640             if (!useJava8) {
641                 ObjectModelOperation operation = addOperation(
642                         output,
643                         getFunctionMethodName,
644                         "<BeanType extends " + typeName + "> " + functionTypeName,
645                         ObjectModelJavaModifier.STATIC,
646                         ObjectModelJavaModifier.PUBLIC
647                 );
648 
649 
650                 setOperationBody(operation, ""
651     /*{
652         return (<%=functionTypeName%>) <%=functionFieldName%>;
653 
654     }*/
655                 );
656 
657                 operation = addOperation(
658                         output,
659                         newFunctionMethodName,
660                         "<BeanType extends " + typeName + "> " + functionTypeName,
661                         ObjectModelJavaModifier.STATIC,
662                         ObjectModelJavaModifier.PUBLIC
663                 );
664 
665                 setOperationBody(operation, ""
666 /*{
667     return new <%=functionTypeName%>() {
668 
669         @Override
670         public <%=simpleType%> apply(BeanType input) {
671             return input.<%=getterName%>();
672         }
673     };
674 
675 }*/
676                 );
677             }
678 
679             ObjectModelOperation operation = addOperation(
680                     output,
681                     "uniqueIndexBy" + capitalizeAttrName,
682                     "<BeanType extends " + typeName + "> ImmutableMap<" + simpleType + ", BeanType>",
683                     ObjectModelJavaModifier.STATIC,
684                     ObjectModelJavaModifier.PUBLIC
685             );
686             addParameter(operation, "Iterable<BeanType>", "$source");
687             if (useJava8) {
688                 setOperationBody(operation, ""
689     /*{
690         return Maps.uniqueIndex($source, <%=functionFieldName%>::apply);
691     }*/
692                 );
693             } else {
694                 setOperationBody(operation, ""
695     /*{
696         return Maps.uniqueIndex($source, <%=functionFieldName%>);
697     }*/
698                 );
699             }
700         }
701 
702         if (atLeastOnePropertyFound) {
703             if (useJava8) {
704                 addImport(output, "java.util.function.Function");
705                 addImport(output, "java.util.Objects");
706             } else {
707                 addImport(output, Function.class);
708                 addImport(output, com.google.common.collect.Iterables.class);
709                 addImport(output, com.google.common.base.Objects.class);
710             }
711 
712             addImport(output, ImmutableMap.class);
713             addImport(output, Iterable.class);
714             addImport(output, Maps.class);
715         }
716 
717     }
718 
719     protected String getGeneratedHelperSuperClassName(ObjectModelPackage aPackage, ObjectModelClass aClass) {
720         String superClassName = null;
721 
722         // test if a super class has bean stereotype
723         boolean superClassIsBean = false;
724         Collection<ObjectModelClass> superclasses = aClass.getSuperclasses();
725         if (CollectionUtils.isNotEmpty(superclasses)) {
726             for (ObjectModelClass superclass : superclasses) {
727                 superClassIsBean = helpers.contains(superclass);
728                 if (superClassIsBean) {
729                     superClassName = superclass.getPackageName() + "." + helpersNameTranslation.get(superclass);
730                     break;
731                 }
732                 superClassName = superclass.getQualifiedName();
733             }
734         }
735 
736         if (!superClassIsBean) {
737 
738             // try to find a super class by tag-value
739             superClassName = beanTagValues.getHelperSuperClassTagValue(aClass, aPackage, model);
740 
741         }
742         return superClassName;
743     }
744 
745     protected String getAttributeType(ObjectModelAttribute attr) {
746         String attrType = attr.getType();
747         if (attr.hasAssociationClass()) {
748             attrType = attr.getAssociationClass().getName();
749         }
750         return getAttributeType(attrType);
751     }
752 
753     protected String getAttributeType(String attrType) {
754         if (!JavaGeneratorUtil.isPrimitiveType(attrType)) {
755             boolean hasClass = model.hasClass(attrType);
756             if (hasClass) {
757                 ObjectModelClass attributeClass = model.getClass(attrType);
758                 String attributeType = classesNameTranslation.get(attributeClass);
759                 if (attributeType != null) {
760                     attrType = attributeClass.getPackageName() + "." + attributeType;
761                 }
762             }
763         }
764         return attrType;
765     }
766 
767     protected boolean notFoundInClassPath(ObjectModelClass input, String className) {
768         String fqn = input.getPackageName() + "." + className;
769         boolean inClassPath = getResourcesHelper().isJavaFileInClassPath(fqn);
770         return !inClassPath;
771     }
772 
773     protected void createProperty(ObjectModelClass output,
774                                   ObjectModelAttribute attr,
775                                   boolean usePCS,
776                                   boolean generateBooleanGetMethods,
777                                   boolean generateNotEmptyCollections) {
778 
779         String attrName = getAttributeName(attr);
780         String attrType = getAttributeTypeWithGeneric(attr);
781 
782         boolean multiple = JavaGeneratorUtil.isNMultiplicity(attr);
783 
784         String constantName = getConstantName(attrName);
785         String simpleType = JavaGeneratorUtil.getSimpleName(attrType);
786 
787         if (multiple) {
788 
789             createGetChildMethod(output,
790                                  attrName,
791                                  attrType,
792                                  simpleType
793             );
794 
795             createIsEmptyMethod(output, attrName);
796 
797             createSizeMethod(output, attrName);
798 
799             createAddChildMethod(output,
800                                  attrName,
801                                  attrType,
802                                  constantName,
803                                  usePCS
804             );
805 
806             createAddAllChildrenMethod(output,
807                                        attrName,
808                                        attrType,
809                                        constantName,
810                                        usePCS
811             );
812 
813             createRemoveChildMethod(output,
814                                     attrName,
815                                     attrType,
816                                     constantName,
817                                     usePCS
818             );
819 
820             createRemoveAllChildrenMethod(output,
821                                           attrName,
822                                           attrType,
823                                           constantName,
824                                           usePCS
825             );
826 
827             createContainsChildMethod(output,
828                                       attrName,
829                                       attrType,
830                                       constantName,
831                                       usePCS
832             );
833 
834             createContainsAllChildrenMethod(output,
835                                             attrName,
836                                             attrType,
837                                             constantName
838             );
839 
840             // Change type for Multiple attribute
841             attrType = JavaGeneratorUtil.getAttributeInterfaceType(attr, getAttributeTypeWithGeneric(attr), true);
842             simpleType = JavaGeneratorUtil.getSimpleName(attrType);
843         }
844 
845         boolean booleanProperty = JavaGeneratorUtil.isBooleanPrimitive(attr);
846 
847         if (multiple) {
848 
849             String collectionImplementationType = JavaGeneratorUtil.getAttributeImplementationType(attr, getAttributeTypeWithGeneric(attr), true);
850 
851             // creates a getXXX (multiple) method
852             createGetMethod(output,
853                             attrName,
854                             attrType,
855                             JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX,
856                             generateNotEmptyCollections,
857                             collectionImplementationType
858             );
859 
860         } else {
861 
862             if (booleanProperty) {
863 
864                 // creates a isXXX method
865                 createGetMethod(output,
866                                 attrName,
867                                 attrType,
868                                 JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX
869                 );
870             }
871 
872             if (!booleanProperty || generateBooleanGetMethods) {
873 
874                 // creates a getXXX method
875                 createGetMethod(output,
876                                 attrName,
877                                 attrType,
878                                 JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX
879                 );
880 
881             }
882 
883 
884         }
885 
886         createSetMethod(output,
887                         attrName,
888                         attrType,
889                         simpleType,
890                         constantName,
891                         usePCS
892         );
893 
894         // Add attribute to the class
895         addAttribute(output,
896                      attrName,
897                      attrType,
898                      "",
899                      ObjectModelJavaModifier.PROTECTED
900         );
901 
902     }
903 
904     protected List<ObjectModelAttribute> getProperties(ObjectModelClass input) {
905         List<ObjectModelAttribute> attributes =
906                 (List<ObjectModelAttribute>) input.getAttributes();
907 
908         List<ObjectModelAttribute> attrs =
909                 new ArrayList<>();
910         for (ObjectModelAttribute attr : attributes) {
911             if (attr.isNavigable()) {
912 
913                 // only keep navigable attributes
914                 attrs.add(attr);
915             }
916         }
917         return attrs;
918     }
919 
920     protected void createGetMethod(ObjectModelClass output,
921                                    String attrName,
922                                    String attrType,
923                                    String methodPrefix,
924                                    boolean generateLayzCode,
925                                    String collectionImplementationType) {
926 
927         ObjectModelOperation operation = addOperation(
928                 output,
929                 getJavaBeanMethodName(methodPrefix, attrName),
930                 attrType,
931                 ObjectModelJavaModifier.PUBLIC
932         );
933         if (generateLayzCode) {
934             addImport(output, collectionImplementationType);
935             String implementationSimpleType = JavaGeneratorUtil.getSimpleName(collectionImplementationType);
936             setOperationBody(operation, ""
937 /*{
938     if (<%=attrName%> == null) {
939         <%=attrName%> = new <%=implementationSimpleType%>();
940     }
941     return <%=attrName%>;
942 }*/
943             );
944         } else {
945             setOperationBody(operation, ""
946 /*{
947     return <%=attrName%>;
948 }*/
949             );
950         }
951 
952     }
953 
954     protected void createGetMethod(ObjectModelClass output,
955                                    String attrName,
956                                    String attrType,
957                                    String methodPrefix) {
958 
959         ObjectModelOperation operation = addOperation(
960                 output,
961                 getJavaBeanMethodName(methodPrefix, attrName),
962                 attrType,
963                 ObjectModelJavaModifier.PUBLIC
964         );
965         setOperationBody(operation, ""
966     /*{
967         return <%=attrName%>;
968     }*/
969         );
970     }
971 
972     protected void createGetChildMethod(ObjectModelClass output,
973                                         String attrName,
974                                         String attrType,
975                                         String simpleType) {
976         ObjectModelOperation operation = addOperation(
977                 output,
978                 getJavaBeanMethodName("get", attrName),
979                 attrType,
980                 ObjectModelJavaModifier.PUBLIC
981         );
982         addParameter(operation, "int", "index");
983         setOperationBody(operation, ""
984     /*{
985         <%=simpleType%> o = getChild(<%=attrName%>, index);
986         return o;
987     }*/
988         );
989     }
990 
991     protected void createIsEmptyMethod(ObjectModelClass output,
992                                        String attrName) {
993         ObjectModelOperation operation = addOperation(
994                 output,
995                 getJavaBeanMethodName("is", attrName) + "Empty",
996                 boolean.class,
997                 ObjectModelJavaModifier.PUBLIC
998         );
999         setOperationBody(operation, ""
1000     /*{
1001         return <%=attrName%> == null || <%=attrName%>.isEmpty();
1002     }*/
1003         );
1004     }
1005 
1006     protected void createSizeMethod(ObjectModelClass output,
1007                                     String attrName) {
1008         ObjectModelOperation operation = addOperation(
1009                 output,
1010                 getJavaBeanMethodName("size", attrName),
1011                 int.class,
1012                 ObjectModelJavaModifier.PUBLIC
1013         );
1014         setOperationBody(operation, ""
1015     /*{
1016         return <%=attrName%> == null ? 0 : <%=attrName%>.size();
1017     }*/
1018         );
1019     }
1020 
1021     protected void createAddChildMethod(ObjectModelClass output,
1022                                         String attrName,
1023                                         String attrType,
1024                                         String constantName,
1025                                         boolean usePCS) {
1026         ObjectModelOperation operation = addOperation(
1027                 output,
1028                 getJavaBeanMethodName("add", attrName),
1029                 "void",
1030                 ObjectModelJavaModifier.PUBLIC
1031         );
1032         addParameter(operation, attrType, attrName);
1033 
1034         String methodName = getJavaBeanMethodName("get", attrName);
1035         StringBuilder buffer = new StringBuilder(""
1036     /*{
1037         <%=methodName%>().add(<%=attrName%>);
1038     }*/
1039         );
1040         if (usePCS) {
1041             buffer.append(""
1042     /*{    firePropertyChange(<%=constantName%>, null, <%=attrName%>);
1043     }*/
1044             );
1045         }
1046         setOperationBody(operation, buffer.toString());
1047     }
1048 
1049     protected void createAddAllChildrenMethod(ObjectModelClass output,
1050                                               String attrName,
1051                                               String attrType,
1052                                               String constantName,
1053                                               boolean usePCS) {
1054         ObjectModelOperation operation = addOperation(
1055                 output,
1056                 getJavaBeanMethodName("addAll", attrName),
1057                 "void",
1058                 ObjectModelJavaModifier.PUBLIC
1059         );
1060         addParameter(operation, "java.util.Collection<" + attrType + ">", attrName);
1061 
1062         String methodName = getJavaBeanMethodName("get", attrName);
1063         StringBuilder buffer = new StringBuilder(""
1064     /*{
1065         <%=methodName%>().addAll(<%=attrName%>);
1066     }*/
1067         );
1068         if (usePCS) {
1069             buffer.append(""
1070     /*{    firePropertyChange(<%=constantName%>, null, <%=attrName%>);
1071     }*/
1072             );
1073         }
1074         setOperationBody(operation, buffer.toString());
1075     }
1076 
1077     protected void createRemoveChildMethod(ObjectModelClass output,
1078                                            String attrName,
1079                                            String attrType,
1080                                            String constantName,
1081                                            boolean usePCS) {
1082         ObjectModelOperation operation = addOperation(
1083                 output,
1084                 getJavaBeanMethodName("remove", attrName),
1085                 "boolean",
1086                 ObjectModelJavaModifier.PUBLIC
1087         );
1088         addParameter(operation, attrType, attrName);
1089         String methodName = getJavaBeanMethodName("get", attrName);
1090         StringBuilder buffer = new StringBuilder();
1091         buffer.append(""
1092     /*{
1093         boolean removed = <%=methodName%>().remove(<%=attrName%>);}*/
1094         );
1095 
1096         if (usePCS) {
1097             buffer.append(""
1098     /*{
1099         if (removed) {
1100             firePropertyChange(<%=constantName%>, <%=attrName%>, null);
1101         }}*/
1102             );
1103         }
1104         buffer.append(""
1105     /*{
1106         return removed;
1107     }*/
1108         );
1109         setOperationBody(operation, buffer.toString());
1110     }
1111 
1112     protected void createRemoveAllChildrenMethod(ObjectModelClass output,
1113                                                  String attrName,
1114                                                  String attrType,
1115                                                  String constantName,
1116                                                  boolean usePCS) {
1117 
1118         ObjectModelOperation operation = addOperation(
1119                 output,
1120                 getJavaBeanMethodName("removeAll", attrName),
1121                 "boolean",
1122                 ObjectModelJavaModifier.PUBLIC
1123         );
1124         addParameter(operation, "java.util.Collection<" + attrType + ">", attrName);
1125         StringBuilder buffer = new StringBuilder();
1126         String methodName = getJavaBeanMethodName("get", attrName);
1127         buffer.append(""
1128     /*{
1129         boolean  removed = <%=methodName%>().removeAll(<%=attrName%>);}*/
1130         );
1131 
1132         if (usePCS) {
1133             buffer.append(""
1134     /*{
1135         if (removed) {
1136             firePropertyChange(<%=constantName%>, <%=attrName%>, null);
1137         }}*/
1138             );
1139         }
1140         buffer.append(""
1141     /*{
1142         return removed;
1143     }*/
1144         );
1145         setOperationBody(operation, buffer.toString());
1146     }
1147 
1148     protected void createContainsChildMethod(ObjectModelClass output,
1149                                              String attrName,
1150                                              String attrType,
1151                                              String constantName,
1152                                              boolean usePCS) {
1153 
1154         ObjectModelOperation operation = addOperation(
1155                 output,
1156                 getJavaBeanMethodName("contains", attrName),
1157                 "boolean",
1158                 ObjectModelJavaModifier.PUBLIC
1159         );
1160         addParameter(operation, attrType, attrName);
1161         StringBuilder buffer = new StringBuilder();
1162         String methodName = getJavaBeanMethodName("get", attrName);
1163         buffer.append(""
1164     /*{
1165         boolean contains = <%=methodName%>().contains(<%=attrName%>);
1166         return contains;
1167     }*/
1168         );
1169         setOperationBody(operation, buffer.toString());
1170     }
1171 
1172     protected void createContainsAllChildrenMethod(ObjectModelClass output,
1173                                                    String attrName,
1174                                                    String attrType,
1175                                                    String constantName) {
1176 
1177         ObjectModelOperation operation = addOperation(
1178                 output,
1179                 getJavaBeanMethodName("containsAll", attrName),
1180                 "boolean",
1181                 ObjectModelJavaModifier.PUBLIC
1182         );
1183         addParameter(operation, "java.util.Collection<" + attrType + ">", attrName);
1184         StringBuilder buffer = new StringBuilder();
1185         String methodName = getJavaBeanMethodName("get", attrName);
1186         buffer.append(""
1187     /*{
1188         boolean  contains = <%=methodName%>().containsAll(<%=attrName%>);
1189         return contains;
1190     }*/
1191         );
1192         setOperationBody(operation, buffer.toString());
1193     }
1194 
1195     protected void createSetMethod(ObjectModelClass output,
1196                                    String attrName,
1197                                    String attrType,
1198                                    String simpleType,
1199                                    String constantName,
1200                                    boolean usePCS) {
1201         boolean booleanProperty = GeneratorUtil.isBooleanPrimitive(simpleType);
1202         ObjectModelOperation operation = addOperation(
1203                 output,
1204                 getJavaBeanMethodName("set", attrName),
1205                 "void",
1206                 ObjectModelJavaModifier.PUBLIC
1207         );
1208         addParameter(operation, attrType, attrName);
1209 
1210         if (usePCS) {
1211             String methodPrefix = JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX;
1212             if (booleanProperty) {
1213                 methodPrefix = JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX;
1214             }
1215             String methodName = getJavaBeanMethodName(methodPrefix, attrName);
1216             setOperationBody(operation, ""
1217     /*{
1218         <%=simpleType%> oldValue = <%=methodName%>();
1219         this.<%=attrName%> = <%=attrName%>;
1220         firePropertyChange(<%=constantName%>, oldValue, <%=attrName%>);
1221     }*/
1222             );
1223         } else {
1224             setOperationBody(operation, ""
1225     /*{
1226         this.<%=attrName%> = <%=attrName%>;
1227     }*/
1228             );
1229         }
1230     }
1231 
1232     protected void addSerializable(ObjectModelClass input,
1233                                    ObjectModelClass output,
1234                                    boolean interfaceFound) {
1235         if (!interfaceFound) {
1236             addInterface(output, Serializable.class);
1237         }
1238 
1239         // Generate the serialVersionUID
1240         long serialVersionUID = JavaGeneratorUtil.generateSerialVersionUID(input);
1241 
1242         addConstant(output,
1243                     JavaGeneratorUtil.SERIAL_VERSION_UID,
1244                     "long",
1245                     serialVersionUID + "L",
1246                     ObjectModelJavaModifier.PRIVATE
1247         );
1248     }
1249 
1250     /**
1251      * Add all interfaces defines in input class and returns if
1252      * {@link Serializable} interface was found.
1253      *
1254      * @param input  the input model class to process
1255      * @param output the output generated class
1256      * @return {@code true} if {@link Serializable} was found from input,
1257      * {@code false} otherwise
1258      */
1259     protected boolean addInterfaces(ObjectModelClass input,
1260                                     ObjectModelClassifier output,
1261                                     String extraInterfaceName) {
1262         boolean foundSerializable = false;
1263         Set<String> added = new HashSet<>();
1264         for (ObjectModelInterface parentInterface : input.getInterfaces()) {
1265             String fqn = parentInterface.getQualifiedName();
1266             added.add(fqn);
1267             addInterface(output, fqn);
1268             if (Serializable.class.getName().equals(fqn)) {
1269                 foundSerializable = true;
1270             }
1271         }
1272         if (extraInterfaceName != null && !added.contains(extraInterfaceName)) {
1273             addInterface(output, extraInterfaceName);
1274         }
1275         return foundSerializable;
1276     }
1277 
1278     protected void createPropertyChangeSupport(ObjectModelClass output) {
1279 
1280         addAttribute(output,
1281                      "pcs",
1282                      PropertyChangeSupport.class,
1283                      "new PropertyChangeSupport(this)",
1284                      ObjectModelJavaModifier.PROTECTED,
1285                      ObjectModelJavaModifier.FINAL,
1286                      ObjectModelJavaModifier.TRANSIENT
1287         );
1288 
1289         // Add PropertyListener
1290 
1291         ObjectModelOperation operation;
1292 
1293         operation = addOperation(output,
1294                                  "addPropertyChangeListener",
1295                                  "void",
1296                                  ObjectModelJavaModifier.PUBLIC
1297         );
1298         addParameter(operation, PropertyChangeListener.class, "listener");
1299         setOperationBody(operation, ""
1300     /*{
1301         pcs.addPropertyChangeListener(listener);
1302     }*/
1303         );
1304 
1305         operation = addOperation(output,
1306                                  "addPropertyChangeListener",
1307                                  "void",
1308                                  ObjectModelJavaModifier.PUBLIC
1309         );
1310         addParameter(operation, String.class, "propertyName");
1311         addParameter(operation, PropertyChangeListener.class, "listener");
1312         setOperationBody(operation, ""
1313     /*{
1314         pcs.addPropertyChangeListener(propertyName, listener);
1315     }*/
1316         );
1317 
1318         operation = addOperation(output,
1319                                  "removePropertyChangeListener",
1320                                  "void",
1321                                  ObjectModelJavaModifier.PUBLIC
1322         );
1323         addParameter(operation, PropertyChangeListener.class, "listener");
1324         setOperationBody(operation, ""
1325     /*{
1326         pcs.removePropertyChangeListener(listener);
1327     }*/
1328         );
1329 
1330         operation = addOperation(output,
1331                                  "removePropertyChangeListener",
1332                                  "void",
1333                                  ObjectModelJavaModifier.PUBLIC
1334         );
1335         addParameter(operation, String.class, "propertyName");
1336         addParameter(operation, PropertyChangeListener.class, "listener");
1337         setOperationBody(operation, ""
1338     /*{
1339         pcs.removePropertyChangeListener(propertyName, listener);
1340     }*/
1341         );
1342 
1343         operation = addOperation(output,
1344                                  "firePropertyChange",
1345                                  "void",
1346                                  ObjectModelJavaModifier.PROTECTED
1347         );
1348         addParameter(operation, String.class, "propertyName");
1349         addParameter(operation, Object.class, "oldValue");
1350         addParameter(operation, Object.class, "newValue");
1351         setOperationBody(operation, ""
1352     /*{
1353         pcs.firePropertyChange(propertyName, oldValue, newValue);
1354     }*/
1355         );
1356 
1357         operation = addOperation(output,
1358                                  "firePropertyChange",
1359                                  "void",
1360                                  ObjectModelJavaModifier.PROTECTED
1361         );
1362         addParameter(operation, String.class, "propertyName");
1363         addParameter(operation, Object.class, "newValue");
1364         setOperationBody(operation, ""
1365     /*{
1366         firePropertyChange(propertyName, null, newValue);
1367     }*/
1368         );
1369     }
1370 
1371     protected void createGetChildMethod(ObjectModelClass output) {
1372         ObjectModelOperation getChild = addOperation(
1373                 output,
1374                 "getChild", "<T> T",
1375                 ObjectModelJavaModifier.PROTECTED
1376         );
1377         addImport(output, List.class);
1378 
1379         addParameter(getChild, "java.util.Collection<T>", "childs");
1380         addParameter(getChild, "int", "index");
1381         setOperationBody(getChild, ""
1382 /*{
1383         T result = null;
1384         if (childs != null) {
1385             if (childs instanceof List) {
1386                 if (index < childs.size()) {
1387                     result = ((List<T>) childs).get(index);
1388                 }
1389             } else {
1390                 int i = 0;
1391                 for (T o : childs) {
1392                     if (index == i) {
1393                         result = o;
1394                         break;
1395                     }
1396                     i++;
1397                 }
1398             }
1399         }
1400         return result;
1401 }*/
1402         );
1403     }
1404 
1405     protected void generateI18nBlockAndConstants(ObjectModelPackage aPackage,
1406                                                  ObjectModelClass input,
1407                                                  ObjectModelClassifier output) {
1408 
1409         String i18nPrefix = eugeneTagValues.getI18nPrefixTagValue(input,
1410                                                                   aPackage,
1411                                                                   model);
1412         if (!StringUtils.isEmpty(i18nPrefix)) {
1413             generateI18nBlock(input, output, i18nPrefix);
1414         }
1415 
1416         String prefix = getConstantPrefix(input);
1417 
1418         setConstantPrefix(prefix);
1419 
1420         Set<String> constantNames = addConstantsFromDependency(input, output);
1421 
1422         // Add properties constant
1423         for (ObjectModelAttribute attr : getProperties(input)) {
1424 
1425             createPropertyConstant(output, attr, prefix, constantNames);
1426         }
1427     }
1428 
1429     protected void addDefaultMethodForNoneBeanSuperClass(ObjectModelClass output,
1430                                                          boolean usePCS,
1431                                                          List<ObjectModelAttribute> properties) {
1432 
1433 
1434         if (usePCS) {
1435 
1436             // Add property change support
1437             createPropertyChangeSupport(output);
1438         }
1439 
1440         boolean hasAMultipleProperty = containsMultiple(properties);
1441 
1442         // Add helper operations
1443         if (hasAMultipleProperty) {
1444 
1445             // add getChild methods
1446             createGetChildMethod(output);
1447         }
1448     }
1449 
1450     protected String wrapPrimitiveType(String attrType) {
1451         if (JavaGeneratorUtil.isPrimitiveType(attrType)) {
1452             attrType = JavaGeneratorUtil.getPrimitiveWrapType(attrType);
1453         }
1454         return attrType;
1455     }
1456 
1457     protected String getGetterName(ObjectModelAttribute attribute, String attrName) {
1458         boolean booleanProperty = JavaGeneratorUtil.isBooleanPrimitive(attribute);
1459         String methodPrefix = JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX;
1460         if (booleanProperty) {
1461             methodPrefix = JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX;
1462         }
1463         return getJavaBeanMethodName(methodPrefix, attrName);
1464     }
1465 
1466     protected String generateName(String prefix, String name, String suffix) {
1467         StringBuilder sb = new StringBuilder();
1468         if (StringUtils.isNotEmpty(prefix)) {
1469             sb.append(prefix);
1470         }
1471         sb.append(name);
1472         if (StringUtils.isNotEmpty(suffix)) {
1473             sb.append(suffix);
1474         }
1475         return sb.toString();
1476     }
1477 
1478     protected boolean canGenerateAbstractClass(ObjectModelClass aClass, String abstractClassName) {
1479 
1480         boolean inClassPath = !notFoundInClassPath(aClass, abstractClassName);
1481 
1482         if (inClassPath) {
1483             throw new IllegalStateException(String.format("Can't generate %s, already found in class-path, this is a generated class, you should not ovveride it.\n\nPlease remove it from class path and use the %s class instead.", aClass.getPackageName() + "." + abstractClassName, aClass));
1484         }
1485 
1486         return true;
1487 
1488     }
1489 
1490     protected void createPropertyConstant(ObjectModelClassifier output,
1491                                           ObjectModelAttribute attr,
1492                                           String prefix,
1493                                           Set<String> constantNames) {
1494 
1495         String attrName = getAttributeName(attr);
1496 
1497         String constantName = prefix + builder.getConstantName(attrName);
1498 
1499         if (!constantNames.contains(constantName)) {
1500 
1501             addConstant(output,
1502                         constantName,
1503                         String.class,
1504                         "\"" + attrName + "\"",
1505                         ObjectModelJavaModifier.PUBLIC
1506             );
1507         }
1508     }
1509 
1510     protected String getAttributeName(ObjectModelAttribute attr) {
1511         String attrName = attr.getName();
1512         if (attr.hasAssociationClass()) {
1513             String assocAttrName = JavaGeneratorUtil.getAssocAttrName(attr);
1514             attrName = JavaGeneratorUtil.toLowerCaseFirstLetter(assocAttrName);
1515         }
1516         return attrName;
1517     }
1518 
1519     protected String getAttributeTypeWithGeneric(ObjectModelAttribute attr) {
1520         String attrType = getAttributeType(attr);
1521         String generic = eugeneTagValues.getAttributeGenericTagValue(attr);
1522         if (generic != null) {
1523             attrType += "<" + getAttributeType(generic) + ">";
1524         }
1525         return attrType;
1526     }
1527 
1528     protected boolean containsMultiple(List<ObjectModelAttribute> attributes) {
1529 
1530         boolean result = false;
1531 
1532         for (ObjectModelAttribute attr : attributes) {
1533 
1534             if (JavaGeneratorUtil.isNMultiplicity(attr)) {
1535                 result = true;
1536 
1537                 break;
1538             }
1539 
1540         }
1541         return result;
1542     }
1543 
1544 
1545 }