1 package org.apache.torque.task;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.util.ArrayList;
24 import java.util.Date;
25 import java.util.Hashtable;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.apache.commons.lang.StringUtils;
31 import org.apache.tools.ant.BuildException;
32 import org.apache.tools.ant.DirectoryScanner;
33 import org.apache.tools.ant.types.FileSet;
34 import org.apache.torque.engine.EngineException;
35 import org.apache.torque.engine.database.model.Database;
36 import org.apache.torque.engine.database.transform.XmlToAppData;
37 import org.apache.velocity.VelocityContext;
38 import org.apache.velocity.context.Context;
39 import org.apache.velocity.texen.ant.TexenTask;
40
41 /***
42 * A base torque task that uses either a single XML schema
43 * representing a data model, or a <fileset> of XML schemas.
44 * We are making the assumption that an XML schema representing
45 * a data model contains tables for a <strong>single</strong>
46 * database.
47 *
48 * @author <a href="mailto:jvanzyl@zenplex.com">Jason van Zyl</a>
49 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
50 */
51 public class TorqueDataModelTask extends TexenTask
52 {
53 /***
54 * XML that describes the database model, this is transformed
55 * into the application model object.
56 */
57 protected String xmlFile;
58
59 /*** Fileset of XML schemas which represent our data models. */
60 protected List filesets = new ArrayList();
61
62 /*** Data models that we collect. One from each XML schema file. */
63 protected List dataModels = new ArrayList();
64
65 /*** Velocity context which exposes our objects in the templates. */
66 protected Context context;
67
68 /***
69 * Map of data model name to database name.
70 * Should probably stick to the convention of them being the same but
71 * I know right now in a lot of cases they won't be.
72 */
73 protected Hashtable dataModelDbMap;
74
75 /***
76 * Hashtable containing the names of all the databases
77 * in our collection of schemas.
78 */
79 protected Hashtable databaseNames;
80
81
82
83
84
85
86 /***
87 * Name of the properties file that maps an SQL file
88 * to a particular database.
89 */
90 protected String sqldbmap;
91
92 /*** The target database(s) we are generating SQL for. */
93 private String targetDatabase;
94
95 /**</package-summary/html">Target Java package to place the generated files in/ *//package-summary.html">em>* Target Java package to place the generated files in. */
96 private String targetPackage;
97
98
99 /***
100 * Set the sqldbmap.
101 *
102 * @param sqldbmap th db map
103 */
104 public void setSqlDbMap(String sqldbmap)
105 {
106
107 this.sqldbmap = getProject().resolveFile(sqldbmap).toString();
108 }
109
110 /***
111 * Get the sqldbmap.
112 *
113 * @return String sqldbmap.
114 */
115 public String getSqlDbMap()
116 {
117 return sqldbmap;
118 }
119
120 /***
121 * Return the data models that have been processed.
122 *
123 * @return List data models
124 */
125 public List getDataModels()
126 {
127 return dataModels;
128 }
129
130 /***
131 * Return the data model to database name map.
132 *
133 * @return Hashtable data model name to database name map.
134 */
135 public Hashtable getDataModelDbMap()
136 {
137 return dataModelDbMap;
138 }
139
140 /***
141 * Get the xml schema describing the application model.
142 *
143 * @return String xml schema file.
144 */
145 public String getXmlFile()
146 {
147 return xmlFile;
148 }
149
150 /***
151 * Set the xml schema describing the application model.
152 *
153 * @param xmlFile The new XmlFile value
154 */
155 public void setXmlFile(String xmlFile)
156 {
157 this.xmlFile = getProject().resolveFile(xmlFile).toString();
158 }
159
160 /***
161 * Adds a set of xml schema files (nested fileset attribute).
162 *
163 * @param set a Set of xml schema files
164 */
165 public void addFileset(FileSet set)
166 {
167 filesets.add(set);
168 }
169
170 /***
171 * Get the current target database.
172 *
173 * @return String target database(s)
174 */
175 public String getTargetDatabase()
176 {
177 return targetDatabase;
178 }
179
180 /***
181 * Set the current target database. (e.g. mysql, oracle, ..)
182 *
183 * @param v target database(s)
184 */
185 public void setTargetDatabase(String v)
186 {
187 targetDatabase = v;
188 }
189
190 /***
191 * Get the current target package.
192 *
193 * @return return target java package.
194 */
195 public String getTargetPackage()
196 {
197 return targetPackage;
198 }
199
200 /***
201 * Set the current target package. This is where generated java classes will
202 * live.
203 *
204 * @param v target java package.
205 */
206 public void setTargetPackage(String v)
207 {
208 targetPackage = v;
209 }
210
211 /***
212 * Set up the initial context for generating the SQL from the XML schema.
213 *
214 * @return the context
215 * @throws Exception
216 */
217 public Context initControlContext() throws Exception
218 {
219 XmlToAppData xmlParser;
220
221 if (xmlFile == null && filesets.isEmpty())
222 {
223 throw new BuildException("You must specify an XML schema or "
224 + "fileset of XML schemas!");
225 }
226
227 try
228 {
229 if (xmlFile != null)
230 {
231
232
233 xmlParser = new XmlToAppData(getTargetDatabase(),
234 getTargetPackage());
235 Database ad = xmlParser.parseFile(xmlFile);
236 ad.setFileName(grokName(xmlFile));
237 dataModels.add(ad);
238 }
239 else
240 {
241
242 for (int i = 0; i < filesets.size(); i++)
243 {
244 FileSet fs = (FileSet) filesets.get(i);
245 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
246 File srcDir = fs.getDir(getProject());
247
248 String[] dataModelFiles = ds.getIncludedFiles();
249
250
251 for (int j = 0; j < dataModelFiles.length; j++)
252 {
253 File f = new File(srcDir, dataModelFiles[j]);
254 xmlParser = new XmlToAppData(getTargetDatabase(),
255 getTargetPackage());
256 Database ad = xmlParser.parseFile(f.toString());
257 ad.setFileName(grokName(f.toString()));
258 dataModels.add(ad);
259 }
260 }
261 }
262
263 Iterator i = dataModels.iterator();
264 databaseNames = new Hashtable();
265 dataModelDbMap = new Hashtable();
266
267
268
269 while (i.hasNext())
270 {
271 Database database = (Database) i.next();
272 databaseNames.put(database.getName(), database.getName());
273 dataModelDbMap.put(database.getFileName(), database.getName());
274 }
275 }
276 catch (EngineException ee)
277 {
278 throw new BuildException(ee);
279 }
280
281 context = new VelocityContext();
282
283
284
285 context.put("dataModels", dataModels);
286 context.put("databaseNames", databaseNames);
287 context.put("targetDatabase", targetDatabase);
288 context.put("targetPackage", targetPackage);
289
290 return context;
291 }
292
293 /***
294 * Change type of "now" to java.util.Date
295 *
296 * @see org.apache.velocity.texen.ant.TexenTask#populateInitialContext(org.apache.velocity.context.Context)
297 */
298 protected void populateInitialContext(Context context) throws Exception
299 {
300 super.populateInitialContext(context);
301 context.put("now", new Date());
302 }
303
304 /***
305 * Gets a name to use for the application's data model.
306 *
307 * @param xmlFile The path to the XML file housing the data model.
308 * @return The name to use for the <code>AppData</code>.
309 */
310 private String grokName(String xmlFile)
311 {
312
313
314
315
316 String name = "data-model";
317 int i = xmlFile.lastIndexOf(System.getProperty("file.separator"));
318 if (i != -1)
319 {
320
321 i++;
322
323 int j = xmlFile.lastIndexOf('.');
324 if (i < j)
325 {
326 name = xmlFile.substring(i, j);
327 }
328 else
329 {
330
331 name = xmlFile.substring(i);
332 }
333 }
334 return name;
335 }
336
337 /***
338 * Override Texen's context properties to map the
339 * torque.xxx properties (including defaults set by the
340 * org/apache/torque/defaults.properties) to just xxx.
341 *
342 * <p>
343 * Also, move xxx.yyy properties to xxxYyy as Velocity
344 * doesn't like the xxx.yyy syntax.
345 * </p>
346 *
347 * @param file the file to read the properties from
348 */
349 public void setContextProperties(String file)
350 {
351 super.setContextProperties(file);
352
353
354 Hashtable env = super.getProject().getProperties();
355 for (Iterator i = env.entrySet().iterator(); i.hasNext();)
356 {
357 Map.Entry entry = (Map.Entry) i.next();
358 String key = (String) entry.getKey();
359 if (key.startsWith("torque."))
360 {
361 String newKey = key.substring("torque.".length());
362 int j = newKey.indexOf(".");
363 while (j != -1)
364 {
365 newKey =
366 newKey.substring(0, j)
367 + StringUtils.capitalize(newKey.substring(j + 1));
368 j = newKey.indexOf(".");
369 }
370
371 contextProperties.setProperty(newKey, entry.getValue());
372 }
373 }
374 }
375 }