1 package org.asyrinx.joey.gen.task;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 import java.io.File;
58 import java.io.IOException;
59 import java.util.ArrayList;
60 import java.util.Hashtable;
61 import java.util.Iterator;
62 import java.util.List;
63
64 import org.apache.tools.ant.BuildException;
65 import org.apache.tools.ant.DirectoryScanner;
66 import org.apache.tools.ant.types.FileSet;
67 import org.apache.velocity.VelocityContext;
68 import org.apache.velocity.context.Context;
69 import org.apache.velocity.texen.ant.TexenTask;
70 import org.asyrinx.brownie.core.lang.ClassUtils;
71 import org.asyrinx.brownie.core.lang.StringUtils;
72 import org.asyrinx.joey.gen.command.rdb2java.standard.Rdb2JavaBuilder;
73 import org.asyrinx.joey.gen.hibernate.HibernateUtils;
74 import org.asyrinx.joey.gen.model.java.AppDomain;
75 import org.asyrinx.joey.gen.model.rdb.Databases;
76 import org.asyrinx.joey.gen.model.rdb.xml.XmlToRdb;
77 import org.xml.sax.SAXException;
78
79 /***
80 * A base torque task that uses either a single XML schema representing a data
81 * model, or a <fileset> of XML schemas. We are making the assumption that
82 * an XML schema representing a data model contains tables for a <strong>single
83 * </strong> database.
84 *
85 * @author <a href="mailto:jvanzyl@zenplex.com">Jason van Zyl </a>
86 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall </a>
87 */
88 public class DataModelTask extends TexenTask {
89 /***
90 * XML that describes the database model, this is transformed into the
91 * application model object.
92 */
93 protected String xmlFile;
94
95 /***
96 * Fileset of XML schemas which represent our data models.
97 */
98 protected List filesets = new ArrayList();
99
100 /***
101 * Velocity context which exposes our objects in the templates.
102 */
103 protected Context context;
104
105 /***
106 * Get the xml schema describing the application model.
107 *
108 * @return String xml schema file.
109 */
110 public String getXmlFile() {
111 return xmlFile;
112 }
113
114 /***
115 * Set the xml schema describing the application model.
116 *
117 * @param xmlFile
118 * The new XmlFile value
119 */
120 public void setXmlFile(String xmlFile) {
121 this.xmlFile = project.resolveFile(xmlFile).toString();
122 }
123
124 /***
125 * Adds a set of xml schema files (nested fileset attribute).
126 *
127 * @param set
128 * a Set of xml schema files
129 */
130 public void addFileset(FileSet set) {
131 filesets.add(set);
132 }
133
134 /***
135 * Set up the initial context for generating the SQL from the XML schema.
136 *
137 * @return the context
138 * @throws Exception
139 */
140 public Context initControlContext() throws Exception {
141 return loadModels();
142 }
143
144 /***
145 * @return
146 * @throws SAXException
147 * @throws IOException
148 * @throws InstantiationException
149 */
150 private Context loadModels() throws IOException, SAXException, InstantiationException {
151 if (xmlFile == null && filesets.isEmpty())
152 throw new BuildException("You must specify an XML schema or " + "fileset of XML schemas!");
153 final Databases databases = new Databases();
154 if (xmlFile != null) {
155
156
157 databases.getDatabases().add(loadModelXmlFile(xmlFile));
158 } else {
159
160 for (int i = 0; i < filesets.size(); i++) {
161 FileSet fs = (FileSet) filesets.get(i);
162 DirectoryScanner ds = fs.getDirectoryScanner(project);
163 File srcDir = fs.getDir(project);
164 String[] dataModelFiles = ds.getIncludedFiles();
165
166 for (int j = 0; j < dataModelFiles.length; j++) {
167 final File f = new File(srcDir, dataModelFiles[j]);
168 final Databases loaded = loadModelXmlFile(f.toString());
169 databases.appendDatabases(loaded);
170 }
171 }
172 }
173
174 final Rdb2JavaBuilder builder = newBuilder();
175 final AppDomain domain = builder.execute(databases);
176
177 context = new VelocityContext();
178
179
180 context.put("databases", databases);
181 context.put("domain", domain);
182 context.put("builder", builder);
183 context.put("helper", new VelocityHelper());
184 context.put("stringUtils", new org.asyrinx.brownie.core.lang.StringUtils());
185 context.put("hibernateUtils", new HibernateUtils());
186
187 return context;
188 }
189
190 protected Databases loadModelXmlFile(String filename) throws IOException, SAXException {
191 final XmlToRdb xmlToRdb = new XmlToRdb();
192 xmlToRdb.setDebug("true".equals(getContextProperties().getString("schemaDebug")));
193 return xmlToRdb.load(filename);
194 }
195
196 /***
197 * Override Texen's context properties to map the torque.xxx properties
198 * (including defaults set by the org/apache/torque/defaults.properties) to
199 * just xxx.
200 *
201 * <p>
202 * Also, move xxx.yyy properties to xxxYyy as Velocity doesn't like the
203 * xxx.yyy syntax.
204 * </p>
205 *
206 * @param file
207 * the file to read the properties from
208 */
209 public void setContextProperties(String file) {
210 super.setContextProperties(file);
211
212 Hashtable env = super.getProject().getProperties();
213 for (Iterator i = env.keySet().iterator(); i.hasNext();) {
214 String key = (String) i.next();
215 if (key.startsWith("joey-gen.")) {
216 String newKey = toVelocityKey(key.substring("joey-gen.".length()));
217 contextProperties.setProperty(newKey, env.get(key));
218 System.out.println("joey-gen property available: " + newKey + ":" + env.get(key));
219 }
220 }
221 for (Iterator i = env.keySet().iterator(); i.hasNext();) {
222 String key = (String) i.next();
223 if (key.startsWith("proj.")) {
224 String newKey = toVelocityKey(key);
225 contextProperties.setProperty(newKey, env.get(key));
226 System.out.println("project property available: " + newKey + ":" + env.get(key));
227 }
228 }
229 }
230
231 /***
232 * @param newKey
233 * @return
234 */
235 private String toVelocityKey(String newKey) {
236 int j = newKey.indexOf(".");
237 while (j != -1) {
238 newKey = newKey.substring(0, j) + StringUtils.capitalize(newKey.substring(j + 1));
239 j = newKey.indexOf(".");
240 }
241 return newKey;
242 }
243
244 private String builderClassName = "org.asyrinx.joey.gen.command.rdb2java.standard.BasicBuilder";
245
246 /***
247 * @return Returns the builderClassName.
248 */
249 public String getBuilderClassName() {
250 return builderClassName;
251 }
252
253 /***
254 * @param builderClassName
255 * The builderClassName to set.
256 */
257 public void setBuilderClassName(String builderClassName) {
258 this.builderClassName = builderClassName;
259 }
260
261 protected Rdb2JavaBuilder newBuilder() throws InstantiationException {
262 return (Rdb2JavaBuilder) ClassUtils.newObject(getBuilderClassName(), Rdb2JavaBuilder.class);
263 }
264
265 }