All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.torque.task.TorqueDataModelTask Maven / Gradle / Ivy

package org.apache.torque.task;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.apache.torque.engine.EngineException;
import org.apache.torque.engine.database.model.Database;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.context.Context;
import org.apache.texen.ant.TexenTask;
import org.kuali.core.db.torque.DatabaseParser;
import org.kuali.core.db.torque.KualiXmlToAppData;

/**
 * A base torque task that uses either a single XML schema representing a data model, or a <fileset> of XML
 * schemas. We are making the assumption that an XML schema representing a data model contains tables for a
 * single database.
 * 
 * @author Jason van Zyl
 * @author Daniel Rall
 */
public class TorqueDataModelTask extends TexenTask {
	/**
	 * XML that describes the database model, this is transformed into the application model object.
	 */
	protected String xmlFile;

	/** Fileset of XML schemas which represent our data models. */
	protected List filesets = new ArrayList();

	/** Data models that we collect. One from each XML schema file. */
	protected List dataModels = new ArrayList();

	/** Velocity context which exposes our objects in the templates. */
	protected Context context;

	/**
	 * Map of data model name to database name. Should probably stick to the convention of them being the same but I
	 * know right now in a lot of cases they won't be.
	 */
	protected Hashtable dataModelDbMap;

	/**
	 * Hashtable containing the names of all the databases in our collection of schemas.
	 */
	protected Hashtable databaseNames;

	// !! This is probably a crappy idea having the sql file -> db map
	// here. I can't remember why I put it here at the moment ...
	// maybe I was going to map something else. It can probably
	// move into the SQL task.

	/**
	 * Name of the properties file that maps an SQL file to a particular database.
	 */
	protected String sqldbmap;

	/** The target database(s) we are generating SQL for. */
	private String targetDatabase;

	/** Target Java package to place the generated files in. */
	private String targetPackage;

	/**
	 * Set the sqldbmap.
	 * 
	 * @param sqldbmap
	 *            th db map
	 */
	public void setSqlDbMap(String sqldbmap) {
		// !! Make all these references files not strings.
		this.sqldbmap = getProject().resolveFile(sqldbmap).toString();
	}

	/**
	 * Get the sqldbmap.
	 * 
	 * @return String sqldbmap.
	 */
	public String getSqlDbMap() {
		return sqldbmap;
	}

	/**
	 * Return the data models that have been processed.
	 * 
	 * @return List data models
	 */
	public List getDataModels() {
		return dataModels;
	}

	/**
	 * Return the data model to database name map.
	 * 
	 * @return Hashtable data model name to database name map.
	 */
	public Hashtable getDataModelDbMap() {
		return dataModelDbMap;
	}

	/**
	 * Get the xml schema describing the application model.
	 * 
	 * @return String xml schema file.
	 */
	public String getXmlFile() {
		return xmlFile;
	}

	/**
	 * Set the xml schema describing the application model.
	 * 
	 * @param xmlFile
	 *            The new XmlFile value
	 */
	public void setXmlFile(String xmlFile) {
		this.xmlFile = xmlFile;
	}

	/**
	 * Adds a set of xml schema files (nested fileset attribute).
	 * 
	 * @param set
	 *            a Set of xml schema files
	 */
	public void addFileset(FileSet set) {
		filesets.add(set);
	}

	/**
	 * Get the current target database.
	 * 
	 * @return String target database(s)
	 */
	public String getTargetDatabase() {
		return targetDatabase;
	}

	/**
	 * Set the current target database. (e.g. mysql, oracle, ..)
	 */
	public void setTargetDatabase(String targetDatabase) {
		this.targetDatabase = targetDatabase;
	}

	/**
	 * Get the current target package.
	 * 
	 * @return return target java package.
	 */
	public String getTargetPackage() {
		return targetPackage;
	}

	/**
	 * Set the current target package. This is where generated java classes will live.
	 */
	public void setTargetPackage(String targetPackage) {
		this.targetPackage = targetPackage;
	}

	/**
	 * Return a SAX parser that implements the DatabaseParser interface
	 */
	protected DatabaseParser getDatabaseParser() {
		return new KualiXmlToAppData(getTargetDatabase(), getTargetPackage());
	}

	/**
	 * Parse a schema XML File into a Database object
	 */
	protected Database getDataModel(File file) throws EngineException {
		// Get a handle to a parser
		DatabaseParser databaseParser = getDatabaseParser();

		// Parse the file into a database
		Database database = databaseParser.parseResource(file.toString());

		// Extract the filename
		database.setFileName(grokName(file.toString()));

		// return the database
		return database;
	}

