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.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.codehaus.plexus.component.annotations.Component;
31  import org.nuiton.eugene.GeneratorUtil;
32  import org.nuiton.eugene.Template;
33  import org.nuiton.eugene.java.ObjectModelTransformerToJava;
34  import org.nuiton.eugene.models.object.ObjectModel;
35  import org.nuiton.eugene.models.object.ObjectModelAssociationClass;
36  import org.nuiton.eugene.models.object.ObjectModelAttribute;
37  import org.nuiton.eugene.models.object.ObjectModelClass;
38  import org.nuiton.eugene.models.object.ObjectModelClassifier;
39  import org.nuiton.eugene.models.object.ObjectModelDependency;
40  import org.nuiton.eugene.models.object.ObjectModelInterface;
41  import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
42  import org.nuiton.eugene.models.object.ObjectModelModifier;
43  import org.nuiton.eugene.models.object.ObjectModelOperation;
44  import org.nuiton.eugene.models.object.ObjectModelParameter;
45  import org.nuiton.topia.TopiaException;
46  import org.nuiton.topia.framework.TopiaContextImplementor;
47  import org.nuiton.topia.persistence.TopiaDAO;
48  import org.nuiton.topia.persistence.TopiaDAOLegacy;
49  import org.nuiton.topia.persistence.TopiaEntity;
50  import org.nuiton.util.StringUtil;
51  
52  import java.security.Permission;
53  import java.util.ArrayList;
54  import java.util.Arrays;
55  import java.util.Collection;
56  import java.util.HashMap;
57  import java.util.HashSet;
58  import java.util.List;
59  import java.util.Map;
60  import java.util.Set;
61  import java.util.TreeMap;
62  import java.util.regex.Matcher;
63  import java.util.regex.Pattern;
64  
65  
66  /*{generator option: parentheses = false}*/
67  /*{generator option: writeString = +}*/
68  
69  /**
70   * Created: 13 déc. 2009
71   *
72   * @author tchemit &lt;chemit@codelutin.com&gt;
73   * @version $Id: DAOAbstractTransformer.java 1960 2010-05-13 17:18:23Z tchemit$
74   * @since 2.3.0
75   * @deprecated 2.5.4, prefer use the transformer {@link EntityDAOTransformer}
76   */
77  @Deprecated
78  @Component(role = Template.class, hint = "org.nuiton.topia.generator.DAOAbstractTransformer")
79  public class DAOAbstractTransformer extends ObjectModelTransformerToJava {
80  
81      /** Logger. */
82      private static final Log log = LogFactory.getLog(
83              DAOAbstractTransformer.class);
84  
85      /** TODO */
86      protected Map<ObjectModelClass, Set<ObjectModelClass>> usages;
87  
88      /**
89       * All entities fqn of the model (used to detect if an attribute is not
90       * an entity).
91       */
92      Set<String> allEntitiesFqn;
93  
94      /**
95       * The class of abstract dao to use.
96       * @since 2.5
97       */
98      protected Class<?> daoImplementation;
99  
100     /**
101      * Map of extra operations for DAO. The key of the map is the qualified
102      * name of the entity relative to the DAO.
103      */
104     Map<String, Collection<ObjectModelOperation>> extraOperations = new HashMap<>();
105 
106     @Override
107     public void transformFromModel(ObjectModel model) {
108 
109         usages = TopiaGeneratorUtil.searchDirectUsages(model);
110         boolean extendLegacyDAO = Boolean.valueOf(model.getTagValue(TopiaTagValues.TAG_USE_LEGACY_DAO));
111         if (extendLegacyDAO) {
112             log.warn("Using a deprecated tag value "+
113                      TopiaTagValues.TAG_USE_LEGACY_DAO+", prefer use the tag value "+TopiaTagValues.TAG_DAO_IMPLEMENTATION);
114             daoImplementation = TopiaDAOLegacy.class;
115         } else {
116             daoImplementation = TopiaGeneratorUtil.getDAOImplementation(model);
117         }
118 
119         List<ObjectModelClass> allEntities = TopiaGeneratorUtil.getEntityClasses(model, true);
120         allEntitiesFqn = new HashSet<String>(allEntities.size());
121         for (ObjectModelClass entity : allEntities) {
122             allEntitiesFqn.add(entity.getQualifiedName());
123         }
124     }
125 
126     @Override
127     public void transformFromInterface(ObjectModelInterface interfacez) {
128         if (!TopiaGeneratorUtil.hasDaoStereotype(interfacez)) {
129             return;
130         }
131 
132         // Extra operations from &lt;&lt;dao&gt;&gt; interfacez
133         collectExtraOperations(interfacez);
134     }
135 
136     /**
137      * EVO #636 : Manage extra operations for DAO from "dao" dependency
138      * between an interface with stereotype &lt;&lt;dao&gt;&gt; (dependency client) and
139      * a class with stereotype &lt;&lt;entity&gt;&gt; (dependency supplier).
140      *
141      * @param interfacez The interface with &lt;&lt;dao&gt;&gt; stereotype
142      */
143     protected void collectExtraOperations(ObjectModelInterface interfacez) {
144         ObjectModelDependency dependency =
145                 interfacez.getDependency(TopiaGeneratorUtil.DEPENDENCIES_DAO);
146 
147         if (dependency == null) {
148             if (log.isWarnEnabled()) {
149                 log.warn("Could not find dependency " +
150                          TopiaGeneratorUtil.DEPENDENCIES_DAO +
151                          " but DAO stereotype was placed on the interface " +
152                          interfacez.getName());
153 
154             }
155             return;
156         }
157         ObjectModelClassifier classifier = dependency.getSupplier();
158 
159         if (TopiaGeneratorUtil.isEntity(classifier)) {
160 
161             // Only direct operations will be used. No need to have more
162             // operations.
163             Collection<ObjectModelOperation> operations =
164                     interfacez.getOperations();
165 
166             if (log.isDebugEnabled()) {
167                 log.debug("add extra operations for DAO");
168             }
169 
170             extraOperations.put(classifier.getQualifiedName(), operations);
171         }
172     }
173 
174     @Override
175     public void transformFromClass(ObjectModelClass clazz) {
176         if (!TopiaGeneratorUtil.isEntity(clazz)) {
177             return;
178         }
179 
180         String clazzName = clazz.getName();
181 
182         ObjectModelClass result = createAbstractClass(
183                 clazzName + "DAOAbstract<E extends " + clazzName + '>',
184                 clazz.getPackageName());
185 
186         // super class
187 
188         String extendClass = "";
189         for (ObjectModelClass parent : clazz.getSuperclasses()) {
190             extendClass = parent.getQualifiedName();
191             if (TopiaGeneratorUtil.isEntity(parent)) {
192                 extendClass += "DAOImpl<E>";
193                 // in java no multi-inheritance
194                 break;
195             }
196         }
197         if (extendClass.length() == 0) {
198             extendClass = daoImplementation.getName() + "<E>";
199         }
200         if (log.isDebugEnabled()) {
201             log.debug("super class = " + extendClass);
202         }
203         setSuperClass(result, extendClass);
204 
205         addInterface(result, TopiaDAO.class.getName() + "<E>");
206 
207         String prefix = getConstantPrefix(clazz);
208         setConstantPrefix(prefix);
209 
210         // imports
211 
212         Collection<ObjectModelOperation> DAOoperations = getDAOOperations(clazz);
213         if (isCollectionNeeded(DAOoperations)) {
214             addImport(result, Collection.class);
215         }
216         if (isSetNeeded(DAOoperations)) {
217             addImport(result, Set.class);
218         }
219         addImport(result, List.class);
220         addImport(result, Arrays.class);
221         addImport(result, TopiaException.class);
222         addImport(result, TopiaContextImplementor.class);
223 
224         boolean enableSecurity = TopiaGeneratorUtil.isClassWithSecurity(clazz);
225 
226         if (enableSecurity) {
227             addImport(result, ArrayList.class);
228             addImport(result, Permission.class);
229             addImport(result, "org.nuiton.topia.taas.entities.TaasAuthorizationImpl");
230             addImport(result, "org.nuiton.topia.taas.jaas.TaasPermission");
231             addImport(result, "org.nuiton.topia.taas.TaasUtil");
232             addImport(result, TopiaDAO.class);
233 
234             //FIXME : how to do static imports ?
235 //import static org.nuiton.topia.taas.TaasUtil.CREATE;
236 //import static org.nuiton.topia.taas.TaasUtil.DELETE;
237 //import static org.nuiton.topia.taas.TaasUtil.LOAD;
238 //import static org.nuiton.topia.taas.TaasUtil.UPDATE;
239         }
240 
241         ObjectModelOperation op;
242 
243         // getEntityClass
244 
245         op = addOperation(result,
246                 "getEntityClass",
247                 "Class<E>",
248                 ObjectModelJavaModifier.PUBLIC);
249         setOperationBody(op, ""
250 /*{
251         return (Class<E>)<%=clazzName%>.class;
252     }*/
253         );
254 
255 
256         generateDAOOperations(result, DAOoperations);
257 
258         generateDelete(clazz, result);
259 
260         generateNaturalId(result, clazz);
261 
262         for (ObjectModelAttribute attr : clazz.getAttributes()) {
263             if (!attr.isNavigable()) {
264                 continue;
265             }
266 
267             if (!GeneratorUtil.isNMultiplicity(attr)) {
268                 generateNoNMultiplicity(clazzName, result, attr, false);
269             } else {
270                 generateNMultiplicity(clazzName, result, attr);
271             }
272         }
273 
274         if (clazz instanceof ObjectModelAssociationClass) {
275             ObjectModelAssociationClass assocClass =
276                     (ObjectModelAssociationClass) clazz;
277             for (ObjectModelAttribute attr : assocClass.getParticipantsAttributes()) {
278                 if (attr != null) {
279                     if (!GeneratorUtil.isNMultiplicity(attr)) {
280                         generateNoNMultiplicity(clazzName, result, attr, true);
281                     } else {
282                         generateNMultiplicity(clazzName, result, attr);
283                     }
284                 }
285             }
286         }
287 
288         if (enableSecurity) {
289 
290             // getRequestPermission
291 
292             op = addOperation(result,
293                     "getRequestPermission",
294                     "List<Permission>",
295                     ObjectModelJavaModifier.PUBLIC);
296             setDocumentation(op, "Retourne les permissions a verifier pour " +
297                     "l'acces a l'entite pour le service Taas");
298             addException(op, TopiaException.class);
299             addParameter(op, String.class, "topiaId");
300             addParameter(op, int.class, "actions");
301             StringBuilder buffer = new StringBuilder();
302             buffer.append(""
303 /*{
304         List<Permission> resultPermissions = new ArrayList<Permission>();
305         if ((actions & TaasUtil.CREATE) == TaasUtil.CREATE) {
306 }*/
307             );
308             buffer.append(generateSecurity(result, clazz,
309                                            TopiaGeneratorUtil.getSecurityCreateTagValue(clazz)));
310             buffer.append(""
311 /*{
312         }
313         if ((actions & TaasUtil.LOAD) == TaasUtil.LOAD) {
314 }*/
315             );
316             buffer.append(generateSecurity(result, clazz,
317                                            TopiaGeneratorUtil.getSecurityLoadTagValue(clazz)));
318             buffer.append(""
319 /*{
320         }
321         if ((actions & TaasUtil.UPDATE) == TaasUtil.UPDATE) {
322 }*/
323             );
324             buffer.append(generateSecurity(result, clazz,
325                                            TopiaGeneratorUtil.getSecurityUpdateTagValue(clazz)));
326             buffer.append(""
327 /*{
328         }
329         if ((actions & TaasUtil.DELETE) == TaasUtil.DELETE) {
330 }*/
331             );
332             buffer.append(generateSecurity(result, clazz,
333                                            TopiaGeneratorUtil.getSecurityDeleteTagValue(clazz)));
334             buffer.append(""
335 /*{
336         }
337         return resultPermissions;
338     }*/
339             );
340 
341             setOperationBody(op, buffer.toString());
342 
343             // THIMEL : Le code suivant doit pouvoir être déplacé dans DAODelegator ?
344 
345             // getRequestPermission
346 
347 
348             op = addOperation(result,
349                     "getRequestPermission",
350                     "List<Permission>",
351                     ObjectModelJavaModifier.PROTECTED);
352             addParameter(op, String.class, "topiaId");
353             addParameter(op, int.class, "actions");
354             addParameter(op, String.class, "query");
355             addParameter(op, Class.class, "daoClass");
356             addException(op, TopiaException.class);
357             setDocumentation(op, "Retourne les permissions a verifier pour " +
358                     "l'acces a l'entite pour le service Taas");
359             setOperationBody(op, ""
360 /*{    TopiaContextImplementor context = getContext();
361     List<String> result = context.findAll(query, "id", topiaId);
362 
363     List<Permission> resultPermissions = new ArrayList<Permission>();
364     for (String topiaIdPermission : result) {
365         TopiaDAO dao = context.getDAO(daoClass);
366         List<Permission> permissions = dao.getRequestPermission(topiaIdPermission, actions);
367         if(permissions != null) {
368             resultPermissions.addAll(permissions);
369         } else {
370             TaasPermission permission = new TaasPermission(topiaIdPermission, actions);
371             resultPermissions.add(permission);
372         }
373     }
374     return resultPermissions;
375     }*/
376             );
377         }
378 
379         Set<ObjectModelClass> usagesForclass = usages.get(clazz);
380         generateFindUsages(clazz, result, usagesForclass);
381     }
382 
383     protected void generateDelete(ObjectModelClass clazz,
384                                 ObjectModelClass result) {
385         ObjectModelOperation op;
386         op = addOperation(result, "delete", "void", ObjectModelJavaModifier.PUBLIC);
387         addException(op, TopiaException.class);
388         addParameter(op, "E", "entity");
389         StringBuilder body = new StringBuilder();
390         String modelName = StringUtils.capitalize(model.getName());
391         String providerFQN = getOutputProperties().getProperty(
392                 PROP_DEFAULT_PACKAGE) + '.' + modelName +
393                 "DAOHelper.getImplementationClass";
394         
395         for (ObjectModelAttribute attr : clazz.getAttributes()) {
396 
397             String attrType = GeneratorUtil.getSimpleName(attr.getType());
398 
399             String reverseAttrName = attr.getReverseAttributeName();
400             ObjectModelAttribute reverse = attr.getReverseAttribute();
401             if (attr.hasAssociationClass() ||
402                 reverse == null || !reverse.isNavigable()) {
403 
404                 // never treate a non reverse and navigable attribute
405                 // never treate an association class attribute
406                 continue;
407             }
408 
409             // at this point we are sure to have a attribute which is
410             // - reverse
411             // - navigable
412             // - not from an association class
413             if (!allEntitiesFqn.contains(attr.getType())) {
414 
415                 // this attribute is not from an entity, don't treate it
416                 if (log.isDebugEnabled()) {
417                     log.debug("[" + result.getName() + "] Skip attribute [" +
418                               attr.getName() + "] with type " + attr.getType());
419                 }
420                 continue;
421             }
422 
423             // At this point, the attribute type is a entity
424             if (GeneratorUtil.isNMultiplicity(attr) &&
425                 GeneratorUtil.isNMultiplicity(reverse)) {
426                 // On doit absolument supprimer pour les relations many-to-many
427                 // le this de la collection de l'autre cote
428 
429                 String attrDBName = TopiaGeneratorUtil.getDbName(attr);
430                 String attrClassifierDBName = TopiaGeneratorUtil.getDbName(attr.getClassifier());
431                 String attrJoinTableName = TopiaGeneratorUtil.getManyToManyTableName(attr);
432                 String attrReverseDBName = TopiaGeneratorUtil.getReverseDbName(attr);
433 
434                 //FIXME_-FC-20100413 Use a TopiaQuery (use HQLin elements)
435 //                // Add DAOHelper
436 //                String daoHelper = modelName + "DAOHelper";
437 //                String daoHelperFQN = getOutputProperties().
438 //                        getProperty(PROP_DEFAULT_PACKAGE) + '.' + daoHelper;
439 //                addImport(result, daoHelperFQN);
440 //
441 //                // Add import for TopiaQuery
442 //                addImport(result, TopiaQuery.class);
443 //
444 //                // Entity DAO and reversePropertyName
445 //                String entityDAO = attrType + "DAO";
446 //                String reverseAttrNameProperty =
447 //                        attrType + "." + getConstantName(reverseAttrName);
448 //
449 //
450 //             <%=entityDAO%> dao = <%=daoHelper%>.get<%=entityDAO%>(getContext());
451 //            TopiaQuery query = dao.createQuery("B").
452 //                    addFrom(entity.getClass(), "A").
453 //                    add("A", entity).
454 //                    addInElements("A", "B." + <%=reverseAttrNameProperty%>);
455 //
456 //            System.out.println("Query : " + query);
457 //            List&lt;&lt;%=attrType%&gt;&gt; list = dao.findAllByQuery(query);
458 
459 
460                 body.append(""
461 /*{
462         {
463             List&lt;&lt;%=attrType%&gt;&gt; list = getContext().getHibernate().createNativeQuery(
464                     "SELECT main.topiaid " +
465                     "from <%=attrClassifierDBName%> main, <%=attrJoinTableName%> secondary " +
466                     "where main.topiaid=secondary.<%=attrDBName%>" +
467                     " and secondary.<%=attrReverseDBName%>='" + entity.getTopiaId() + "'")
468                     .addEntity("main", <%=providerFQN%>(<%=attrType%>.class)).list();
469 
470             for (<%=attrType%> item : list) {
471                 item.remove<%=StringUtils.capitalize(reverseAttrName)%>(entity);
472             }
473         }
474 }*/
475                 );
476             } else if (!GeneratorUtil.isNMultiplicity(reverse)) {
477                 // On doit mettre a null les attributs qui ont cet objet sur les
478                 // autres entites en one-to-*
479                 // TODO peut-etre qu'hibernate est capable de faire ca tout seul ?
480                 // THIMEL: J'ai remplacé reverse.getName() par reverseAttrName sans certitude
481                 builder.addImport(result, attrType);
482                 String attrSimpleType = TopiaGeneratorUtil.getClassNameFromQualifiedName(attrType);
483 
484                 body.append(""
485                         /*{
486                                         {
487                                         List&lt;&lt;%=attrSimpleType%&gt;&gt; list = getContext()
488                                                     .getDAO(<%=attrSimpleType%>.class)
489                                                     .findAllByProperties(<%=attrSimpleType%>.<%=getConstantName(reverseAttrName)%>, entity);
490                                             for (<%=attrSimpleType%> item : list) {
491                                                 item.set<%=StringUtils.capitalize(reverseAttrName)%>(null);
492                         }*/
493                 );
494                 if (attr.isAggregate()) {
495                     body.append(""
496 /*{
497             			getContext().getDAO(<%=attrSimpleType%>.class).delete(item);
498             			//item.delete();
499 }*/
500                     );
501                 }
502                 body.append(""
503 /*{
504                     }
505                 }
506 }*/
507                 );
508 
509             }
510         }
511         body.append(""
512 /*{
513         super.delete(entity);
514     }*/
515         );
516 
517         setOperationBody(op, body.toString());
518     }
519 
520     private void generateFindUsages(ObjectModelClass clazz,
521                                     ObjectModelClass result,
522                                     Set<ObjectModelClass> usagesForclass) {
523 
524         builder.addImport(result, ArrayList.class.getName());
525         builder.addImport(result, Map.class.getName());
526         builder.addImport(result, HashMap.class.getName());
527         builder.addImport(result, TopiaEntity.class.getName());
528 
529         if (clazz instanceof ObjectModelAssociationClass || usagesForclass.isEmpty()) {
530             // not for an association class
531             // just let a null method
532             ObjectModelOperation operation;
533             operation = addOperation(result,
534                     "findUsages",
535                     "<U extends TopiaEntity> List<U>",
536                     ObjectModelJavaModifier.PUBLIC);
537 
538             addParameter(operation, "Class<U>", "type");
539             addParameter(operation, "E", "entity");
540             addException(operation, TopiaException.class);
541             addAnnotation(result, operation, "Override");
542             setOperationBody(operation, ""
543 /*{
544         return new ArrayList<U>();
545     }*/
546             );
547 
548             operation = addOperation(result,
549                     "findAllUsages",
550                     "Map<Class<? extends TopiaEntity>, List<? extends TopiaEntity&gt;&gt;",
551                     ObjectModelJavaModifier.PUBLIC);
552 
553             addParameter(operation, "E", "entity");
554             addException(operation, TopiaException.class);
555             addAnnotation(result, operation, "Override");
556             setOperationBody(operation, ""
557 /*{
558         return new HashMap<Class<? extends TopiaEntity>, List<? extends TopiaEntity&gt;&gt;();
559     }*/
560             );
561 
562             return;
563         }
564         List<ObjectModelClass> allEntities;
565         Map<String, ObjectModelClass> allEntitiesByFQN;
566 
567         allEntities = TopiaGeneratorUtil.getEntityClasses(model, true);
568         allEntitiesByFQN = new TreeMap<String, ObjectModelClass>();
569 
570         // prepare usages map and fill allEntitiesByFQN map
571         for (ObjectModelClass klass : allEntities) {
572             allEntitiesByFQN.put(klass.getQualifiedName(), klass);
573         }
574 
575         ObjectModelOperation operation;
576         operation = addOperation(result,
577                 "findUsages",
578                 "<U extends TopiaEntity> List<U>",
579                 ObjectModelJavaModifier.PUBLIC);
580 
581         addParameter(operation, "Class<U>", "type");
582         addParameter(operation, "E", "entity");
583         addException(operation, TopiaException.class);
584         addAnnotation(result, operation, "Override");
585         StringBuilder buffer = new StringBuilder(300);
586         buffer.append(""
587 /*{
588         List<?> result = new ArrayList();
589         List tmp;
590 }*/
591         );
592 
593         for (ObjectModelClass usageClass : usagesForclass) {
594             String usageType = usageClass.getQualifiedName();
595             builder.addImport(result, usageType);
596             String usageSimpleType =
597                     TopiaGeneratorUtil.getClassNameFromQualifiedName(usageType);
598             String usageSimplePropertyMethod = "findAllBy" + usageSimpleType;
599             String usageCollectionPropertyMethod = "findAllContaining" + usageSimpleType;
600             for (ObjectModelAttribute attr : usageClass.getAttributes()) {
601                 if (!attr.isNavigable()) {
602                     // skip this case
603                     continue;
604                 }
605                 String type;
606                 String attrName = attr.getName();
607                 if (attr.hasAssociationClass()) {
608                     //FIXME-TC20100224 dont known how to do this ?
609                     continue;
610 //                    type = attr.getAssociationClass().getQualifiedName();
611 //                    //FIXME-TC20100224 : this is crazy ??? must find the good name
612 //                    // Perhaps need to make different cases?
613 //                    attrName = attrName + "_" + TopiaGeneratorUtil.toLowerCaseFirstLetter(attr.getAssociationClass().getName());
614                 } else {
615                     type = attr.getType();
616                 }
617                 if (!allEntitiesByFQN.containsKey(type)) {
618                     // not a entity, can skip for this attribute
619                     continue;
620                 }
621                 ObjectModelClass targetEntity = allEntitiesByFQN.get(type);
622 //                if (!type.equals(clazz.getQualifiedName())) {
623                 if (!targetEntity.equals(clazz)) {
624                     // not a good attribute reference
625                     continue;
626                 }
627                 // found something to seek
628 
629                 String methodNameSuffix = StringUtils.capitalize(attrName);
630                 String methodName;
631                 if (TopiaGeneratorUtil.isNMultiplicity(attr)) {
632                     methodName = "findAllContains" + methodNameSuffix;
633                 } else {
634                     methodName = "findAllBy" + methodNameSuffix;
635                 }
636                 String daoName = StringUtils.capitalize(usageSimpleType) + "DAO";
637 
638                 builder.addImport(result, usageClass.getPackageName() + '.' + daoName);
639 
640                 buffer.append(""
641 /*{
642         if (type == <%=usageSimpleType%>.class) {
643             <%=daoName%> dao = (<%=daoName%>)
644                 getContext().getDAO(<%=usageSimpleType%>.class);
645             tmp = dao.<%=methodName%>(entity);
646             result.addAll(tmp);
647         }
648 }*/
649                 );
650             }
651         }
652 
653         buffer.append(""
654 /*{
655         return (List<U>) result;
656     }*/
657         );
658         setOperationBody(operation, buffer.toString());
659 
660         operation = addOperation(result,
661                 "findAllUsages",
662                 "Map<Class<? extends TopiaEntity>, List<? extends TopiaEntity&gt;&gt;",
663                 ObjectModelJavaModifier.PUBLIC);
664 
665         addParameter(operation, "E", "entity");
666         addException(operation, TopiaException.class);
667         addAnnotation(result, operation, "Override");
668 
669         buffer = new StringBuilder(300);
670         buffer.append(""
671 /*{
672         Map<Class<? extends TopiaEntity>,List<? extends TopiaEntity&gt;&gt; result;
673         result = new HashMap<Class<? extends TopiaEntity>, List<? extends TopiaEntity&gt;&gt;(<%=usagesForclass.size()%>);
674         
675         List<? extends TopiaEntity> list;
676 }*/
677         );
678         for (ObjectModelClass usageClass : usagesForclass) {
679 
680             String fqn = usageClass.getName();
681             buffer.append(""
682 /*{
683         list = findUsages(<%=fqn%>.class, entity);
684         if (!list.isEmpty()) {
685             result.put(<%=fqn%>.class, list);
686         }
687 }*/
688             );
689 
690         }
691         buffer.append(""
692 /*{
693         return result;
694     }*/
695         );
696 
697         setOperationBody(operation, buffer.toString());
698     }
699 
700     /**
701      * Generation of DAO operations signatures from class. These operations are
702      * abstract and identified by &lt;&lt;dao&gt;&gt; stereotype in the model. The
703      * developper must defined these methods in the DAOImpl associated to this
704      * DAOAbstract.
705      *
706      * @param result     clazz where to add operations
707      * @param operations operations to generate
708      */
709     private void generateDAOOperations(ObjectModelClass result,
710                                        Collection<ObjectModelOperation>
711                                                operations) {
712         for (ObjectModelOperation op : operations) {
713 
714             //TODO: add to transformer cloneOperation
715 
716             ObjectModelOperation op2;
717             op2 = addOperation(result,
718                     op.getName(),
719                     op.getReturnType(),
720                     ObjectModelJavaModifier.ABSTRACT,
721                     ObjectModelJavaModifier.fromVisibility(op.getVisibility()));
722             setDocumentation(op2, op.getDocumentation());
723 
724             // parameters
725 
726             for (ObjectModelParameter param : op.getParameters()) {
727                 ObjectModelParameter param2 = addParameter(op2,
728                         param.getType(), param.getName());
729                 setDocumentation(param2, param.getDocumentation());
730             }
731 
732             // exceptions 
733             Set<String> exceptions = op.getExceptions();
734             exceptions.add(TopiaException.class.getName());
735             for (String exception : exceptions) {
736                 addException(op2, exception);
737             }
738         }
739     }
740 
741 
742     private String generateSecurity(ObjectModelClass result,
743                                     ObjectModelClass clazz,
744                                     String tagValue) {
745         StringBuilder buffer = new StringBuilder();
746 
747         if (StringUtils.isNotEmpty(tagValue)) {
748             String security = tagValue;
749             Pattern propertiesPattern = Pattern
750                     .compile("((?:[_a-zA-Z0-9]+\\.)+(?:_?[A-Z][_a-zA-Z0-9]*\\.)+)attribute\\.(?:([_a-z0-9][_a-zA-Z0-9]*))#(?:(create|load|update|delete))");
751             String[] valuesSecurity = security.split(":");
752 
753             for (String valueSecurity : valuesSecurity) {
754                 Matcher matcher = propertiesPattern.matcher(valueSecurity);
755                 matcher.find();
756                 // className is fully qualified name of class
757                 String className = matcher.group(1);
758                 className = StringUtil.substring(className, 0, -1); // remove ended
759                 // .
760                 // target is class, attribute or operation
761                 String attributeName = matcher.group(2);
762                 String actions = matcher.group(3).toUpperCase();
763 
764                 String query = "";
765                 String daoClass = "";
766                 if (className.equals(clazz.getQualifiedName())) {
767                     query = "select " + attributeName + ".topiaId from " + clazz.getQualifiedName() + " where topiaId = :id";
768                     daoClass = clazz.getAttribute(attributeName).getClassifier().getQualifiedName();
769                 } else {
770                     query = "select at.topiaId from " + className + " at inner join at." + attributeName + " cl where cl.topiaId = :id";
771                     daoClass = className;
772                 }
773                 buffer.append(""
774 /*{
775               resultPermissions.addAll(getRequestPermission(topiaId,
776                                                             <%=actions%>,
777                                                             "<%=query%>",
778                                                             <%=daoClass%>.class));
779 }*/
780                 );
781             }
782         } else {
783             buffer.append(""
784 /*{            return null;
785     }*/
786             );
787         }
788         return buffer.toString();
789     }
790 
791     protected void generateNoNMultiplicity(String clazzName,
792                                            ObjectModelClass result,
793                                            ObjectModelAttribute attr,
794                                            boolean isAssoc) {
795         String attrName = attr.getName();
796         String attrType = attr.getType();
797         String propertyName = attrName;
798         if (!isAssoc && attr.hasAssociationClass()) {
799             propertyName = TopiaGeneratorUtil.toLowerCaseFirstLetter(
800                     attr.getAssociationClass().getName()) + '.' + propertyName;
801         }
802         ObjectModelOperation op;
803         op = addOperation(result,
804                 "findBy" + StringUtils.capitalize(attrName),
805                 "E",
806                 ObjectModelJavaModifier.PUBLIC);
807         addException(op, TopiaException.class);
808         addParameter(op, attrType, "v");
809         setDocumentation(op, "Retourne le premier élément trouvé ayant comme valeur pour l'attribut " + attrName + " le paramètre.");
810         setOperationBody(op, ""
811 /*{
812         E result = findByProperty(<%=clazzName + "." + getConstantName(propertyName)%>, v);
813         return result;
814     }*/
815         );
816 
817         op = addOperation(result,
818                 "findAllBy" + StringUtils.capitalize(attrName),
819                 "List<E>",
820                 ObjectModelJavaModifier.PUBLIC);
821         addException(op, TopiaException.class);
822         addParameter(op, attrType, "v");
823         setDocumentation(op, "Retourne les éléments ayant comme valeur pour " +
824                 "l'attribut " + attrName + " le paramètre.");
825         setOperationBody(op, ""
826 /*{
827         List<E> result = findAllByProperty(<%=clazzName + "." + getConstantName(propertyName)%>, v);
828         return result;
829     }*/
830         );
831 
832         if (attr.hasAssociationClass()) {
833             String assocClassName = attr.getAssociationClass().getName();
834             String assocClassFQN = attr.getAssociationClass().getQualifiedName();
835             op = addOperation(result,
836                     "findBy" + StringUtils.capitalize(assocClassName),
837                     "E",
838                     ObjectModelJavaModifier.PUBLIC);
839             addException(op, TopiaException.class);
840             addParameter(op, assocClassFQN, "value");
841             setDocumentation(op, "Retourne le premier élément trouvé ayant " +
842                     "comme valeur pour l'attribut " +
843                     TopiaGeneratorUtil.toLowerCaseFirstLetter(assocClassName) +
844                     " le paramètre.");
845             setOperationBody(op, ""
846 /*{
847         E result = findByProperty(<%=clazzName + "." + getConstantName(TopiaGeneratorUtil.toLowerCaseFirstLetter(assocClassName))%>, value);
848         return result;
849     }*/
850             );
851 
852             op = addOperation(result,
853                     "findAllBy" + StringUtils.capitalize(assocClassName),
854                     "List<E>",
855                     ObjectModelJavaModifier.PUBLIC);
856             addException(op, TopiaException.class);
857             addParameter(op, assocClassFQN, "value");
858             setDocumentation(op, "Retourne les éléments ayant comme valeur pour" +
859                     " l'attribut " +
860                     TopiaGeneratorUtil.toLowerCaseFirstLetter(assocClassName) +
861                     " le paramètre.");
862             setOperationBody(op, ""
863 /*{
864         List<E> result = findAllByProperty(<%=clazzName + "." + getConstantName(TopiaGeneratorUtil.toLowerCaseFirstLetter(assocClassName))%>, value);
865         return result;
866     }*/
867             );
868         }
869     }
870 
871     protected void generateNMultiplicity(String clazzName, ObjectModelClass result, ObjectModelAttribute attr) {
872         String attrName = attr.getName();
873         String attrType = attr.getType();
874         if (attr.hasAssociationClass()) {
875             // do nothing for association class, too complex...
876             return;
877         }
878         ObjectModelOperation op;
879         // Since 2.4 do nothing, findContains and findAllContains are not generated anymore
880         op = addOperation(result,
881                     "findContains" + StringUtils.capitalize(attrName),
882                     "E",
883                     ObjectModelJavaModifier.PUBLIC);
884             addException(op, TopiaException.class);
885             addParameter(op, attrType, "v");
886             setDocumentation(op, "Retourne le premier élément ayant comme valeur pour" +
887                     " l'attribut " +
888                     TopiaGeneratorUtil.toLowerCaseFirstLetter(attrName) +
889                     " le paramètre.");
890             setOperationBody(op, ""
891 /*{
892         E result = findContains(<%=clazzName + "." + getConstantName(attrName)%>, v);
893         return result;
894     }*/
895             );
896 
897         op = addOperation(result,
898                     "findAllContains" + StringUtils.capitalize(attrName),
899                     "List<E>",
900                     ObjectModelJavaModifier.PUBLIC);
901             addException(op, TopiaException.class);
902             addParameter(op, attrType, "v");
903             setDocumentation(op, "Retourne les éléments ayant comme valeur pour" +
904                     " l'attribut " +
905                     TopiaGeneratorUtil.toLowerCaseFirstLetter(attrName) +
906                     " le paramètre.");
907             setOperationBody(op, ""
908 /*{
909         List<E> result = findAllContains(<%=clazzName + "." + getConstantName(attrName)%>, v);
910         return result;
911     }*/
912             );
913     }
914 
915     private boolean isCollectionNeeded(
916             Collection<ObjectModelOperation> operations) {
917         return isImportNeeded(operations, "Collection");
918     }
919 
920     private boolean isSetNeeded(Collection<ObjectModelOperation> operations) {
921         return isImportNeeded(operations, "Set");
922     }
923 
924     private boolean isImportNeeded(Collection<ObjectModelOperation> operations,
925                                    String importName) {
926         for (ObjectModelOperation op : operations) {
927             if (op.getReturnType().contains(importName)) {
928                 return true;
929             }
930             for (ObjectModelParameter param : op.getParameters()) {
931                 if (param.getType().contains(importName)) {
932                     return true;
933                 }
934             }
935         }
936         return false;
937     }
938 
939     public Collection<ObjectModelOperation> getDAOOperations(
940             ObjectModelClass clazz) {
941         // Note : this collection will contains extra operations for DAO.
942         // Overriding existing generated methods is not managed yet
943         Collection<ObjectModelOperation> results =
944                 new ArrayList<ObjectModelOperation>();
945 
946         // This code will be deprecated
947         for (ObjectModelOperation op : clazz.getOperations()) {
948             if (TopiaGeneratorUtil.hasDaoStereotype(op)) {
949                 results.add(op);
950             }
951         }
952         // New method : interface dependency
953         Collection<ObjectModelOperation> extra =
954                 extraOperations.get(clazz.getQualifiedName());
955 
956         if (extra != null) {
957             for (ObjectModelOperation op : extra) {
958                 results.add(op);
959             }
960         }
961 
962         return results;
963     }
964 
965     private void generateNaturalId(ObjectModelClass result,
966                                    ObjectModelClass clazz) {
967         Set<ObjectModelAttribute> props =
968                 TopiaGeneratorUtil.getNaturalIdAttributes(clazz);
969 
970         if (!props.isEmpty()) {
971 
972             if (log.isDebugEnabled()) {
973                 log.debug("generateNaturalId for " + props);
974             }
975             ObjectModelOperation findByNaturalId = addOperation(result,
976                     "findByNaturalId", "E", ObjectModelJavaModifier.PUBLIC);
977             addException(findByNaturalId, TopiaException.class);
978 
979             ObjectModelOperation existByNaturalId = addOperation(result,
980                     "existByNaturalId", "boolean", ObjectModelJavaModifier.PUBLIC);
981             addException(existByNaturalId, TopiaException.class);
982 
983             ObjectModelOperation create = addOperation(result,
984                     "create", "E", ObjectModelJavaModifier.PUBLIC);
985             addException(create, TopiaException.class);
986 
987             // used for calling findByProperties in findByNaturalId
988             String searchProperties = "";
989             // used for calling findByNaturalId in existByNaturalId
990             String params = "";
991             String clazzName = clazz.getName();
992             for (ObjectModelAttribute attr : props) {
993                 String propName = attr.getName();
994                 // add property as param in both methods
995                 addParameter(findByNaturalId, attr.getType(), propName);
996                 addParameter(existByNaturalId, attr.getType(), propName);
997                 addParameter(create, attr.getType(), propName);
998 
999                 searchProperties +=
1000                         ", " + clazzName + '.' + getConstantName(propName) +
1001                                 ", " + propName;
1002                 //params += ", " + propName;
1003             }
1004             searchProperties = searchProperties.substring(2);
1005             //params = params.substring(2);
1006 
1007             setOperationBody(findByNaturalId, ""
1008 /*{
1009         return findByProperties(<%=searchProperties%>);
1010     }*/
1011             );
1012 
1013             setOperationBody(existByNaturalId, ""
1014 /*{
1015         return existByProperties(<%=searchProperties%>);
1016     }*/
1017             );
1018 
1019             setOperationBody(create, ""
1020 /*{
1021         return create(<%=searchProperties%>);
1022     }*/
1023             );
1024         }
1025 
1026 
1027     }
1028 }