Coverage Report - org.apache.torque.task.TorqueDataModelTask
 
Classes in this File Line Coverage Branch Coverage Complexity
TorqueDataModelTask
0%
0/154
0%
0/50
1.703
 
 1  
 package org.apache.torque.task;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 5  
  * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 7  
  * License. You may obtain a copy of the License at
 8  
  * 
 9  
  * http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 12  
  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 13  
  * specific language governing permissions and limitations under the License.
 14  
  */
 15  
 
 16  
 import java.io.File;
 17  
 import java.util.ArrayList;
 18  
 import java.util.Date;
 19  
 import java.util.Hashtable;
 20  
 import java.util.Iterator;
 21  
 import java.util.List;
 22  
 import java.util.Map;
 23  
 
 24  
 import org.apache.commons.lang.StringUtils;
 25  
 import org.apache.texen.ant.TexenTask;
 26  
 import org.apache.tools.ant.BuildException;
 27  
 import org.apache.tools.ant.DirectoryScanner;
 28  
 import org.apache.tools.ant.types.FileSet;
 29  
 import org.apache.torque.engine.EngineException;
 30  
 import org.apache.torque.engine.database.model.Database;
 31  
 import org.apache.torque.engine.database.model.Table;
 32  
 import org.apache.velocity.VelocityContext;
 33  
 import org.apache.velocity.context.Context;
 34  
 import org.kuali.core.db.torque.DatabaseParser;
 35  
 import org.kuali.core.db.torque.KualiXmlToAppData;
 36  
 import org.kuali.core.db.torque.StringFilter;
 37  
 import org.kuali.core.db.torque.pojo.KualiDatabase;
 38  
 import org.kuali.core.db.torque.pojo.Sequence;
 39  
 import org.kuali.core.db.torque.pojo.View;
 40  
 
 41  
 /**
 42  
  * A base torque task that uses either a single XML schema representing a data model, or a <fileset> of XML
 43  
  * schemas. We are making the assumption that an XML schema representing a data model contains tables for a
 44  
  * <strong>single</strong> database.
 45  
  * 
 46  
  * @author <a href="mailto:jvanzyl@zenplex.com">Jason van Zyl</a>
 47  
  * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
 48  
  */
 49  0
 public class TorqueDataModelTask extends TexenTask {
 50  
     List<String> tblIncludes;
 51  
     List<String> tblExcludes;
 52  
     List<String> vIncludes;
 53  
     List<String> sIncludes;
 54  
     List<String> vExcludes;
 55  
     List<String> sExcludes;
 56  
 
 57  
     /**
 58  
      * XML that describes the database model, this is transformed into the application model object.
 59  
      */
 60  
     protected String xmlFile;
 61  
 
 62  
     /** Fileset of XML schemas which represent our data models. */
 63  0
     protected List<FileSet> filesets = new ArrayList<FileSet>();
 64  
 
 65  
     /** Data models that we collect. One from each XML schema file. */
 66  0
     protected List<Database> dataModels = new ArrayList<Database>();
 67  
 
 68  
     /** Velocity context which exposes our objects in the templates. */
 69  
     protected Context context;
 70  
 
 71  
     /**
 72  
      * Map of data model name to database name. Should probably stick to the convention of them being the same but I
 73  
      * know right now in a lot of cases they won't be.
 74  
      */
 75  
     protected Hashtable<String, String> dataModelDbMap;
 76  
 
 77  
     /**
 78  
      * Hashtable containing the names of all the databases in our collection of schemas.
 79  
      */
 80  
     protected Hashtable<String, String> databaseNames;
 81  
 
 82  
     // !! This is probably a crappy idea having the sql file -> db map
 83  
     // here. I can't remember why I put it here at the moment ...
 84  
     // maybe I was going to map something else. It can probably
 85  
     // move into the SQL task.
 86  
 
 87  
     /**
 88  
      * Name of the properties file that maps an SQL file 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  
     /** Target Java package to place the generated files in. */
 96  
     private String targetPackage;
 97  
 
 98  
     /**
 99  
      * Set the sqldbmap.
 100  
      * 
 101  
      * @param sqldbmap
 102  
      *            th db map
 103  
      */
 104  
     public void setSqlDbMap(String sqldbmap) {
 105  
         // !! Make all these references files not strings.
 106  0
         this.sqldbmap = getProject().resolveFile(sqldbmap).toString();
 107  0
     }
 108  
 
 109  
     /**
 110  
      * Get the sqldbmap.
 111  
      * 
 112  
      * @return String sqldbmap.
 113  
      */
 114  
     public String getSqlDbMap() {
 115  0
         return sqldbmap;
 116  
     }
 117  
 
 118  
     /**
 119  
      * Return the data models that have been processed.
 120  
      * 
 121  
      * @return List data models
 122  
      */
 123  
     public List<Database> getDataModels() {
 124  0
         return dataModels;
 125  
     }
 126  
 
 127  
     /**
 128  
      * Return the data model to database name map.
 129  
      * 
 130  
      * @return Hashtable data model name to database name map.
 131  
      */
 132  
     public Hashtable<String, String> getDataModelDbMap() {
 133  0
         return dataModelDbMap;
 134  
     }
 135  
 
 136  
     /**
 137  
      * Get the xml schema describing the application model.
 138  
      * 
 139  
      * @return String xml schema file.
 140  
      */
 141  
     public String getXmlFile() {
 142  0
         return xmlFile;
 143  
     }
 144  
 
 145  
     /**
 146  
      * Set the xml schema describing the application model.
 147  
      * 
 148  
      * @param xmlFile
 149  
      *            The new XmlFile value
 150  
      */
 151  
     public void setXmlFile(String xmlFile) {
 152  0
         this.xmlFile = xmlFile;
 153  0
     }
 154  
 
 155  
     /**
 156  
      * Adds a set of xml schema files (nested fileset attribute).
 157  
      * 
 158  
      * @param set
 159  
      *            a Set of xml schema files
 160  
      */
 161  
     public void addFileset(FileSet set) {
 162  0
         filesets.add(set);
 163  0
     }
 164  
 
 165  
     /**
 166  
      * Get the current target database.
 167  
      * 
 168  
      * @return String target database(s)
 169  
      */
 170  
     public String getTargetDatabase() {
 171  0
         return targetDatabase;
 172  
     }
 173  
 
 174  
     /**
 175  
      * Set the current target database. (e.g. mysql, oracle, ..)
 176  
      */
 177  
     public void setTargetDatabase(String targetDatabase) {
 178  0
         this.targetDatabase = targetDatabase;
 179  0
     }
 180  
 
 181  
     /**
 182  
      * Get the current target package.
 183  
      * 
 184  
      * @return return target java package.
 185  
      */
 186  
     public String getTargetPackage() {
 187  0
         return targetPackage;
 188  
     }
 189  
 
 190  
     /**
 191  
      * Set the current target package. This is where generated java classes will live.
 192  
      */
 193  
     public void setTargetPackage(String targetPackage) {
 194  0
         this.targetPackage = targetPackage;
 195  0
     }
 196  
 
 197  
     /**
 198  
      * Return a SAX parser that implements the DatabaseParser interface
 199  
      */
 200  
     protected DatabaseParser getDatabaseParser() {
 201  0
         return new KualiXmlToAppData(getTargetDatabase(), getTargetPackage());
 202  
     }
 203  
 
 204  
     /**
 205  
      * Parse a schema XML File into a Database object
 206  
      */
 207  
     protected Database getDataModel(File file) throws EngineException {
 208  
         // Get a handle to a parser
 209  0
         DatabaseParser databaseParser = getDatabaseParser();
 210  
 
 211  
         // Parse the file into a database
 212  0
         Database database = databaseParser.parseResource(file.toString());
 213  
 
 214  0
         KualiDatabase kdb = (KualiDatabase) database;
 215  
 
 216  
         // Filter out tables as needed
 217  0
         filterTables(database);
 218  
 
 219  
         // Filter out views as needed
 220  0
         filterViews(kdb);
 221  
 
 222  
         // Filter out sequences as needed
 223  0
         filterSequences(kdb);
 224  
 
 225  
         // Extract the filename
 226  0
         database.setFileName(grokName(file.toString()));
 227  
 
 228  
         // return the database
 229  0
         return database;
 230  
     }
 231  
 
 232  
     protected List<Table> getTables(Database database) {
 233  0
         List<Table> tables = new ArrayList<Table>();
 234  0
         for (Object object : database.getTables()) {
 235  0
             Table table = (Table) object;
 236  0
             tables.add(table);
 237  0
         }
 238  0
         return tables;
 239  
     }
 240  
 
 241  
     protected void filterSequences(KualiDatabase database) {
 242  0
         StringFilter filter = new StringFilter(sIncludes, sExcludes);
 243  0
         Iterator<Sequence> itr = database.getSequences().iterator();
 244  0
         while (itr.hasNext()) {
 245  0
             Sequence sequence = itr.next();
 246  0
             String name = sequence.getName();
 247  0
             boolean remove = !filter.isInclude(name) || filter.isExclude(name);
 248  0
             if (remove) {
 249  0
                 System.out.println("[INFO] Filtering out sequence " + name);
 250  0
                 itr.remove();
 251  
             }
 252  0
         }
 253  0
     }
 254  
 
 255  
     protected void filterViews(KualiDatabase database) {
 256  0
         StringFilter filter = new StringFilter(vIncludes, vExcludes);
 257  0
         Iterator<View> itr = database.getViews().iterator();
 258  0
         while (itr.hasNext()) {
 259  0
             View view = itr.next();
 260  0
             String name = view.getName();
 261  0
             boolean remove = !filter.isInclude(name) || filter.isExclude(name);
 262  0
             if (remove) {
 263  0
                 System.out.println("[INFO] Filtering out view " + name);
 264  0
                 itr.remove();
 265  
             }
 266  0
         }
 267  0
     }
 268  
 
 269  
     protected void filterTables(Database database) {
 270  0
         StringFilter filter = new StringFilter(tblIncludes, tblExcludes);
 271  0
         List<Table> tables = getTables(database);
 272  0
         for (Table table : tables) {
 273  0
             String name = table.getName();
 274  0
             boolean remove = !filter.isInclude(name) || filter.isExclude(name);
 275  0
             if (remove) {
 276  0
                 System.out.println("[INFO] Filtering out table " + name);
 277  0
                 database.removeTable(table);
 278  
             }
 279  0
         }
 280  0
     }
 281  
 
 282  
     /**
 283  
      * Get the list of schema XML files from our filesets
 284  
      */
 285  
     protected List<File> getDataModelFiles() {
 286  
         // Allocate some storage
 287  0
         List<File> dataModelFiles = new ArrayList<File>();
 288  
 
 289  
         // Iterate through the filesets
 290  0
         for (int i = 0; i < getFilesets().size(); i++) {
 291  
             // Extract a fileset
 292  0
             FileSet fs = getFilesets().get(i);
 293  
 
 294  
             // Create a directory scanner
 295  0
             DirectoryScanner ds = fs.getDirectoryScanner(getProject());
 296  
 
 297  
             // Figure out the directory to scan
 298  0
             File srcDir = fs.getDir(getProject());
 299  
 
 300  
             // Scan the directory
 301  0
             String[] dataModelFilesArray = ds.getIncludedFiles();
 302  
 
 303  
             // Add each file in the directory to our list
 304  0
             for (int j = 0; j < dataModelFilesArray.length; j++) {
 305  0
                 File file = new File(srcDir, dataModelFilesArray[j]);
 306  0
                 dataModelFiles.add(file);
 307  
             }
 308  
         }
 309  
 
 310  
         // Return the list of schema.xml files
 311  0
         return dataModelFiles;
 312  
     }
 313  
 
 314  
     /**
 315  
      * Parse schema XML files into Database objects
 316  
      */
 317  
     protected List<Database> getPopulatedDataModels() throws EngineException {
 318  
         // Allocate some storage
 319  0
         List<Database> databases = new ArrayList<Database>();
 320  
 
 321  
         // Only one file to parse
 322  0
         if (getXmlFile() != null) {
 323  
             // Parse the file into a database object
 324  0
             Database database = getDataModel(new File(getXmlFile()));
 325  
             // Add it to our list
 326  0
             databases.add(database);
 327  
             // we are done
 328  0
             return databases;
 329  
         }
 330  
 
 331  
         // Get the list of schema XML files to parse from our filesets
 332  0
         List<File> dataModelFiles = getDataModelFiles();
 333  
         // Iterate through the list, parsing each schema.xml file into a database object
 334  0
         for (File dataModelFile : dataModelFiles) {
 335  
             // Parse a schema.xml file into a database object
 336  0
             Database database = getDataModel(dataModelFile);
 337  
             // Add the database object to our list
 338  0
             databases.add(database);
 339  0
         }
 340  
         // Return the list of database objects
 341  0
         return databases;
 342  
     }
 343  
 
 344  
     /**
 345  
      * Set up the initial context for generating SQL
 346  
      * 
 347  
      * @return the context
 348  
      * @throws Exception
 349  
      */
 350  
     @Override
 351  
     public Context initControlContext() throws Exception {
 352  0
         if (xmlFile == null && filesets.isEmpty()) {
 353  0
             throw new BuildException("You must specify an XML schema or fileset of XML schemas!");
 354  
         }
 355  
 
 356  
         try {
 357  0
             dataModels = getPopulatedDataModels();
 358  0
         } catch (EngineException ee) {
 359  0
             throw new BuildException(ee);
 360  0
         }
 361  
 
 362  0
         Iterator<Database> i = dataModels.iterator();
 363  0
         databaseNames = new Hashtable<String, String>();
 364  0
         dataModelDbMap = new Hashtable<String, String>();
 365  
 
 366  
         // Different datamodels may state the same database
 367  
         // names, we just want the unique names of databases.
 368  0
         while (i.hasNext()) {
 369  0
             Database database = i.next();
 370  0
             databaseNames.put(database.getName(), database.getName());
 371  0
             dataModelDbMap.put(database.getFileName(), database.getName());
 372  0
         }
 373  
 
 374  0
         context = new VelocityContext();
 375  
 
 376  
         // Place our set of data models into the context along
 377  
         // with the names of the databases as a convenience for now.
 378  0
         context.put("dataModels", dataModels);
 379  0
         context.put("databaseNames", databaseNames);
 380  0
         context.put("targetDatabase", targetDatabase);
 381  0
         context.put("targetPackage", targetPackage);
 382  
 
 383  0
         return context;
 384  
     }
 385  
 
 386  
     /**
 387  
      * Change type of "now" to java.util.Date
 388  
      * 
 389  
      * @see org.apache.velocity.texen.ant.TexenTask#populateInitialContext(org.apache.velocity.context.Context)
 390  
      */
 391  
     @Override
 392  
     protected void populateInitialContext(Context context) throws Exception {
 393  0
         super.populateInitialContext(context);
 394  0
         context.put("now", new Date());
 395  0
     }
 396  
 
 397  
     /**
 398  
      * Gets a name to use for the application's data model.
 399  
      * 
 400  
      * @param xmlFile
 401  
      *            The path to the XML file housing the data model.
 402  
      * @return The name to use for the <code>AppData</code>.
 403  
      */
 404  
     private String grokName(String xmlFile) {
 405  
         // This can't be set from the file name as it is an unreliable
 406  
         // method of naming the descriptor. Not everyone uses the same
 407  
         // method as I do in the TDK. jvz.
 408  
 
 409  0
         String name = "data-model";
 410  0
         int i = xmlFile.lastIndexOf(System.getProperty("file.separator"));
 411  0
         if (i != -1) {
 412  
             // Creep forward to the start of the file name.
 413  0
             i++;
 414  
 
 415  0
             int j = xmlFile.lastIndexOf('.');
 416  0
             if (i < j) {
 417  0
                 name = xmlFile.substring(i, j);
 418  
             } else {
 419  
                 // Weirdo
 420  0
                 name = xmlFile.substring(i);
 421  
             }
 422  
         }
 423  0
         return name;
 424  
     }
 425  
 
 426  
     /**
 427  
      * Override Texen's context properties to map the torque.xxx properties (including defaults set by the
 428  
      * org/apache/torque/defaults.properties) to just xxx.
 429  
      * 
 430  
      * <p>
 431  
      * Also, move xxx.yyy properties to xxxYyy as Velocity doesn't like the xxx.yyy syntax.
 432  
      * </p>
 433  
      * 
 434  
      * @param file
 435  
      *            the file to read the properties from
 436  
      */
 437  
     @Override
 438  
     public void setContextProperties(String file) {
 439  0
         super.setContextProperties(file);
 440  
 
 441  
         // Map the torque.xxx elements from the env to the contextProperties
 442  0
         Hashtable<?, ?> env = super.getProject().getProperties();
 443  0
         for (Iterator<?> i = env.entrySet().iterator(); i.hasNext();) {
 444  0
             Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
 445  0
             String key = (String) entry.getKey();
 446  0
             if (key.startsWith("torque.")) {
 447  0
                 String newKey = key.substring("torque.".length());
 448  0
                 int j = newKey.indexOf(".");
 449  0
                 while (j != -1) {
 450  0
                     newKey = newKey.substring(0, j) + StringUtils.capitalize(newKey.substring(j + 1));
 451  0
                     j = newKey.indexOf(".");
 452  
                 }
 453  
 
 454  0
                 contextProperties.setProperty(newKey, entry.getValue());
 455  
             }
 456  0
         }
 457  0
     }
 458  
 
 459  
     public List<FileSet> getFilesets() {
 460  0
         return filesets;
 461  
     }
 462  
 
 463  
     public void setFilesets(List<FileSet> filesets) {
 464  0
         this.filesets = filesets;
 465  0
     }
 466  
 
 467  
     public List<String> getTblIncludes() {
 468  0
         return tblIncludes;
 469  
     }
 470  
 
 471  
     public void setTblIncludes(List<String> includes) {
 472  0
         this.tblIncludes = includes;
 473  0
     }
 474  
 
 475  
     public List<String> getTblExcludes() {
 476  0
         return tblExcludes;
 477  
     }
 478  
 
 479  
     public void setTblExcludes(List<String> excludes) {
 480  0
         this.tblExcludes = excludes;
 481  0
     }
 482  
 
 483  
     public List<String> getvIncludes() {
 484  0
         return vIncludes;
 485  
     }
 486  
 
 487  
     public void setvIncludes(List<String> vIncludes) {
 488  0
         this.vIncludes = vIncludes;
 489  0
     }
 490  
 
 491  
     public List<String> getsIncludes() {
 492  0
         return sIncludes;
 493  
     }
 494  
 
 495  
     public void setsIncludes(List<String> sIncludes) {
 496  0
         this.sIncludes = sIncludes;
 497  0
     }
 498  
 
 499  
     public List<String> getvExcludes() {
 500  0
         return vExcludes;
 501  
     }
 502  
 
 503  
     public void setvExcludes(List<String> vExcludes) {
 504  0
         this.vExcludes = vExcludes;
 505  0
     }
 506  
 
 507  
     public List<String> getsExcludes() {
 508  0
         return sExcludes;
 509  
     }
 510  
 
 511  
     public void setsExcludes(List<String> sExcludes) {
 512  0
         this.sExcludes = sExcludes;
 513  0
     }
 514  
 }