KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > gen > DefaultClassGenerator


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56
57 package org.objectstyle.cayenne.gen;
58
59 import java.io.File JavaDoc;
60 import java.io.FileOutputStream JavaDoc;
61 import java.io.IOException JavaDoc;
62 import java.io.OutputStreamWriter JavaDoc;
63 import java.io.Writer JavaDoc;
64 import java.util.ArrayList JavaDoc;
65 import java.util.List JavaDoc;
66
67 import org.objectstyle.cayenne.map.DataMap;
68 import org.objectstyle.cayenne.map.ObjEntity;
69 import org.objectstyle.cayenne.tools.NamePatternMatcher;
70
71 /**
72  * Extends MapClassGenerator to allow target-specific filesystem locations where the files
73  * should go. Adds "execute" method that performs class generation based on the internal
74  * state of this object.
75  *
76  * @author Andrei Adamchik
77  */

78 public class DefaultClassGenerator extends MapClassGenerator {
79
80     protected File JavaDoc destDir;
81     protected boolean overwrite;
82     protected boolean usePkgPath = true;
83     protected boolean makePairs = true;
84     protected File JavaDoc template;
85     protected File JavaDoc superTemplate;
86     protected long timestamp = System.currentTimeMillis();
87     private static final String JavaDoc WILDCARD = "*";
88     protected String JavaDoc outputPattern = "*.java";
89     
90     /**
91      * Stores the encoding of the generated file.
92      *
93      * @since 1.2
94      */

95     protected String JavaDoc encoding;
96
97     public DefaultClassGenerator() {
98     }
99
100     /**
101      * Creates class generator and initializes it with DataMap. This will ensure
102      * generation of classes for all ObjEntities in the DataMap.
103      */

104     public DefaultClassGenerator(DataMap dataMap) {
105         this(dataMap, new ArrayList JavaDoc(dataMap.getObjEntities()));
106     }
107
108     /**
109      * Creates class generator and initializes it with the list of ObjEntities that will
110      * be used in class generation.
111      */

112     public DefaultClassGenerator(DataMap dataMap, List JavaDoc selectedObjEntities) {
113         super(dataMap, selectedObjEntities);
114     }
115
116     /**
117      * Creates class generator and initializes it with the list of ObjEntities that will
118      * be used in class generation.
119      * @deprecated Use DefaultClassGenerator(DataMap, List) to provide support for v1.2 templates.
120      */

121     public DefaultClassGenerator(List JavaDoc selectedObjEntities) {
122         super(selectedObjEntities);
123     }
124
125     /** Runs class generation. */
126     public void execute() throws Exception JavaDoc {
127         validateAttributes();
128
129         if (makePairs) {
130             String JavaDoc t = getTemplateForPairs();
131             String JavaDoc st = getSupertemplateForPairs();
132             generateClassPairs(t, st, MapClassGenerator.SUPERCLASS_PREFIX);
133         }
134         else {
135             generateSingleClasses(getTemplateForSingles(), MapClassGenerator.SUPERCLASS_PREFIX);
136         }
137     }
138
139     /**
140      * Validates the state of this class generator. Throws exception if it is in
141      * inconsistent state. Called internally from "execute".
142      */

143     public void validateAttributes() throws Exception JavaDoc {
144         if (destDir == null) {
145             throw new Exception JavaDoc("'destDir' attribute is missing.");
146         }
147
148         if (!destDir.isDirectory()) {
149             throw new Exception JavaDoc("'destDir' is not a directory.");
150         }
151
152         if (!destDir.canWrite()) {
153             throw new Exception JavaDoc("Do not have write permissions for " + destDir);
154         }
155
156         if (template != null && !template.canRead()) {
157             throw new Exception JavaDoc("Can't read template from " + template);
158         }
159
160         if (makePairs && superTemplate != null && !superTemplate.canRead()) {
161             throw new Exception JavaDoc("Can't read super template from " + superTemplate);
162         }
163         
164         if ( (false == VERSION_1_1.equals(versionString)) && (false == VERSION_1_2.equals(versionString)) ) {
165             throw new Exception JavaDoc("'version' must be '" + VERSION_1_1 + "' or '" + VERSION_1_2 + "'.");
166         }
167     }
168
169     /**
170      * Sets the destDir.
171      */

172     public void setDestDir(File JavaDoc destDir) {
173         this.destDir = destDir;
174     }
175
176     /**
177      * Sets <code>overwrite</code> property.
178      */

179     public void setOverwrite(boolean overwrite) {
180         this.overwrite = overwrite;
181     }
182
183     /**
184      * Sets <code>makepairs</code> property.
185      */

186     public void setMakePairs(boolean makePairs) {
187         this.makePairs = makePairs;
188     }
189
190     /**
191      * Sets <code>template</code> property.
192      */

193     public void setTemplate(File JavaDoc template) {
194         this.template = template;
195     }
196
197     /**
198      * Sets <code>superTemplate</code> property.
199      */

200     public void setSuperTemplate(File JavaDoc superTemplate) {
201         this.superTemplate = superTemplate;
202     }
203
204     /**
205      * Sets <code>usepkgpath</code> property.
206      */

207     public void setUsePkgPath(boolean usePkgPath) {
208         this.usePkgPath = usePkgPath;
209     }
210
211     /**
212      * Sets <code>outputPattern</code> property.
213      */

214     public void setOutputPattern(String JavaDoc outputPattern) {
215         this.outputPattern = outputPattern;
216     }
217
218     public void closeWriter(Writer JavaDoc out) throws Exception JavaDoc {
219         out.close();
220     }
221
222     /**
223      * Opens a Writer to write generated output. Writer encoding is determined from the
224      * value of the "encoding" property.
225      */

226     public Writer JavaDoc openWriter(ObjEntity entity, String JavaDoc pkgName, String JavaDoc className)
227             throws Exception JavaDoc {
228         File JavaDoc outFile = (className.startsWith(SUPERCLASS_PREFIX))
229                 ? fileForSuperclass(pkgName, className)
230                 : fileForClass(pkgName, className);
231
232         if (outFile == null) {
233             return null;
234         }
235
236         // return writer with specified encoding
237
FileOutputStream JavaDoc out = new FileOutputStream JavaDoc(outFile);
238
239         return (getEncoding() != null)
240                 ? new OutputStreamWriter JavaDoc(out, getEncoding())
241                 : new OutputStreamWriter JavaDoc(out);
242     }
243
244     /**
245      * Returns a target file where a generated superclass must be saved. If null is
246      * returned, class shouldn't be generated.
247      */

248     protected File JavaDoc fileForSuperclass(String JavaDoc pkgName, String JavaDoc className) throws Exception JavaDoc {
249
250         String JavaDoc filename = NamePatternMatcher.replaceWildcardInStringWithString(WILDCARD, outputPattern, className);
251         File JavaDoc dest = new File JavaDoc(mkpath(destDir, pkgName), filename);
252
253         // Ignore if the destination is newer than the map
254
// (internal timestamp), i.e. has been generated after the map was
255
// last saved AND the template is older than the destination file
256
if (dest.exists()
257                 && !isOld(dest)
258                 && (superTemplate == null || superTemplate.lastModified() < dest
259                         .lastModified())) {
260             return null;
261         }
262
263         return dest;
264     }
265
266     /**
267      * Returns a target file where a generated class must be saved. If null is returned,
268      * class shouldn't be generated.
269      */

270     protected File JavaDoc fileForClass(String JavaDoc pkgName, String JavaDoc className) throws Exception JavaDoc {
271
272         String JavaDoc filename = NamePatternMatcher.replaceWildcardInStringWithString(WILDCARD, outputPattern, className);
273         File JavaDoc dest = new File JavaDoc(mkpath(destDir, pkgName), filename);
274
275         if (dest.exists()) {
276             // no overwrite of subclasses
277
if (makePairs) {
278                 return null;
279             }
280
281             // skip if said so
282
if (!overwrite) {
283                 return null;
284             }
285
286             // Ignore if the destination is newer than the map
287
// (internal timestamp), i.e. has been generated after the map was
288
// last saved AND the template is older than the destination file
289
if (!isOld(dest)
290                     && (template == null || template.lastModified() < dest.lastModified())) {
291                 return null;
292             }
293         }
294
295         return dest;
296     }
297
298     /**
299      * Returns true if <code>file</code> parameter is older than internal timestamp of
300      * this class generator.
301      */

302     protected boolean isOld(File JavaDoc file) {
303         return file.lastModified() <= getTimestamp();
304     }
305
306     /**
307      * Returns a File object corresponding to a directory where files that belong to
308      * <code>pkgName</code> package should reside. Creates any missing diectories below
309      * <code>dest</code>.
310      */

311     protected File JavaDoc mkpath(File JavaDoc dest, String JavaDoc pkgName) throws Exception JavaDoc {
312
313         if (!usePkgPath || pkgName == null) {
314             return dest;
315         }
316
317         String JavaDoc path = pkgName.replace('.', File.separatorChar);
318         File JavaDoc fullPath = new File JavaDoc(dest, path);
319         if (!fullPath.isDirectory() && !fullPath.mkdirs()) {
320             throw new Exception JavaDoc("Error making path: " + fullPath);
321         }
322
323         return fullPath;
324     }
325
326     /**
327      * Returns template file path for Java class when generating single classes.
328      */

329     protected String JavaDoc getTemplateForSingles() throws IOException JavaDoc {
330         return (template != null) ? template.getPath() : defaultSingleClassTemplate();
331     }
332
333     /**
334      * Returns template file path for Java subclass when generating class pairs.
335      */

336     protected String JavaDoc getTemplateForPairs() throws IOException JavaDoc {
337         return (template != null) ? template.getPath() : defaultSubclassTemplate();
338     }
339
340     /**
341      * Returns template file path for Java superclass when generating class pairs.
342      */

343     protected String JavaDoc getSupertemplateForPairs() throws IOException JavaDoc {
344         return (superTemplate != null)
345                 ? superTemplate.getPath()
346                 : defaultSuperclassTemplate();
347     }
348
349     /**
350      * Returns internal timestamp of this generator used to make decisions about
351      * overwriting individual files.
352      */

353     public long getTimestamp() {
354         return timestamp;
355     }
356
357     public void setTimestamp(long timestamp) {
358         this.timestamp = timestamp;
359     }
360
361     /**
362      * Returns file encoding for the generated files.
363      *
364      * @since 1.2
365      */

366     public String JavaDoc getEncoding() {
367         return encoding;
368     }
369
370     /**
371      * Sets file encoding. If set to null, default system encoding will be used.
372      *
373      * @since 1.2
374      */

375     public void setEncoding(String JavaDoc encoding) {
376         this.encoding = encoding;
377     }
378 }
Popular Tags