KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.gen;
21
22 import java.io.File JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.OutputStreamWriter JavaDoc;
26 import java.io.Writer JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.List JavaDoc;
29
30 import org.apache.cayenne.map.DataMap;
31 import org.apache.cayenne.map.ObjEntity;
32 import org.apache.cayenne.tools.NamePatternMatcher;
33
34 /**
35  * Extends MapClassGenerator to allow target-specific filesystem locations where the files
36  * should go. Adds "execute" method that performs class generation based on the internal
37  * state of this object.
38  *
39  * @author Andrus Adamchik
40  */

41 public class DefaultClassGenerator extends MapClassGenerator {
42
43     protected File JavaDoc destDir;
44     protected boolean overwrite;
45     protected boolean usePkgPath = true;
46     protected boolean makePairs = true;
47     protected String JavaDoc template;
48     protected String JavaDoc superTemplate;
49     protected long timestamp = System.currentTimeMillis();
50     private static final String JavaDoc WILDCARD = "*";
51     protected String JavaDoc outputPattern = "*.java";
52
53     /**
54      * Stores the encoding of the generated file.
55      *
56      * @since 1.2
57      */

58     protected String JavaDoc encoding;
59
60     public DefaultClassGenerator() {
61     }
62
63     /**
64      * Creates class generator and initializes it with DataMap. This will ensure
65      * generation of classes for all ObjEntities in the DataMap.
66      */

67     public DefaultClassGenerator(DataMap dataMap) {
68         this(dataMap, new ArrayList JavaDoc(dataMap.getObjEntities()));
69     }
70
71     /**
72      * Creates class generator and initializes it with the list of ObjEntities that will
73      * be used in class generation.
74      */

75     public DefaultClassGenerator(DataMap dataMap, List JavaDoc selectedObjEntities) {
76         super(dataMap, selectedObjEntities);
77     }
78
79     /** Runs class generation. */
80     public void execute() throws Exception JavaDoc {
81         validateAttributes();
82
83         if (makePairs) {
84             String JavaDoc t = getTemplateForPairs();
85             String JavaDoc st = getSupertemplateForPairs();
86             generateClassPairs(t, st, MapClassGenerator.SUPERCLASS_PREFIX);
87         }
88         else {
89             generateSingleClasses(
90                     getTemplateForSingles(),
91                     MapClassGenerator.SUPERCLASS_PREFIX);
92         }
93     }
94
95     /**
96      * Validates the state of this class generator. Throws exception if it is in
97      * inconsistent state. Called internally from "execute".
98      */

99     public void validateAttributes() throws Exception JavaDoc {
100         if (destDir == null) {
101             throw new Exception JavaDoc("'destDir' attribute is missing.");
102         }
103
104         if (!destDir.isDirectory()) {
105             throw new Exception JavaDoc("'destDir' is not a directory.");
106         }
107
108         if (!destDir.canWrite()) {
109             throw new Exception JavaDoc("Do not have write permissions for " + destDir);
110         }
111
112         if ((false == VERSION_1_1.equals(versionString))
113                 && (false == VERSION_1_2.equals(versionString))) {
114             throw new Exception JavaDoc("'version' must be '"
115                     + VERSION_1_1
116                     + "' or '"
117                     + VERSION_1_2
118                     + "'.");
119         }
120     }
121
122     /**
123      * Sets the destDir.
124      */

125     public void setDestDir(File JavaDoc destDir) {
126         this.destDir = destDir;
127     }
128
129     /**
130      * Sets <code>overwrite</code> property.
131      */

132     public void setOverwrite(boolean overwrite) {
133         this.overwrite = overwrite;
134     }
135
136     /**
137      * Sets <code>makepairs</code> property.
138      */

139     public void setMakePairs(boolean makePairs) {
140         this.makePairs = makePairs;
141     }
142
143     /**
144      * Sets <code>template</code> property.
145      */

146     public void setTemplate(String JavaDoc template) {
147         this.template = template;
148     }
149
150     /**
151      * Sets <code>superTemplate</code> property.
152      */

153     public void setSuperTemplate(String JavaDoc superTemplate) {
154         this.superTemplate = superTemplate;
155     }
156
157     /**
158      * Sets <code>usepkgpath</code> property.
159      */

160     public void setUsePkgPath(boolean usePkgPath) {
161         this.usePkgPath = usePkgPath;
162     }
163
164     /**
165      * Sets <code>outputPattern</code> property.
166      */

167     public void setOutputPattern(String JavaDoc outputPattern) {
168         this.outputPattern = outputPattern;
169     }
170
171     public void closeWriter(Writer JavaDoc out) throws Exception JavaDoc {
172         out.close();
173     }
174
175     /**
176      * Opens a Writer to write generated output. Writer encoding is determined from the
177      * value of the "encoding" property.
178      */

179     public Writer JavaDoc openWriter(ObjEntity entity, String JavaDoc pkgName, String JavaDoc className)
180             throws Exception JavaDoc {
181         File JavaDoc outFile = (className.startsWith(SUPERCLASS_PREFIX)) ? fileForSuperclass(
182                 pkgName,
183                 className) : fileForClass(pkgName, className);
184
185         if (outFile == null) {
186             return null;
187         }
188
189         // return writer with specified encoding
190
FileOutputStream JavaDoc out = new FileOutputStream JavaDoc(outFile);
191
192         return (getEncoding() != null)
193                 ? new OutputStreamWriter JavaDoc(out, getEncoding())
194                 : new OutputStreamWriter JavaDoc(out);
195     }
196
197     /**
198      * Returns a target file where a generated superclass must be saved. If null is
199      * returned, class shouldn't be generated.
200      */

201     protected File JavaDoc fileForSuperclass(String JavaDoc pkgName, String JavaDoc className) throws Exception JavaDoc {
202
203         String JavaDoc filename = NamePatternMatcher.replaceWildcardInStringWithString(
204                 WILDCARD,
205                 outputPattern,
206                 className);
207         File JavaDoc dest = new File JavaDoc(mkpath(destDir, pkgName), filename);
208
209         // Ignore if the destination is newer than the map
210
// (internal timestamp), i.e. has been generated after the map was
211
// last saved AND the template is older than the destination file
212
if (dest.exists() && !isOld(dest)) {
213
214             if (superTemplate == null) {
215                 return null;
216             }
217
218             File JavaDoc superTemplateFile = new File JavaDoc(superTemplate);
219             if (superTemplateFile.lastModified() < dest.lastModified()) {
220                 return null;
221             }
222         }
223
224         return dest;
225     }
226
227     /**
228      * Returns a target file where a generated class must be saved. If null is returned,
229      * class shouldn't be generated.
230      */

231     protected File JavaDoc fileForClass(String JavaDoc pkgName, String JavaDoc className) throws Exception JavaDoc {
232
233         String JavaDoc filename = NamePatternMatcher.replaceWildcardInStringWithString(
234                 WILDCARD,
235                 outputPattern,
236                 className);
237         File JavaDoc dest = new File JavaDoc(mkpath(destDir, pkgName), filename);
238
239         if (dest.exists()) {
240             // no overwrite of subclasses
241
if (makePairs) {
242                 return null;
243             }
244
245             // skip if said so
246
if (!overwrite) {
247                 return null;
248             }
249
250             // Ignore if the destination is newer than the map
251
// (internal timestamp), i.e. has been generated after the map was
252
// last saved AND the template is older than the destination file
253
if (!isOld(dest)) {
254
255                 if (template == null) {
256                     return null;
257                 }
258
259                 File JavaDoc templateFile = new File JavaDoc(template);
260                 if (templateFile.lastModified() < dest.lastModified()) {
261                     return null;
262                 }
263             }
264         }
265
266         return dest;
267     }
268
269     /**
270      * Returns true if <code>file</code> parameter is older than internal timestamp of
271      * this class generator.
272      */

273     protected boolean isOld(File JavaDoc file) {
274         return file.lastModified() <= getTimestamp();
275     }
276
277     /**
278      * Returns a File object corresponding to a directory where files that belong to
279      * <code>pkgName</code> package should reside. Creates any missing diectories below
280      * <code>dest</code>.
281      */

282     protected File JavaDoc mkpath(File JavaDoc dest, String JavaDoc pkgName) throws Exception JavaDoc {
283
284         if (!usePkgPath || pkgName == null) {
285             return dest;
286         }
287
288         String JavaDoc path = pkgName.replace('.', File.separatorChar);
289         File JavaDoc fullPath = new File JavaDoc(dest, path);
290         if (!fullPath.isDirectory() && !fullPath.mkdirs()) {
291             throw new Exception JavaDoc("Error making path: " + fullPath);
292         }
293
294         return fullPath;
295     }
296
297     /**
298      * Returns template file path for Java class when generating single classes.
299      */

300     protected String JavaDoc getTemplateForSingles() throws IOException JavaDoc {
301         return (template != null) ? template : defaultSingleClassTemplate();
302     }
303
304     /**
305      * Returns template file path for Java subclass when generating class pairs.
306      */

307     protected String JavaDoc getTemplateForPairs() throws IOException JavaDoc {
308         return (template != null) ? template : defaultSubclassTemplate();
309     }
310
311     /**
312      * Returns template file path for Java superclass when generating class pairs.
313      */

314     protected String JavaDoc getSupertemplateForPairs() throws IOException JavaDoc {
315         return (superTemplate != null) ? superTemplate : defaultSuperclassTemplate();
316     }
317
318     /**
319      * Returns internal timestamp of this generator used to make decisions about
320      * overwriting individual files.
321      */

322     public long getTimestamp() {
323         return timestamp;
324     }
325
326     public void setTimestamp(long timestamp) {
327         this.timestamp = timestamp;
328     }
329
330     /**
331      * Returns file encoding for the generated files.
332      *
333      * @since 1.2
334      */

335     public String JavaDoc getEncoding() {
336         return encoding;
337     }
338
339     /**
340      * Sets file encoding. If set to null, default system encoding will be used.
341      *
342      * @since 1.2
343      */

344     public void setEncoding(String JavaDoc encoding) {
345         this.encoding = encoding;
346     }
347 }
348
Popular Tags