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  package org.nuiton.eugene.models.object;
24  
25  import org.apache.commons.lang3.StringUtils;
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.nuiton.eugene.AbstractGenerator;
29  import org.nuiton.eugene.MonitorWriter;
30  
31  import java.io.File;
32  import java.io.IOException;
33  import java.io.StringWriter;
34  import java.io.Writer;
35  import java.util.Collection;
36  
37  /**
38   * Pour utiliser ce type de générateur il faut implanter au moins une des trois
39   * méthodes generateFrom... et le getFilenameFor... associé si l'on souhaite un
40   * nom de fichier convenable. Si dans une méthode generateFrom... on utilise pas
41   * le Writer alors aucun fichier n'est généré.
42   *
43   * <pre>
44   *          public String getFilenameForClass(ObjectModelClass clazz){
45   *          return super.getFilenameForClass(Clazz) + &quot;Service.java&quot;;
46   *          }
47   *
48   *          public void generateFromClass(Writer output, ObjectModelClass clazz) throws IOException{
49   *          if(clazz.getType().equals(&quot;service&quot;)){
50   *           / *{
51   *          public class .... {
52   *
53   *          }
54   *          }* /
55   *          }
56   *          }
57   * </pre>
58   *
59   * Le nom de l'argument writer doit absolument etre output et pas autre chose si
60   * vous souhaitez utiliser le processeur
61   * org.codelutin.processor.filters.GeneratorTemplatesFilter pour vous
62   * s'implifier l'écriture des templates.
63   *
64   * Created: 14 mars 2004
65   *
66   * @author Benjamin Poussin - poussin@codelutin.com
67   */
68  public class ObjectModelGenerator extends AbstractGenerator<ObjectModel> {
69  
70      /** Logger for this class. */
71      private static Log log = LogFactory.getLog(ObjectModelGenerator.class);
72  
73      public ObjectModelGenerator() {
74      }
75  
76      public ObjectModelGenerator(AbstractGenerator<ObjectModel> parent) {
77          super(parent);
78      }
79  
80      /**
81       * Par defaut la methode appelle la methode
82       * {@link #generateFromModel(Writer, ObjectModel)} puis boucle sur chaque
83       * class en appelant la m?thode
84       * {@link #generateFromClass(Writer, ObjectModelClass)} puis boucle sur chaque
85       * interface en appelant a méthode
86       * {@link #generateFromInterface(Writer, ObjectModelInterface)} et enfin sur chaque
87       * énumération en appelant la méthode
88       * {@link #generateFromEnumeration(Writer, ObjectModelEnumeration)}
89       * Le nom de fichier est récupérer pour chacun d'eux en appelant la méthode
90       * getFilenameFor.... La methode generateFrom... n'utilise pas le Writer
91       * alors le fichier n'est pas généré, si on l'utilise m?me pour ne rien
92       * écrire alors le fichier sera généré.
93       *
94       * @param model   le modele memoire a utiliser
95       * @param destDir le repertoire ou generer
96       * @throws IOException pour tout pb
97       */
98      @Override
99      public void applyTemplate(ObjectModel model, File destDir) throws IOException {
100 
101         if (StringUtils.isEmpty(model.getName())) {
102             throw new IllegalArgumentException("No name defined on the model");
103         }
104 
105         // generateFromModel
106         this.model = model;
107 
108         String filename = getFilenameForModel(model);
109 
110         // generateFromModel
111         generateFromElement(model, destDir, filename, ObjectModelType.OBJECT_MODEL);
112 
113         // generateFromClassifier
114         generateFromElements(model.getClassifiers(), destDir, ObjectModelType.OBJECT_MODEL_CLASSIFIER);
115 
116         // generateFromInterface
117         generateFromElements(model.getInterfaces(), destDir, ObjectModelType.OBJECT_MODEL_INTERFACE);
118 
119         // generateFromClass
120         generateFromElements(model.getClasses(), destDir, ObjectModelType.OBJECT_MODEL_CLASS);
121 
122         // generateFromEnumeration
123         generateFromElements(model.getEnumerations(), destDir, ObjectModelType.OBJECT_MODEL_ENUMERATION);
124 
125     }
126 
127     /**
128      * Parcours une collection d'éléments pour la génération suivant un type d'éléments.
129      * Types possibles : ObjectModelClassifier, ObjectModelClass, ObjectModelInterface et
130      * ObjectModelEnumeration.
131      * Deux méthodes dépendent du type et peuvent être surchargées :
132      * getFilenameForXXX et generateFromXXX (XXX étant un type prédéfini pour une méthode existante).
133      *
134      * @param elements Collection d'éléments d'un des types ci-dessus
135      * @param destDir  dossier de destination pour le fichier généré
136      * @param type     type explicite d'ObjectModel
137      * @see ObjectModelType
138      */
139     private void generateFromElements(Collection<? extends ObjectModelElement> elements,
140                                       File destDir,
141                                       ObjectModelType type) {
142 
143         for (ObjectModelElement element : elements) {
144             String filename = "";
145             // Filename depends on type of element (Classifier, Class, Interface or Enumeration)
146             switch (type) {
147                 case OBJECT_MODEL_CLASSIFIER:
148                     filename = getFilenameForClassifier((ObjectModelClassifier) element);
149                     break;
150                 case OBJECT_MODEL_INTERFACE:
151                     filename = getFilenameForInterface((ObjectModelInterface) element);
152                     break;
153                 case OBJECT_MODEL_CLASS:
154                     filename = getFilenameForClass((ObjectModelClass) element);
155                     break;
156                 case OBJECT_MODEL_ENUMERATION:
157                     filename = getFilenameForEnumeration((ObjectModelEnumeration) element);
158             }
159 
160             generateFromElement(element, destDir, filename, type);
161         }
162     }
163 
164     /**
165      * Génération pour un élément du modèle (ou le modèle lui-même).
166      * Types possibles : ObjectModel, ObjectModelClassifier, ObjectModelClass,
167      * ObjectModelInterface et ObjectModelEnumeration.
168      * La méthode generateFromXXX dépend du type d'élément et peut être surchargée.
169      *
170      * @param element  element à généré
171      * @param destDir  dossier de destination
172      * @param filename nom du fichier de sortie
173      * @param type     type d'ObjectModel
174      * @see ObjectModelType
175      */
176     protected void generateFromElement(Object element,
177                                        File destDir,
178                                        String filename,
179                                        ObjectModelType type) {
180 
181         // on a maintenant une restriction des elements a generer
182         // c'est à dire un filtrage par package
183         // effectue un appel pour savoir si on a le droit de generer l'element
184         // courant
185         if (canGenerateElement(element)) {
186 
187             File outputFile = getDestinationFile(destDir, filename);
188             if (!isOverwrite() && isNewerThanSource(outputFile)) {
189                 if (isVerbose()) {
190                     if (log.isInfoEnabled()) {
191                         log.info("Will not generate " + outputFile + " (up-to-date).");
192                     }
193                 }
194                 return;
195             }
196             if (!outputFile.exists()) {
197                 if (log.isDebugEnabled()) {
198                     log.debug("not up-to-date " + outputFile.lastModified()
199                               + " <" + outputFile + ">");
200                 }
201             }
202             try {
203                 StringWriter out = new StringWriter();
204 
205                 try (MonitorWriter monitorOut = new MonitorWriter(out)) {
206                     switch (type) {
207                         case OBJECT_MODEL:
208                             generateFromModel(monitorOut, (ObjectModel) element);
209                             break;
210                         case OBJECT_MODEL_CLASSIFIER:
211                             generateFromClassifier(monitorOut, (ObjectModelClassifier) element);
212                             break;
213                         case OBJECT_MODEL_INTERFACE:
214                             generateFromInterface(monitorOut, (ObjectModelInterface) element);
215                             break;
216                         case OBJECT_MODEL_CLASS:
217                             generateFromClass(monitorOut, (ObjectModelClass) element);
218                             break;
219                         case OBJECT_MODEL_ENUMERATION:
220                             generateFromEnumeration(monitorOut, (ObjectModelEnumeration) element);
221                             break;
222                     }
223 
224                     write(outputFile, monitorOut);
225 
226                 }
227 
228             } catch (Exception eee) {
229                 if (log.isWarnEnabled()) {
230                     log.warn("Erreur lors de la génération du fichier "
231                              + outputFile);
232                 }
233                 throw new RuntimeException(
234                         "Erreur lors de la génération du fichier "
235                         + outputFile, eee);
236             }
237         }
238     }
239 
240     /**
241      * Test if given element can be generated.
242      *
243      * An element can be generated if his package is in the
244      * {@link #generatedPackages} list or if {@link #generatedPackages} is
245      * null or empty.
246      *
247      * @param element element to test
248      * @return generation allowed
249      */
250     protected boolean canGenerateElement(Object element) {
251 
252         boolean canGenerate = true;
253 
254         // can get package only for Classifiers
255         if (element instanceof ObjectModelClassifier) {
256             ObjectModelClassifier classifier = (ObjectModelClassifier) element;
257             String classifierPackage = classifier.getPackageName();
258 
259             canGenerate = canGeneratePackage(classifierPackage);
260         }
261 
262         return canGenerate;
263     }
264 
265     /**
266      * Par defaut cette methode retourne le getName du model. Si l'on souhaite
267      * utiliser la methode generateFromModel il vaut mieux surcharger cette
268      * methode
269      *
270      * @param model le modele utilise
271      * @return le nom du fichier a generer
272      */
273     public String getFilenameForModel(ObjectModel model) {
274         return model.getName();
275     }
276 
277     /**
278      * Par defaut cette methode retourne le QualifiedName convertie en chemin
279      * par exemple pour org.codelutin.Toto on aurait org/codelutin/Toto
280      *
281      * @param model       le modele utilise
282      * @param packageName le nom du paquetage
283      * @return le repertoire correspondant au paquetage
284      */
285     public String getFilenameForPackage(ObjectModel model,
286                                         String packageName) {
287         return packageName.replace('.', File.separatorChar);
288     }
289 
290     /**
291      * Par defaut cette methode retourne le QualifiedName convertie en chemin
292      * par exemple pour org.codelutin.Toto on aurait org/codelutin/Toto
293      *
294      * @param interfacez l'interface utilisee
295      * @return le nom du l'interface a generer
296      */
297     public String getFilenameForInterface(ObjectModelInterface interfacez) {
298         return getFilenameForClassifier(interfacez);
299     }
300 
301     /**
302      * Par defaut cette methode retourne le QualifiedName convertie en chemin
303      * par exemple pour org.codelutin.Toto on aurait org/codelutin/Toto
304      *
305      * @param clazz la classe utilisee
306      * @return le nom de la classe a generer
307      */
308     public String getFilenameForClass(ObjectModelClass clazz) {
309         return getFilenameForClassifier(clazz);
310     }
311 
312     /**
313      * Par defaut cette methode retourne le QualifiedName convertie en chemin
314      * par exemple pour org.codelutin.Toto on aurait org/codelutin/Toto
315      *
316      * @param classifier le classifier utilisee
317      * @return le nom du classifier a generer
318      */
319     public String getFilenameForClassifier(ObjectModelClassifier classifier) {
320         return classifier.getQualifiedName().replace('.', File.separatorChar);
321     }
322 
323     public String getFilenameForEnumeration(ObjectModelEnumeration enumeration) {
324         return getFilenameForClassifier(enumeration);
325     }
326 
327     public void generateFromModel(Writer output,
328                                   ObjectModel input) throws IOException {
329     }
330 
331     public void generateFromInterface(Writer output,
332                                       ObjectModelInterface input) throws IOException {
333     }
334 
335     public void generateFromEnum(Writer output,
336                                  ObjectModelEnumeration input) throws IOException {
337     }
338 
339     public void generateFromClass(Writer output,
340                                   ObjectModelClass input) throws IOException {
341     }
342 
343     public void generateFromClassifier(Writer output,
344                                        ObjectModelClassifier input) throws IOException {
345     }
346 
347     public void generateFromEnumeration(Writer output,
348                                         ObjectModelEnumeration input) throws IOException {
349     }
350 }