KickJava   Java API By Example, From Geeks To Geeks.

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


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.Writer JavaDoc;
60 import java.util.Properties JavaDoc;
61
62 import org.apache.velocity.Template;
63 import org.apache.velocity.VelocityContext;
64 import org.apache.velocity.app.Velocity;
65 import org.apache.velocity.context.Context;
66 import org.apache.velocity.runtime.RuntimeConstants;
67 import org.apache.velocity.runtime.log.NullLogSystem;
68 import org.apache.velocity.runtime.resource.loader.JarResourceLoader;
69 import org.objectstyle.cayenne.CayenneRuntimeException;
70 import org.objectstyle.cayenne.map.DataMap;
71 import org.objectstyle.cayenne.map.ObjEntity;
72 import org.objectstyle.cayenne.util.ResourceLocator;
73
74 import foundrylogic.vpp.VPPConfig;
75
76 /**
77  * Class generation engine for ObjEntities based on <a
78  * HREF="http://jakarta.apache.org/velocity/" target="_blank">Velocity templates
79  * </a>. Instance of ClassGenerationInfo is available inside Velocity template under
80  * the key "classGen".
81  *
82  * @author Andrei Adamchik
83  */

84 public class ClassGenerator {
85     public static final String JavaDoc VERSION_1_1 = "1.1";
86     public static final String JavaDoc VERSION_1_2 = "1.2";
87     
88     protected String JavaDoc versionString;
89     protected Template classTemplate;
90     protected Context velCtxt;
91     protected ClassGenerationInfo classGenerationInfo; // only used for VERSION_1_1
92

93     private static boolean initDone;
94
95     /**
96      * Configures ClassGenerationInfo to load class templates using ClassLoader of a
97      * specified class. It is a responsibility of a class caller to invoke this
98      * method before ClassGenerationInfo is used.
99      *
100      * <p>
101      * This method affects Velocity configuration when called for the first
102      * time, since Velocity.init() is done only once. Subsequent calls have no
103      * effect on ClassLoader behavior.
104      * </p>
105      */

106     public synchronized static final void bootstrapVelocity(Class JavaDoc cl) {
107         if (initDone) {
108             return;
109         }
110
111         // TODO: use an internal RuntimeInstance like SQLTemplateProcessor does...
112

113         try {
114             String JavaDoc classLoaderUrl = ResourceLocator.classBaseUrl(cl);
115
116             // use ClasspathResourceLoader for velocity templates lookup
117
// if Cayenne URL is not null, load resource from this URL
118
Properties JavaDoc props = new Properties JavaDoc();
119             
120             // set null logger
121
props.put(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, NullLogSystem.class
122                     .getName());
123
124             String JavaDoc loaderProp = null;
125             // init special loaders
126
if (classLoaderUrl != null && classLoaderUrl.startsWith("jar:")) {
127                 loaderProp = "jar";
128                 props.put("jar.resource.loader.class", JarResourceLoader.class.getName());
129                 props.put("jar.resource.loader.path", classLoaderUrl);
130             }
131             else if (classLoaderUrl != null && classLoaderUrl.startsWith("file:")) {
132                 loaderProp = "file";
133                 props.put("file.resource.loader.path", classLoaderUrl.substring(5));
134             }
135
136             // always add Filesystem loader for default templates
137
if (loaderProp != null) {
138                 if (loaderProp.indexOf("file") < 0) {
139                     loaderProp += ",file";
140                 }
141             }
142
143             // use custom file loader
144
props
145                     .put("file.resource.loader.class", AbsFileResourceLoader.class
146                             .getName());
147
148             // always add Classpath loader for default templates
149
loaderProp = (loaderProp != null) ? loaderProp + ",class" : "class";
150             props.put("resource.loader", loaderProp);
151
152             Velocity.init(props);
153         }
154         catch (Exception JavaDoc ex) {
155             throw new CayenneRuntimeException("Can't initialize VTL", ex);
156         }
157         finally {
158             initDone = true;
159         }
160     }
161
162     /**
163      * Creates a new ClassGenerationInfo that uses a specified Velocity template.
164      * @deprecated Use ClassGenerator(String template, String versionString) instead.
165      */

166     public ClassGenerator(String JavaDoc template) throws Exception JavaDoc {
167         this(template, "1.1");
168     }
169
170     /**
171      * Creates a new ClassGenerationInfo that uses a specified Velocity template.
172      */

173     public ClassGenerator(String JavaDoc template, String JavaDoc versionString) throws Exception JavaDoc {
174         if (!initDone) {
175             bootstrapVelocity(this.getClass());
176         }
177         
178         this.versionString = versionString;
179         
180         if (false == VERSION_1_1.equals(versionString)) {
181             throw new IllegalStateException JavaDoc("Illegal Version in generateClass(Writer,ObjEntity): " + versionString);
182         }
183
184         velCtxt = new VelocityContext();
185         classGenerationInfo = new ClassGenerationInfo();
186         velCtxt.put("classGen", classGenerationInfo);
187         classTemplate = Velocity.getTemplate(template);
188     }
189
190     /**
191      * Creates a new ClassGenerationInfo that uses a specified Velocity template.
192      */

193     public ClassGenerator(String JavaDoc template, String JavaDoc versionString, VPPConfig vppConfig)
194             throws Exception JavaDoc {
195         
196         if (!initDone) {
197             bootstrapVelocity(this.getClass());
198         }
199
200         this.versionString = versionString;
201
202         if (false == VERSION_1_2.equals(versionString)) {
203             throw new IllegalStateException JavaDoc(
204                     "Illegal Version in generateClass(Writer,ObjEntity): "
205                             + versionString);
206         }
207
208         if (vppConfig != null) {
209             velCtxt = vppConfig.getVelocityContext();
210         }
211         else {
212             velCtxt = new VelocityContext();
213         }
214
215         classTemplate = Velocity.getTemplate(template);
216     }
217
218     /**
219      * Generates Java code for the ObjEntity. Output is written to the provided
220      * Writer.
221      */

222     public void generateClass(Writer JavaDoc out, ObjEntity entity) throws Exception JavaDoc {
223         if (false == VERSION_1_1.equals(versionString)) {
224             throw new IllegalStateException JavaDoc("Illegal Version in generateClass(Writer,ObjEntity): " + versionString);
225         }
226         
227         classGenerationInfo.setObjEntity(entity);
228         classTemplate.merge(velCtxt, out);
229     }
230
231     /**
232      * Generates Java code for the ObjEntity. Output is written to the provided
233      * Writer.
234      */

235     public void generateClass(Writer JavaDoc out, DataMap dataMap, ObjEntity entity, String JavaDoc fqnBaseClass, String JavaDoc fqnSuperClass, String JavaDoc fqnSubClass) throws Exception JavaDoc {
236         if (false == VERSION_1_2.equals(versionString)) {
237             throw new IllegalStateException JavaDoc("Illegal Version in generateClass(Writer,ObjEntity,String,String,String): " + versionString);
238         }
239         
240         if (null == dataMap) {
241             throw new IllegalStateException JavaDoc("DataMap MapClassGenerator constructor required for v1.2 templating.");
242         }
243
244         velCtxt.put("objEntity", entity);
245         velCtxt.put("stringUtils", StringUtils.getInstance());
246         velCtxt.put("entityUtils", new EntityUtils(dataMap, entity, fqnBaseClass, fqnSuperClass, fqnSubClass));
247         velCtxt.put("importUtils", new ImportUtils());
248         
249         classTemplate.merge(velCtxt, out);
250     }
251
252     // deprecated, delegated methods previously used internally in cayenne
253
/**
254      * @return Returns the classGenerationInfo in template.
255      */

256     public ClassGenerationInfo getClassGenerationInfo() {
257         return classGenerationInfo;
258     }
259
260     /**
261      * Returns Java package name of the class associated with this generator.
262      * @deprecated Since 1.2 use getClassGenerationInfo().getPackageName()
263      */

264     public String JavaDoc getPackageName() {
265         return classGenerationInfo.getPackageName();
266     }
267     
268     /**
269      * Sets Java package name of the class associated with this generator.
270      *
271      * @deprecated Since 1.2 use getClassGenerationInfo().setPackageName()
272      */

273     public void setPackageName(String JavaDoc packageName) {
274         classGenerationInfo.setPackageName(packageName);
275     }
276
277     /**
278      * Sets <code>superPackageName</code> property that defines a superclass's
279      * package name.
280      *
281      * @deprecated Since 1.2 use getClassGenerationInfo().setSuperPackageName()
282      */

283     public void setSuperPackageName(String JavaDoc superPackageName) {
284         classGenerationInfo.setSuperPackageName(superPackageName);
285     }
286
287     /**
288      * Returns class name (without a package) of the class associated with this
289      * generator.
290      *
291      * @deprecated Since 1.2 use getClassGenerationInfo().getClassName()
292      */

293     public String JavaDoc getClassName() {
294         return classGenerationInfo.getClassName();
295     }
296     /**
297      * Sets class name of the class associated with this
298      * generator. Class name must not include a package.
299      *
300      * @deprecated Since 1.2 use getClassGenerationInfo().setClassName()
301      */

302     public void setClassName(String JavaDoc className) {
303         classGenerationInfo.setClassName(className);
304     }
305     
306     /**
307      * Sets the fully qualified super class of the data object class associated
308      * with this generator
309      * @deprecated Since 1.2 use getClassGenerationInfo().setSuperClassName()
310      */

311     public void setSuperClassName(String JavaDoc value) {
312         classGenerationInfo.setSuperClassName(value);
313     }
314
315     /**
316      * Returns prefix used to distinguish between superclass and subclass when
317      * generating classes in pairs.
318      *
319      * @deprecated Since 1.2 use getClassGenerationInfo().setSuperPrefix()
320      */

321     public void setSuperPrefix(String JavaDoc superPrefix) {
322         classGenerationInfo.setSuperPrefix(superPrefix);
323     }
324     
325     // deprecated, delegated methods not used internally in cayenne
326

327     /**
328      * Returns <code>superPackageName</code> property that defines a
329      * superclass's package name.
330      *
331      * @deprecated Since 1.2 use getClassGenerationInfo().getSuperPackageName()
332      */

333     public String JavaDoc getSuperPackageName()
334     {
335         return classGenerationInfo.getSuperPackageName();
336     }
337
338     /**
339      * @deprecated use getClassGenerationInfo().formatJavaType(String)
340      */

341     public String JavaDoc formatJavaType(String JavaDoc type)
342     {
343         return classGenerationInfo.formatJavaType(type);
344     }
345
346     /**
347      * @deprecated Since 1.2 use getClassGenerationInfo().formatVariableName(String)
348      */

349     public String JavaDoc formatVariableName(String JavaDoc variableName)
350     {
351         return classGenerationInfo.formatVariableName(variableName);
352     }
353
354     /**
355      * Returns prefix used to distinguish between superclass and subclass when
356      * generating classes in pairs.
357      *
358      * @deprecated Since 1.2 use getClassGenerationInfo().getSuperPrefix()
359      */

360     public String JavaDoc getSuperPrefix()
361     {
362         return classGenerationInfo.getSuperPrefix();
363     }
364
365     /**
366      * Sets current class property name. This method is called during template
367      * parsing for each of the class properties.
368      *
369      * @deprecated Since 1.2 use getClassGenerationInfo().setProp(String)
370      */

371     public void setProp(String JavaDoc prop)
372     {
373         classGenerationInfo.setProp(prop);
374     }
375
376     /**
377      * @deprecated Since 1.2 use getClassGenerationInfo().getProp()
378      */

379     public String JavaDoc getProp()
380     {
381         return classGenerationInfo.getProp();
382     }
383
384     /**
385      * Capitalizes the first letter of the property name.
386      *
387      * @since 1.1
388      * @deprecated Since 1.2 use getClassGenerationInfo().capitalized(String)
389      */

390     public String JavaDoc capitalized(String JavaDoc name)
391     {
392         return classGenerationInfo.capitalized(name);
393     }
394
395     /**
396      * Converts property name to Java constants naming convention.
397      *
398      * @since 1.1
399      * @deprecated Since 1.2 use getClassGenerationInfo().capitalizedAsConstant(String)
400      */

401     public String JavaDoc capitalizedAsConstant(String JavaDoc name)
402     {
403         return classGenerationInfo.capitalizedAsConstant(name);
404     }
405
406     /** Returns current property name with capitalized first letter
407      * @deprecated Since 1.2 use getClassGenerationInfo().getCappedProp()
408      */

409     public String JavaDoc getCappedProp()
410     {
411         return classGenerationInfo.getCappedProp();
412     }
413
414     /**
415      * @return a current property name converted to a format used by java static
416      * final variables - all capitalized with underscores.
417      *
418      * @since 1.0.3
419      * @deprecated Since 1.2 use getClassGenerationInfo().getPropAsConstantName()
420      */

421     public String JavaDoc getPropAsConstantName()
422     {
423         return classGenerationInfo.getPropAsConstantName();
424     }
425
426     /**
427      * Returns true if current entity contains at least one List property.
428      *
429      * @since 1.1
430      * @deprecated Since 1.2 use getClassGenerationInfo().isContainingListProperties()
431      */

432     public boolean isContainingListProperties()
433     {
434         return classGenerationInfo.isContainingListProperties();
435     }
436
437     /**
438      * Returns <code>true</code> if a class associated with this generator is
439      * located in a package.
440      * @deprecated Since 1.2 use getClassGenerationInfo().isUsingPackage()
441      */

442     public boolean isUsingPackage()
443     {
444         return classGenerationInfo.isUsingPackage();
445     }
446
447     /**
448      * Returns <code>true</code> if a superclass class associated with this
449      * generator is located in a package.
450      * @deprecated Since 1.2 use getClassGenerationInfo().isUsingSuperPackage()
451      */

452     public boolean isUsingSuperPackage()
453     {
454         return classGenerationInfo.isUsingSuperPackage();
455     }
456
457     /**
458      * Returns entity for the class associated with this generator.
459      * @deprecated Since 1.2 use getClassGenerationInfo().getEntity()
460      */

461     public ObjEntity getEntity()
462     {
463         return classGenerationInfo.getEntity();
464     }
465
466     /**
467      * Returns the fully qualified super class of the data object class
468      * associated with this generator
469      * @deprecated Since 1.2 use getClassGenerationInfo().getSuperClassName()
470      */

471     public String JavaDoc getSuperClassName()
472     {
473         return classGenerationInfo.getSuperClassName();
474     }
475 }
Popular Tags