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