View Javadoc
1   /*
2    * #%L
3    * EUGene :: EUGene
4    * %%
5    * Copyright (C) 2004 - 2010 CodeLutin
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as
9    * published by the Free Software Foundation, either version 3 of the
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
20   * #L%
21   */
22  
23  
24  package org.nuiton.eugene;
25  
26  import org.apache.commons.lang3.StringUtils;
27  import org.nuiton.eugene.models.Model;
28  import org.nuiton.eugene.models.extension.tagvalue.TagValueMetadata;
29  import org.nuiton.eugene.models.extension.tagvalue.TagValueUtil;
30  import org.nuiton.eugene.models.extension.tagvalue.WithTagValuesOrStereotypes;
31  import org.nuiton.eugene.models.object.ObjectModel;
32  import org.nuiton.eugene.models.object.ObjectModelAttribute;
33  import org.nuiton.eugene.models.object.ObjectModelClass;
34  import org.nuiton.eugene.models.object.ObjectModelClassifier;
35  import org.nuiton.eugene.models.object.ObjectModelElement;
36  import org.nuiton.eugene.models.object.ObjectModelOperation;
37  import org.nuiton.eugene.models.object.ObjectModelParameter;
38  import org.nuiton.eugene.models.object.SerialVersionUIDBuilder;
39  import org.nuiton.util.StringUtil;
40  
41  import java.io.File;
42  import java.util.ArrayList;
43  import java.util.Collection;
44  import java.util.HashSet;
45  import java.util.List;
46  import java.util.Set;
47  
48  /**
49   * GeneratorUtil.
50   *
51   * Created: 25 aout 2003
52   *
53   * @author Benjamin Poussin - poussin@codelutin.com
54   */
55  public class GeneratorUtil {
56  
57      public static final String SERIAL_VERSION_UID = "serialVersionUID";
58  
59      /**
60       * return parent package of given package (return given package if it is a root package)
61       * eg : org.nuiton.eugene.models -&gt; org.nuiton.eugene
62       * eg : org -&gt; org
63       * warning : org.nuiton.eugene. -&gt; org.nuiton.eugene
64       *
65       * @param packageName package
66       * @return parent package of given package
67       */
68      public static String getParentPackageName(String packageName) {
69          String parentPackageName = packageName;
70          int index = packageName.lastIndexOf('.');
71          if (index != -1) {
72              parentPackageName = packageName.substring(0, index);
73          }
74          return parentPackageName;
75      }
76  
77      /**
78       * @param qualifiedName the fully qualified name to test
79       * @return class name  fr given fully qualified name (return given name if it is not fully qualified)
80       * eg : org.nuiton.eugene.models.ObjectClass -&gt; ObjectClass
81       * eg : ObjectClass-&gt; ObjectClass
82       */
83      public static String getClassNameFromQualifiedName(String qualifiedName) {
84          String className = qualifiedName;
85          int index = qualifiedName.lastIndexOf('.');
86          if (index != -1) {
87              className = qualifiedName.substring(index + 1);
88          }
89          return className;
90      }
91  
92      /**
93       * @param qualifiedName the fully qualified name to test
94       * @return the filename for the given qualified name.
95       */
96      public static String getFilenameFromQualifiedName(String qualifiedName) {
97          return qualifiedName.replace('.', File.separatorChar);
98      }
99  
100     /**
101      * return all classifiers belonging to the given package recursively. The Collection may be empty.
102      *
103      * @param model       the model where to look at
104      * @param packageName the package name to set for classifiers
105      * @return a Collection containing all classifiers belonging to the given package recursively.
106      * @see ObjectModelClassifier
107      */
108     public static Collection<ObjectModelClassifier> getClassifiers(
109             ObjectModel model, String packageName) {
110         List<ObjectModelClassifier> classifiers = new ArrayList<>();
111         for (ObjectModelClassifier classifier : model.getClassifiers()) {
112             if (classifier.getPackageName().startsWith(packageName)) {
113                 classifiers.add(classifier);
114             }
115         }
116         return classifiers;
117     }
118 
119     /**
120      * Indicates if the specified attribute has a primitive type (byte, boolean, ...)
121      *
122      * @param attribute the attribute to test
123      * @return true if the attribute has a primitive type
124      */
125     public static boolean isPrimitiveAttributeType(
126             ObjectModelAttribute attribute) {
127         if (isNMultiplicity(attribute)) {
128             return false;
129         }
130         String type = attribute.getType();
131         return isPrimitiveType(type);
132 //        return "byte".equals(type) || "short".equals(type)
133 //               || "int".equals(type) || "long".equals(type)
134 //               || "float".equals(type) || "double".equals(type)
135 //               || "char".equals(type) || "boolean".equals(type);
136     }
137 
138     /**
139      * Tests if the given type is a primitive type.
140      *
141      * @param type the type to test
142      * @return {@code true} if given type is primitive.
143      * @since 2.3.2
144      */
145     public static boolean isPrimitiveType(String type) {
146         return "byte".equals(type) || "short".equals(type)
147                || "int".equals(type) || "long".equals(type)
148                || "float".equals(type) || "double".equals(type)
149                || "char".equals(type) || "boolean".equals(type);
150     }
151 
152     /**
153      * @param type primitive type
154      * @return the wrap primitive type
155      * @since 3.0
156      */
157     public static String getPrimitiveWrapType(String type) {
158         if ("byte".equals(type)) {
159             return "Byte";
160         }
161         if ("short".equals(type)) {
162             return "Short";
163         }
164         if ("int".equals(type)) {
165             return "Integer";
166         }
167         if ("long".equals(type)) {
168             return "Long";
169         }
170         if ("float".equals(type)) {
171             return "Float";
172         }
173         if ("double".equals(type)) {
174             return "Double";
175         }
176         if ("char".equals(type)) {
177             return "Character";
178         }
179         if ("boolean".equals(type)) {
180             return "Boolean";
181         }
182 
183         return null;
184     }
185 
186     /**
187      * return an init value for the specified attribute
188      *
189      * @param attribute the attribute to test
190      * @return a String with the corresponding attribute init value
191      */
192     public static String getInitValue(ObjectModelAttribute attribute) {
193         if (isNMultiplicity(attribute)) {
194             return "new java.util.ArrayList()";
195         }
196         return getInitValue(attribute.getType());
197     }
198 
199     public static String getInitValue(String type) {
200         if ("byte".equals(type)) {
201             return "0";
202         }
203         if ("short".equals(type)) {
204             return "0";
205         }
206         if ("int".equals(type)) {
207             return "0";
208         }
209         if ("long".equals(type)) {
210             return "0";
211         }
212         if ("float".equals(type)) {
213             return "0";
214         }
215         if ("double".equals(type)) {
216             return "0";
217         }
218         if ("char".equals(type)) {
219             return "\u0000";
220         }
221         if ("boolean".equals(type)) {
222             return "false";
223         }
224         if ("java.lang.String".equals(type)) {
225             return null;
226         }
227         if ("java.lang.Date".equals(type)) {
228             return null;
229         }
230         return null;
231     }
232 
233     public static String getCastValue(String type, String o) {
234         if ("byte".equals(type)) {
235             return "((Byte)" + o + ").byteValue()";
236         }
237         if ("short".equals(type)) {
238             return "((Short)" + o + ").shortValue()";
239         }
240         if ("int".equals(type)) {
241             return "((Integer)" + o + ").intValue()";
242         }
243         if ("long".equals(type)) {
244             return "((Long)" + o + ").longValue()";
245         }
246         if ("float".equals(type)) {
247             return "((Float)" + o + ").floatValue()";
248         }
249         if ("double".equals(type)) {
250             return "((Double)" + o + ").doubleValue()";
251         }
252         if ("char".equals(type)) {
253             return "((Character)" + o + ").charValue()";
254         }
255         if ("boolean".equals(type)) {
256             return "((Boolean)" + o + ").booleanValue()";
257         }
258         if ("void".equals(type)) {
259             return "";
260         }
261         return "(" + type + ")" + o;
262     }
263 
264     public static String getHashCodeExpression(String type, String o) {
265         String result = o;
266         if ("byte".equals(type)) {
267             result = "new Byte(" + o + ")";
268         }
269         if ("short".equals(type)) {
270             result = "new Short(" + o + ")";
271         }
272         if ("int".equals(type)) {
273             result = "new Integer(" + o + ")";
274         }
275         if ("long".equals(type)) {
276             result = "new Long(" + o + ")";
277         }
278         if ("float".equals(type)) {
279             result = "new Float(" + o + ")";
280         }
281         if ("double".equals(type)) {
282             result = "new Double(" + o + ")";
283         }
284         if ("char".equals(type)) {
285             result = "new Character(" + o + ")";
286         }
287         if ("boolean".equals(type)) {
288             result = "new Boolean(" + o + ")";
289         }
290         return result + ".hashCode()";
291     }
292 
293     /**
294      * @param attribute the attribute to test
295      * @return vrai si la cardinalite de l'attribut est superieur a 1, c-a-d
296      * si MaxMultiplicity == -1 ou &gt; 1
297      */
298     public static boolean isNMultiplicity(ObjectModelAttribute attribute) {
299         return isNMultiplicity(attribute.getMaxMultiplicity());
300     }
301 
302     public static boolean isNMultiplicity(int multiplicity) {
303         return multiplicity == -1 || multiplicity > 1;
304     }
305 
306     /**
307      * @param attribute the attribute to test
308      * @return true is the multiplicity of the given attribute is exactly 1
309      */
310     public static boolean isOneMultiplicity(ObjectModelAttribute attribute) {
311         return attribute != null && attribute.getMinMultiplicity() == 1 &&
312                attribute.getMaxMultiplicity() == 1;
313     }
314 
315     /**
316      * @param word the word to decapitalize
317      * @return the decapitalized word
318      */
319     public static String toLowerCaseFirstLetter(String word) {
320         return word.substring(0, 1).toLowerCase() + word.substring(1);
321     }
322 
323     /**
324      * @param attribute the attribute to test
325      * @return true if the given attribute is a composition (composant of the reverse attribute)
326      */
327     public static boolean isComposition(ObjectModelAttribute attribute) {
328 
329         boolean composition = false;
330         if (attribute != null && attribute.getReverseAttribute() != null) {
331             composition = attribute.getReverseAttribute().isComposite();
332         }
333         return composition;
334     }
335 
336     /**
337      * Tests if an attribute is a boolean primitive.
338      *
339      * @param attribute the attribute to test
340      * @return {@code true} if attribute is a primitive boolean
341      * @since 2.4.1
342      */
343     public static boolean isBooleanPrimitive(ObjectModelAttribute attribute) {
344         String type = attribute.getType();
345         return isBooleanPrimitive(type);
346     }
347 
348     /**
349      * Tests if an type is a boolean primitive.
350      *
351      * @param type the type to test
352      * @return {@code true} if type is a primitive boolean
353      * @since 2.11
354      */
355     public static boolean isBooleanPrimitive(String type) {
356         return "boolean".equals(type);
357     }
358 
359     public static String getParsingExpression(String type,
360                                               String attributeStringName) {
361         if ("byte".equals(type)) {
362             return "Byte.parseByte(" + attributeStringName + ")";
363         }
364         if ("short".equals(type)) {
365             return "Short.parseShort(" + attributeStringName + ")";
366         }
367         if ("int".equals(type)) {
368             return "Integer.parseInt(" + attributeStringName + ")";
369         }
370         if ("long".equals(type)) {
371             return "Long.parseLong(" + attributeStringName + ")";
372         }
373         if ("float".equals(type)) {
374             return "Float.parseFloat(" + attributeStringName + ")";
375         }
376         if ("double".equals(type)) {
377             return "Double.parseDouble(" + attributeStringName + ")";
378         }
379         if ("char".equals(type)) {
380             return attributeStringName + ".charAt(0)";
381         }
382         if ("boolean".equals(type)) {
383             return "Boolean.parseBoolean(" + attributeStringName + ")";
384         }
385         if ("java.lang.String".equals(type)) {
386             return attributeStringName;
387         }
388         if ("java.util.Date".equals(type)) {
389             return "dateParser.parse(" + attributeStringName + ")";
390         }
391         return null;
392     }
393 
394     public static String getFormatingExpression(String type,
395                                                 String attributeStringName) {
396         if ("byte".equals(type)) {
397             return "Byte.toString(" + attributeStringName + ")";
398         }
399         if ("short".equals(type)) {
400             return "Short.toString(" + attributeStringName + ")";
401         }
402         if ("int".equals(type)) {
403             return "Integer.toString(" + attributeStringName + ")";
404         }
405         if ("long".equals(type)) {
406             return "Long.toString(" + attributeStringName + ")";
407         }
408         if ("float".equals(type)) {
409             return "Float.toString(" + attributeStringName + ")";
410         }
411         if ("double".equals(type)) {
412             return "Double.toString(" + attributeStringName + ")";
413         }
414         if ("char".equals(type)) {
415             return "Character.toString(" + attributeStringName + ")";
416         }
417         if ("boolean".equals(type)) {
418             return "Boolean.parseBoolean(" + attributeStringName + ")";
419         }
420         if ("java.lang.String".equals(type)) {
421             return attributeStringName;
422         }
423         if ("java.util.Date".equals(type)) {
424             return "dateParser.format(" + attributeStringName + ")";
425         }
426         return null;
427     }
428 
429     /**
430      * ToString contract for ObjectModelParameter with name only. This contract
431      * is used in
432      * {@link StringUtil#join(Iterable, org.nuiton.util.StringUtil.ToString, String, boolean)}
433      */
434     static final StringUtil.ToString<ObjectModelParameter>
435             OBJECT_MODEL_PARAMETER_TO_STRING_NAME =
436             new StringUtil.ToString<ObjectModelParameter>() {
437 
438                 @Override
439                 public String toString(ObjectModelParameter param) {
440                     return param.getName();
441                 }
442             };
443 
444     /**
445      * Used to return the {@code operation} parameter names as a string
446      * separated by a comma. Usefull for operation call in templates writing.
447      *
448      * @param operation to treate
449      * @return the string corresponding to the list of operation parameter
450      * names separated by a ', '.
451      */
452     public static String getOperationParametersListName(
453             ObjectModelOperation operation) {
454         String result = StringUtil.join(
455                 operation.getParameters(),
456                 OBJECT_MODEL_PARAMETER_TO_STRING_NAME,
457                 ", ",
458                 false);
459         return result;
460     }
461 
462     /**
463      * Renvoie si l'attribut passé en paramètre est premier lexicographiquement
464      * par rapport à son attribut inverse (si celui ci existe).
465      *
466      * @param attr L'attribut dont on veut savoir s'il est le premier
467      * @return true, si l'attribut est premier (lexico ou pas de reverse attribute), false dans les autres cas
468      */
469     public static boolean isFirstAttribute(ObjectModelAttribute attr) {
470         boolean firstAttribute = true;
471         if (attr.getReverseAttribute() != null) {
472             firstAttribute = attr.getName().compareTo(
473                     attr.getReverseAttribute().getName()) < 0;
474         }
475         return firstAttribute;
476     }
477 
478     /**
479      * Indique si l'élément spécifié dispose de documentation
480      *
481      * @param element l'élément à tester
482      * @return true s'il y a documentation, false sinon
483      */
484     public static boolean hasDocumentation(ObjectModelElement element) {
485         return StringUtils.isNotEmpty(element.getDocumentation());
486     }
487 
488     /**
489      * Indique si la chaine de caratère n'est pas vide (null ou "")
490      *
491      * @param s la chaine de caractères à tester
492      * @return true si <code>s</code> n'est pas vide
493      * @deprecated since 2.3, use the method {@link StringUtils#isNotEmpty(CharSequence)}
494      */
495     @Deprecated
496     public static boolean notEmpty(String s) {
497         return s != null && !"".equals(s);
498     }
499 
500     /**
501      * Cherches et renvoie la valeur du tagvalue indique sur cet element,
502      * sinon sur le model.
503      *
504      * @param tagName le nom du tag
505      * @param element l'élément à tester
506      * @param model   le modele utilisé
507      * @return la valeur du tagValue ou null
508      * @deprecated since 2.9 (will be remove in version 3.0), prefer use now {@link TagValueUtil#findTagValue(TagValueMetadata, WithTagValuesOrStereotypes...)}
509      */
510     @Deprecated
511     public static String findTagValue(String tagName,
512                                       ObjectModelElement element,
513                                       Model model) {
514         if (element == null) {
515             if (model != null) {
516                 String value = model.getTagValue(tagName);
517                 if (!StringUtils.isEmpty(value)) {
518                     return value;
519                 }
520             }
521             return null;
522         }
523         String value = element.getTagValue(tagName);
524         if (!StringUtils.isEmpty(value)) {
525             return value;
526         }
527         //On va chercher sur l'element declarant
528         return findTagValue(tagName, element.getDeclaringElement(), model);
529     }
530 
531     public static boolean hasStereotype(ObjectModelElement element,
532                                         String stereotype) {
533         return element.hasStereotype(stereotype) ||
534                element.hasStereotype(stereotype.toLowerCase());
535     }
536 
537     /**
538      * For the given class and its attributes, this method computes a
539      * serialVersionUID. Exemple, returns "123456789L".
540      * This id will change only if the type or the order of an attribute
541      * changes.
542      *
543      * @param clazz the class to use
544      * @return the generated serialVersionUID
545      * @deprecated since 2.4, prefer use the method {@link #generateSerialVersionUID(ObjectModelClassifier)}
546      */
547     @Deprecated
548     public static String computeSerialVersionUID(ObjectModelClass clazz) {
549         String query = clazz.getQualifiedName() + "#";
550         for (ObjectModelAttribute attr : clazz.getAttributes()) {
551             query += "-" + attr.getType();
552         }
553         String result = query.hashCode() + "L";
554         return result;
555     }
556 
557 
558     /**
559      * Suppress packageName from a fullQualifiedName, even if it contains
560      * List, Map or other generics.
561      *
562      * See JUnit test for matching expressions.
563      *
564      * @param str FullQualifiedName for an attribute type (for exemple)
565      * @return the simple name associated to the str given
566      */
567     public static String getSimpleName(String str) {
568         String result = getSimpleName(str, false);
569         return result;
570     }
571 
572     /**
573      * Suppress packageName from a fullQualifiedName, even if it contains List,
574      * Map or other generics.
575      *
576      * See JUnit test for matching expressions.
577      *
578      * @param str                     fullQualifiedName for an attribute type (for exemple)
579      * @param removeGenericDefinition a flag to remove any generic definition at the beginning of the expression
580      * @return the simple name associated to the str given
581      * @since 2.3
582      */
583     public static String getSimpleName(String str, boolean removeGenericDefinition) {
584         if (removeGenericDefinition) {
585             str = removeGenericDefinition(str);
586         }
587         // variable array type
588         boolean variableArrayType = false;
589         if (str.endsWith("...")) {
590             variableArrayType = true;
591             str = str.substring(0, str.length() - 3);
592         }
593         if (str.startsWith("\"") && str.endsWith("\"")) {
594             return str;
595         }
596         //return str.replaceAll("[a-zA-Z]\\w*\\.","");
597         String result = str.replaceAll("\\p{Alpha}\\w*\\.", "");
598         if (variableArrayType) {
599             result += "...";
600         }
601         return result;
602     }
603 
604     /**
605      * Remove any generics definition at the beginning of a string.
606      *
607      * For example :
608      * <pre>
609      * &lt;T&gt; T -&gt; T
610      * </pre>
611      *
612      * @param str the string to parse
613      * @return the string without any
614      * @since 2.3
615      */
616     public static String removeGenericDefinition(String str) {
617 
618         // always trim the string
619         String result = str.trim();
620 
621         if (!result.startsWith("<")) {
622 
623             // not starting by a generics definition, no treatment to do
624             return str;
625         }
626 
627         int i = 0;
628         for (int length = result.length(), count = 0; i < length; i++) {
629             char c = result.charAt(i);
630             if ('<' == c) {
631                 count++;
632             } else if ('>' == c) {
633                 count--;
634             }
635             if (count == 0) {
636                 break;
637             }
638         }
639 
640         // the i position was on the last closing caracter, can safely
641         // remove until this position + 1
642         result = result.substring(i + 1);
643 
644         // remove any starting spaces
645         while (result.startsWith(" ")) {
646             result = result.substring(1);
647         }
648         return result;
649     }
650 
651     /**
652      * Remove any generics definition at the beginning of a string.
653      *
654      * For example :
655      * <pre>
656      * &lt;T&gt; T -&gt; T
657      * </pre>
658      *
659      * @param str the string to parse
660      * @return the string without any
661      * @since 2.6.3
662      */
663     public static String removeAnyGenericDefinition(String str) {
664 
665         // always trim the string
666         String result = str.trim();
667 
668         if (!result.contains("<")) {
669 
670             // no generics definition, no treatment to do
671             return str;
672         }
673         result = result.substring(0, result.indexOf('<'));
674         return result;
675     }
676 
677     /**
678      * @param str the string to parse
679      * @return the string without any
680      * @since 2.3.2
681      */
682     public static String[] splitGenericDefinition(String str) {
683 
684         // always trim the string
685         String result = str.trim();
686 
687         if (!result.startsWith("<")) {
688 
689             // not starting by a generics definition, no treatment to do
690             return new String[]{str};
691         }
692 
693         int i = 0;
694         for (int length = result.length(), count = 0; i < length; i++) {
695             char c = result.charAt(i);
696             if ('<' == c) {
697                 count++;
698             } else if ('>' == c) {
699                 count--;
700             }
701             if (count == 0) {
702                 break;
703             }
704         }
705 
706         // the i position was on the last closing caracter, can safely
707         // remove until this position + 1
708         String prefix = result.substring(0, i + 1);
709         String end = result.substring(i + 1);
710 
711         // remove any starting spaces
712         while (end.startsWith(" ")) {
713             end = end.substring(1);
714         }
715         return new String[]{prefix, end};
716     }
717 
718     /**
719      * Parse a fully qualified generic java type, and extract each imbricated types.
720      *
721      * @param str string to parse
722      * @return set of found types
723      */
724     public static Set<String> getTypesList(String str) {
725 
726         Set<String> results = new HashSet<>();
727 
728         // remove extends, super
729         String localStr = str.replaceAll("([\\w\\?]+ extends|[\\w\\?]+ super|new)", "");
730 
731         // replace non java enabled characters
732         localStr = localStr.replaceAll("[^\\w\\.]", " ");
733 
734         // each space separated part is an import
735         String[] strArray = localStr.split("\\s+");
736         for (String strImport : strArray) {
737             String localStrImport = strImport.trim();
738             if (!localStrImport.isEmpty()) {
739                 results.add(localStrImport);
740             }
741         }
742 
743         return results;
744     }
745 
746     /**
747      * Convertit un nom de variable en nom de constante.
748      *
749      * @param variableName le nom de variable a convertir
750      * @return le nom de la constante à partir du nom de la variable
751      */
752     public static String convertVariableNameToConstantName(String variableName) {
753         //TODO Faire des tests pour savoir si variableName est non null et valide
754         //TODO Ameliorer l'algo pour tenir compte des caractères non alpha
755         //TODO pour le moment cela convient, donc...
756         StringBuilder buffer = new StringBuilder();
757         boolean lastCarIsUp = false;
758         for (int i = 0, j = variableName.length(); i < j; i++) {
759             char c = variableName.charAt(i);
760             boolean carIsUp = Character.isUpperCase(c);
761             if (i > 0 && !lastCarIsUp && carIsUp) {
762                 // ajout d'un _
763                 buffer.append('_');
764             }
765             if (carIsUp) {
766                 buffer.append(c);
767             } else {
768                 buffer.append(Character.toUpperCase(c));
769             }
770             lastCarIsUp = carIsUp;
771         }
772         return buffer.toString();
773     }
774 
775     /**
776      * Convertit un nom de constante en nom de variable.
777      *
778      * @param constantName le nom de constante a convertir
779      * @return le nom de la variable à partir du nom de la constante
780      * @since 3.0
781      */
782     public static String convertConstantNameToVariableName(String constantName) {
783         StringBuilder buffer = new StringBuilder();
784         boolean lastCarIsUp = false;
785         for (int i = 0, j = constantName.length(); i < j; i++) {
786             char c = constantName.charAt(i);
787             if ('_' == c) {
788                 lastCarIsUp = true;
789                 continue;
790             }
791             if (lastCarIsUp) {
792                 c = Character.toUpperCase(c);
793                 lastCarIsUp = false;
794             } else {
795                 c = Character.toLowerCase(c);
796             }
797             buffer.append(c);
798         }
799         return buffer.toString();
800     }
801 
802     /**
803      * Renvoie le nom de l'attribut de classe d'association en fonction des cas:
804      * Si l'attribut porte le même nom que le type (extrémité inverse de
805      * l'association), on lui ajoute le nom de la classe d'association
806      *
807      * @param attr l'attribut a traiter
808      * @return le nom de l'attribut de classe d'association
809      * @since 2.0.2
810      */
811     public static String getAssocAttrName(ObjectModelAttribute attr) {
812         String typeName = attr.getType().substring(
813                 attr.getType().lastIndexOf(".") + 1);
814         String result = attr.getName();
815         if (attr.getName().equalsIgnoreCase(typeName)) {
816             result += StringUtils.capitalize(
817                     attr.getAssociationClass().getName());
818         }
819         return result;
820     }
821 
822     /**
823      * Generates the serialVersionUID of the given {@code classifier}.
824      *
825      * @param classifier the classifier
826      * @return the value of the serialVersionUID
827      */
828     public static long generateSerialVersionUID(ObjectModelClassifier classifier) {
829         long result = SerialVersionUIDBuilder.computeDefaultSUID(classifier);
830         return result;
831     }
832 
833 } // GeneratorUtil