View Javadoc
1   /*
2    * #%L
3    * ToPIA :: Persistence
4    * $Id$
5    * $HeadURL$
6    * %%
7    * Copyright (C) 2004 - 2014 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  package org.nuiton.topia.generator;
26  
27  import org.apache.commons.lang3.StringUtils;
28  import org.apache.commons.lang3.builder.ToStringBuilder;
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.codehaus.plexus.component.annotations.Component;
32  import org.nuiton.eugene.GeneratorUtil;
33  import org.nuiton.eugene.Template;
34  import org.nuiton.eugene.java.ObjectModelTransformerToJava;
35  import org.nuiton.eugene.models.object.*;
36  
37  import java.beans.PropertyChangeListener;
38  import java.beans.PropertyChangeSupport;
39  import java.io.Serializable;
40  import java.util.Collection;
41  import java.util.List;
42  
43  
44  /*{generator option: parentheses = false}*/
45  
46  /*{generator option: writeString = +}*/
47  
48  /**
49   * Created: 20 déc. 2009
50   *
51   * @author tchemit &lt;chemit@codelutin.com&gt;
52   * @version $Id$
53   * @since 2.3.0
54   */
55  @Component(role = Template.class, hint = "org.nuiton.topia.generator.DTOTransformer")
56  public class DTOTransformer extends ObjectModelTransformerToJava {
57  
58      /**
59       * Logger
60       */
61      private static final Log log = LogFactory.getLog(DTOTransformer.class);
62  
63      @Override
64      public void transformFromClass(ObjectModelClass clazz) {
65          if (!TopiaGeneratorUtil.hasDtoStereotype(clazz)) {
66              return;
67          }
68          String clazzName = clazz.getName();
69          ObjectModelClass result;
70          result = createClass(clazzName + "DTO", clazz.getPackageName());
71          addImport(result, ToStringBuilder.class);
72          addImport(result, PropertyChangeListener.class);
73  
74          setDocumentation(result, "Implantation DTO pour l'entité " + StringUtils.capitalize(clazzName) + ".");
75          String extendClass = "";
76          for (ObjectModelClass parent : clazz.getSuperclasses()) {
77              extendClass = parent.getQualifiedName() + "DTO";
78              // no multi-inheritance in java
79              break;
80          }
81          if (extendClass.length() > 0) {
82              setSuperClass(result, extendClass);
83          }
84  
85          addInterface(result, Serializable.class);
86          for (ObjectModelInterface parentInterface : clazz.getInterfaces()) {
87              if (TopiaGeneratorUtil.hasDtoStereotype(parentInterface)) {
88                  addInterface(result, parentInterface.getName() + "DTO");
89              } else {
90                  addInterface(result, parentInterface.getName());
91              }
92          }
93  
94          addAttributes(result, clazz);
95  
96          addOperations(result, clazz);
97      }
98  
99      protected void addAttributes(ObjectModelClass result, ObjectModelClass clazz) {
100 
101         String svUID = TopiaGeneratorUtil.findTagValue("dto-serialVersionUID", clazz, model);
102         if (StringUtils.isNotEmpty(svUID)) {
103             addAttribute(result, "serialVersionUID", long.class, svUID, ObjectModelJavaModifier.FINAL, ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
104         }
105 
106         addAttribute(result, "p", PropertyChangeSupport.class, null, ObjectModelJavaModifier.PROTECTED);
107 
108 /*
109 * Définition des attributs
110 */
111         ObjectModelAttribute attr2;
112         for (ObjectModelAttribute attr : clazz.getAttributes()) {
113             ObjectModelAttribute reverse = attr.getReverseAttribute();
114 
115             String attributeName;
116             String attributeType;
117             if (!(attr.isNavigable()
118                     || attr.hasAssociationClass())) {
119                 continue;
120             }
121 
122             String attrName = attr.getName();
123             String attrVisibility = attr.getVisibility();
124             String attrType = attr.getType();
125             if (!GeneratorUtil.isNMultiplicity(attr)) {
126                 if (!attr.hasAssociationClass()) {
127                     if (isDTO(attrType)) {
128                         attrType += "DTO";
129                     }
130                     attributeType = attrType;
131                     attributeName = attrName;
132                 } else {
133                     String assocAttrName = TopiaGeneratorUtil.getAssocAttrName(attr);
134                     attributeType = attr.getAssociationClass().getQualifiedName();
135                     attributeName = GeneratorUtil.toLowerCaseFirstLetter(assocAttrName);
136                 }
137             } else {
138                 if (!attr.hasAssociationClass()) {
139                     String nMultType;
140                     if (attr.isOrdered()) {
141                         nMultType = List.class.getName() + "<";
142                     } else {
143                         nMultType = Collection.class.getName() + "<";
144                     }
145                     nMultType += attrType;
146                     if (isDTO(attrType)) {
147                         nMultType += "DTO";
148                     }
149                     nMultType += ">";
150 
151                     attributeType = nMultType;
152                     attributeName = attrName;
153                 } else {
154                     String assocAttrName = TopiaGeneratorUtil.getAssocAttrName(attr);
155                     String assocClassFQN = attr.getAssociationClass().getQualifiedName();
156                     String nMultType;
157                     if (attr.isOrdered()) {
158                         nMultType = List.class.getName() + "<";
159                     } else {
160                         nMultType = Collection.class.getName() + "<";
161                     }
162                     nMultType += assocClassFQN;
163                     if (isDTO(attrType)) {
164                         nMultType += "DTO";
165                     }
166                     nMultType += ">";
167                     attributeType = nMultType;
168                     attributeName = GeneratorUtil.toLowerCaseFirstLetter(assocAttrName);
169                 }
170             }
171 
172             attr2 = addAttribute(result, attributeName, attributeType, null, ObjectModelJavaModifier.PROTECTED);
173 
174             if (attr2 != null) {
175                 if (TopiaGeneratorUtil.hasDocumentation(attr)) {
176                     setDocumentation(attr2, attr.getDocumentation());
177                 }
178                 String annotation = TopiaGeneratorUtil.getAnnotationTagValue(attr);
179                 if (StringUtils.isNotEmpty(annotation)) {
180                     addAnnotation(result, attr2, annotation);
181                 }
182             }
183         } /* end for*/
184 
185         //Déclaration des attributs d'une classe d'associations
186         if (clazz instanceof ObjectModelAssociationClass) {
187             ObjectModelAssociationClass assoc = (ObjectModelAssociationClass) clazz;
188             for (ObjectModelAttribute attr : assoc.getParticipantsAttributes()) {
189                 if (attr != null) {
190                     String attrName = attr.getName();
191                     String attrVisibility = attr.getVisibility();
192                     String attrType = attr.getType();
193                     if (isDTO(attrType)) {
194                         attrType += "DTO";
195                     }
196                     addAttribute(result, GeneratorUtil.toLowerCaseFirstLetter(attrName), attrType);
197                 }
198             }
199         }
200 
201     }
202 
203     protected void addOperations(ObjectModelClass result, ObjectModelClass clazz) {
204         ObjectModelOperation op;
205         op = addOperation(result, "addPropertyChangeListener", "void", ObjectModelJavaModifier.PUBLIC);
206         addParameter(op, PropertyChangeListener.class, "listener");
207         setOperationBody(op, ""
208 /*{
209         p.addPropertyChangeListener(listener);
210     }*/
211         );
212 
213         op = addOperation(result, "addPropertyChangeListener", "void", ObjectModelJavaModifier.PUBLIC);
214         addParameter(op, String.class, "propertyName");
215         addParameter(op, PropertyChangeListener.class, "listener");
216         setOperationBody(op, ""
217 /*{
218         p.addPropertyChangeListener(propertyName, listener);
219     }*/
220         );
221 
222         op = addOperation(result, "removePropertyChangeListener", "void", ObjectModelJavaModifier.PUBLIC);
223         addParameter(op, PropertyChangeListener.class, "listener");
224         setOperationBody(op, ""
225 /*{
226         p.removePropertyChangeListener(listener);
227     }*/
228         );
229 
230         op = addOperation(result, "removePropertyChangeListener", "void", ObjectModelJavaModifier.PUBLIC);
231         addParameter(op, String.class, "propertyName");
232         addParameter(op, PropertyChangeListener.class, "listener");
233         setOperationBody(op, ""
234 /*{
235         p.removePropertyChangeListener(propertyName, listener);
236     }*/
237         );
238         /*
239          * Définition des getteurs et setteurs
240          */
241         for (ObjectModelAttribute attr : clazz.getAttributes()) {
242 
243             ObjectModelAttribute reverse = attr.getReverseAttribute();
244 
245 //            if (!(attr.isNavigable() || hasUnidirectionalRelationOnAbstractType(reverse, model))) {
246             if (!attr.isNavigable()) {
247                 continue;
248             }
249 
250             String attrName = attr.getName();
251             String attrType = attr.getType();
252             String attrTypeDTO = attr.getType();
253             if (isDTO(attrType)) {
254                 attrTypeDTO += "DTO";
255             }
256 
257             if (!GeneratorUtil.isNMultiplicity(attr)) {
258                 if (!attr.hasAssociationClass()) {
259                     op = addOperation(result, "set" + StringUtils.capitalize(attrName), "void", ObjectModelJavaModifier.PUBLIC);
260                     addParameter(op, attrTypeDTO, "value");
261                     setOperationBody(op, ""
262 /*{
263         <%=attrTypeDTO%> oldValue = this.<%=attrName%>;
264         this.<%=attrName%> = value;
265         p.firePropertyChange("<%=attrName%>", oldValue, value);
266     }*/
267                     );
268 
269                     op = addOperation(result, "get" + StringUtils.capitalize(attrName), attrTypeDTO, ObjectModelJavaModifier.PUBLIC);
270                     setOperationBody(op, ""
271 /*{
272         return <%=attrName%>;
273     }*/
274                     );
275 
276                 } else {
277                     String assocAttrName = TopiaGeneratorUtil.getAssocAttrName(attr);
278                     String assocClassFQN = attr.getAssociationClass().getQualifiedName();
279                     if (log.isTraceEnabled()) {
280                         log.trace("assocAttrName: " + assocAttrName);
281                     }
282                     op = addOperation(result, "set" + StringUtils.capitalize(assocAttrName), "void", ObjectModelJavaModifier.PUBLIC);
283                     addParameter(op, assocClassFQN + "DTO", "association");
284                     setOperationBody(op, ""
285 /*{
286         <%=assocClassFQN%>DTO oldAssocation = this.<%=GeneratorUtil.toLowerCaseFirstLetter(assocAttrName)%>;
287         this.<%=GeneratorUtil.toLowerCaseFirstLetter(assocAttrName)%> = association;
288         p.firePropertyChange("<%=attrName%>", oldAssocation, assocation);
289     }*/
290                     );
291 
292                     op = addOperation(result, "get" + StringUtils.capitalize(assocAttrName), assocClassFQN + "DTO", ObjectModelJavaModifier.PUBLIC);
293                     setOperationBody(op, ""
294 /*{
295         return <%=GeneratorUtil.toLowerCaseFirstLetter(assocAttrName)%>;
296     }*/
297                     );
298                 }
299             } else { //NMultiplicity
300                 if (!attr.hasAssociationClass()) { //Méthodes remplacées par des accesseurs sur les classes d'assoc
301 
302                     String nMultType;
303                     if (attr.isOrdered()) {
304                         nMultType = List.class.getName() + "<" + attrTypeDTO + ">";
305                     } else {
306                         nMultType = Collection.class.getName() + "<" + attrTypeDTO + ">";
307                     }
308                     op = addOperation(result, "set" + StringUtils.capitalize(attrName), "void", ObjectModelJavaModifier.PUBLIC);
309                     addParameter(op, nMultType, "values");
310                     setOperationBody(op, ""
311 /*{
312         <%=nMultType%> oldValues = this.<%=attrName%>;
313         this.<%=attrName%> = values;
314         p.firePropertyChange("<%=attrName%>", oldValues, values);
315     }*/
316                     );
317 
318                     op = addOperation(result, "addChild" + StringUtils.capitalize(attrName), attrTypeDTO, ObjectModelJavaModifier.PUBLIC);
319                     addParameter(op, attrTypeDTO, attrName);
320                     StringBuilder buffercode = new StringBuilder();
321 
322                     buffercode.append(""
323 /*{
324         this.<%=attrName%>.add(<%=attrName%>);
325     }*/
326                     );
327 
328                     if (reverse != null && reverse.isNavigable()) {
329                         String reverseAttrName = reverse.getName();
330                         buffercode.append(""
331 /*{        <%=attrName%>.set<%=StringUtils.capitalize(reverseAttrName)%>(this);
332     }*/
333                         );
334                     }
335                     buffercode.append(""
336 /*{        return <%=attrName%>;
337     }*/
338                     );
339                     setOperationBody(op, buffercode.toString());
340 
341                     op = addOperation(result, "removeChild", "void");
342                     addParameter(op, attrTypeDTO, attrName);
343 
344                     buffercode = new StringBuilder();
345                     buffercode.append(""
346 /*{
347         this.<%=attrName%>.remove(<%=attrName%>);
348     }*/
349                     );
350 
351                     if (reverse != null && reverse.isNavigable()) {
352                         String reverseAttrName = reverse.getName();
353                         buffercode.append(""
354 /*{ 	<%=attrName%>.set<%=StringUtils.capitalize(reverseAttrName)%>(null);
355     }*/
356                         );
357                     }
358                     setOperationBody(op, buffercode.toString());
359 
360                 } else {
361                     String assocAttrName = TopiaGeneratorUtil.getAssocAttrName(attr);
362                     String assocClassFQN = attr.getAssociationClass().getQualifiedName();
363                     String nMultType;
364                     if (attr.isOrdered()) {
365                         nMultType = List.class.getName() + "<" + assocClassFQN + "DTO>";
366                     } else {
367                         nMultType = Collection.class.getName() + "<" + assocClassFQN + "DTO>";
368                     }
369                     if (log.isTraceEnabled()) {
370                         log.trace("assocAttrName: " + assocAttrName);
371                     }
372                     op = addOperation(result, "set" + StringUtils.capitalize(assocAttrName), "void");
373                     addParameter(op, nMultType, "values");
374                     setOperationBody(op, ""
375 /*{
376         <%=nMultType%> oldValues = this.<%=GeneratorUtil.toLowerCaseFirstLetter(assocAttrName)%>;
377         this.<%=GeneratorUtil.toLowerCaseFirstLetter(assocAttrName)%> = values;
378         p.firePropertyChange("<%=attrName%>", oldValues, values);
379     }*/
380                     );
381                 }
382                 if (!attr.hasAssociationClass()) {
383                     String nMultType;
384                     if (attr.isOrdered()) {
385                         nMultType = List.class.getName() + "<" + attrTypeDTO + ">";
386                     } else {
387                         nMultType = Collection.class.getName() + "<" + attrTypeDTO + ">";
388                     }
389                     op = addOperation(result, "get" + StringUtils.capitalize(attrName), nMultType);
390                     setOperationBody(op, ""
391 /*{
392         return this.<%=attrName%>;
393     }*/
394                     );
395                 } else {
396                     String assocAttrName = TopiaGeneratorUtil.getAssocAttrName(attr);
397                     String assocClassFQN = attr.getAssociationClass().getQualifiedName();
398                     String nMultType;
399                     if (attr.isOrdered()) {
400                         nMultType = List.class.getName() + "<" + assocClassFQN + "DTO>";
401                     } else {
402                         nMultType = Collection.class.getName() + "<" + assocClassFQN + "DTO>";
403                     }
404                     if (log.isTraceEnabled()) {
405                         log.trace("assocAttrName: " + assocAttrName);
406                     }
407                     op = addOperation(result, "get" + StringUtils.capitalize(assocAttrName), nMultType);
408                     setOperationBody(op, ""
409 /*{
410         return this.<%=GeneratorUtil.toLowerCaseFirstLetter(assocAttrName)%>;
411     }*/
412                     );
413                 }
414             }
415         }
416 
417         op = addOperation(result, "toString", String.class, ObjectModelJavaModifier.PUBLIC);
418         StringBuilder buffer = new StringBuilder();
419 
420         buffer.append(""
421 /*{
422         String result = new ToStringBuilder(this).
423 }*/
424         );
425 
426         for (Object o : clazz.getAttributes()) {
427             ObjectModelAttribute attr = (ObjectModelAttribute) o;
428             if (!(attr.isNavigable()
429                     || attr.hasAssociationClass())) {
430                 continue;
431             }
432             //FIXME possibilité de boucles (non directes)
433             ObjectModelClass attrEntity = null;
434             if (model.hasClass(attr.getType())) {
435                 attrEntity = model.getClass(attr.getType());
436             }
437             boolean isDTO = attrEntity != null &&
438                             TopiaGeneratorUtil.isEntity(attrEntity); //THIMEL : STEREOTYPE ENTITY ???
439             ObjectModelAttribute reverse = attr.getReverseAttribute();
440             if (isDTO && (reverse == null || !reverse.isNavigable()) && !attr.hasAssociationClass() || !isDTO) {
441                 String attrName = attr.getName();
442                 buffer.append(""
443 /*{            append("<%=attrName%>", this.<%=attrName%>).
444 }*/
445                 );
446             }
447         }
448         buffer.append(""
449 /*{         toString();
450         return result;
451     }*/
452         );
453         setOperationBody(op, buffer.toString());
454     }
455 
456     public boolean isDTO(String type) {
457         ObjectModelClassifier clazz = model.getClassifier(type);
458         return clazz != null && TopiaGeneratorUtil.hasDtoStereotype(clazz);
459     }
460 
461 
462 }
463