	/**
	 * Get the list of schema XML files from our filesets
	 */
	protected List getDataModelFiles() {
		// Allocate some storage
		List dataModelFiles = new ArrayList();

		// Iterate through the filesets
		for (int i = 0; i < getFilesets().size(); i++) {
			// Extract a fileset
			FileSet fs = getFilesets().get(i);

			// Create a directory scanner
			DirectoryScanner ds = fs.getDirectoryScanner(getProject());

			// Figure out the directory to scan
			File srcDir = fs.getDir(getProject());

			// Scan the directory
			String[] dataModelFilesArray = ds.getIncludedFiles();

			// Add each file in the directory to our list
			for (int j = 0; j < dataModelFilesArray.length; j++) {
				File file = new File(srcDir, dataModelFilesArray[j]);
				dataModelFiles.add(file);
			}
		}

		// Return the list of schema.xml files
		return dataModelFiles;
	}

	/**
	 * Parse schema XML files into Database objects
	 */
	protected List getPopulatedDataModels() throws EngineException {
		// Allocate some storage
		List databases = new ArrayList();

		// Only one file to parse
		if (getXmlFile() != null) {
			// Parse the file into a database object
			Database database = getDataModel(new File(getXmlFile()));
			// Add it to our list
			databases.add(database);
			// we are done
			return databases;
		}

		// Get the list of schema XML files to parse from our filesets
		List dataModelFiles = getDataModelFiles();
		// Iterate through the list, parsing each schema.xml file into a database object
		for (File dataModelFile : dataModelFiles) {
			// Parse a schema.xml file into a database object
			Database database = getDataModel(dataModelFile);
			// Add the database object to our list
			databases.add(database);
		}
		// Return the list of database objects
		return databases;
	}

	/**
	 * Set up the initial context for generating SQL
	 * 
	 * @return the context
	 * @throws Exception
	 */
	public Context initControlContext() throws Exception {
		if (xmlFile == null && filesets.isEmpty()) {
			throw new BuildException("You must specify an XML schema or fileset of XML schemas!");
		}

		try {
			dataModels = getPopulatedDataModels();
		} catch (EngineException ee) {
			throw new BuildException(ee);
		}

		Iterator i = dataModels.iterator();
		databaseNames = new Hashtable();
		dataModelDbMap = new Hashtable();

		// Different datamodels may state the same database
		// names, we just want the unique names of databases.
		while (i.hasNext()) {
			Database database = i.next();
			databaseNames.put(database.getName(), database.getName());
			dataModelDbMap.put(database.getFileName(), database.getName());
		}

		context = new VelocityContext();

		// Place our set of data models into the context along
		// with the names of the databases as a convenience for now.
		context.put("dataModels", dataModels);
		context.put("databaseNames", databaseNames);
		context.put("targetDatabase", targetDatabase);
		context.put("targetPackage", targetPackage);

		return context;
	}

	/**
	 * Change type of "now" to java.util.Date
	 * 
	 * @see org.apache.velocity.texen.ant.TexenTask#populateInitialContext(org.apache.velocity.context.Context)
	 */
	protected void populateInitialContext(Context context) throws Exception {
		super.populateInitialContext(context);
		context.put("now", new Date());
	}

	/**
	 * Gets a name to use for the application's data model.
	 * 
	 * @param xmlFile
	 *            The path to the XML file housing the data model.
	 * @return The name to use for the AppData.
	 */
	private String grokName(String xmlFile) {
		// This can't be set from the file name as it is an unreliable
		// method of naming the descriptor. Not everyone uses the same
		// method as I do in the TDK. jvz.

		String name = "data-model";
		int i = xmlFile.lastIndexOf(System.getProperty("file.separator"));
		if (i != -1) {
			// Creep forward to the start of the file name.
			i++;

			int j = xmlFile.lastIndexOf('.');
			if (i < j) {
				name = xmlFile.substring(i, j);
			} else {
				// Weirdo
				name = xmlFile.substring(i);
			}
		}
		return name;
	}

	/**
	 * Override Texen's context properties to map the torque.xxx properties (including defaults set by the
	 * org/apache/torque/defaults.properties) to just xxx.
	 * 
	 * 

* Also, move xxx.yyy properties to xxxYyy as Velocity doesn't like the xxx.yyy syntax. *

* * @param file * the file to read the properties from */ public void setContextProperties(String file) { super.setContextProperties(file); // Map the torque.xxx elements from the env to the contextProperties Hashtable env = super.getProject().getProperties(); for (Iterator i = env.entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); String key = (String) entry.getKey(); if (key.startsWith("torque.")) { String newKey = key.substring("torque.".length()); int j = newKey.indexOf("."); while (j != -1) { newKey = newKey.substring(0, j) + StringUtils.capitalize(newKey.substring(j + 1)); j = newKey.indexOf("."); } contextProperties.setProperty(newKey, entry.getValue()); } } } public List getFilesets() { return filesets; } public void setFilesets(List filesets) { this.filesets = filesets; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy