/*******************************************************************************
* Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* File: $Source: /cvsroot/slrp/common/com.ibm.adtech.jdbc.utils/src/com/ibm/adtech/jdbc/utils/opgen/ant/CompositionTask.java,v $
* Created by: Joe Betz
* Created on: 9/30/2005
* Revision: $Id: CompositionTask.java 176 2007-07-31 14:22:30Z mroy $
*
* Contributors:
* IBM Corporation - initial API and implementation
* Cambridge Semantics Incorporated - Fork to Anzo
*******************************************************************************/
package org.openanzo.jdbc.opgen.ant;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.security.InvalidParameterException;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.FileSet;
import org.openanzo.jdbc.opgen.RdbStatement;
import org.openanzo.jdbc.opgen.RdbStatementSet;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
/**
* An ant task to reads in rdb statements (SQL, DDL, etc.) from files (as specified in the ant file) and composes Anzo SQL Files (i.e. DB2.sql) as well as
* generates java rdb statement wrapper files.
*
* @author Joe Betz
*
*/
public class CompositionTask extends MatchingTask {
List<PSTask> psTasks = new Vector<PSTask>();
List<DDLTask> ddlTasks = new Vector<DDLTask>();
File destinationFile;
private String outputFormat;
/**
* Create a new composition task
*/
public CompositionTask() {
}
/**
* Add a ddl task to this task
*
* @param ddlTask
* to add
*/
public void addDDL(DDLTask ddlTask) {
this.ddlTasks.add(ddlTask);
}
/**
* Add a preparedStatement task to this task
*
* @param ps
* preparedStatement task to add
*/
public void addPreparedStatements(PSTask ps) {
this.psTasks.add(ps);
}
/**
* Set the destination file
*
* @param destinationFile
* to which this sql is written
*/
public void setDestdir(File destinationFile) {
this.destinationFile = destinationFile;
}
@Override
public void execute() throws BuildException {
writeSQL();
}
private void writeSQL() throws FactoryConfigurationError {
try {
Writer writer = null;
if (destinationFile == null) {
writer = new StringWriter();
} else {
writer = new OutputStreamWriter(new FileOutputStream(destinationFile), "UTF-8");
}
writer.write("#*******************************************************************************\n");
writer.write("# Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated.\n");
writer.write("# All rights reserved. This program and the accompanying materials\n");
writer.write("# are made available under the terms of the Eclipse Public License v1.0\n");
writer.write("# which accompanies this distribution, and is available at\n");
writer.write("# http://www.eclipse.org/legal/epl-v10.html\n");
writer.write("# \n");
writer.write("# File: $Source: /cvsroot/slrp/common/com.ibm.adtech.jdbc.utils/src/com/ibm/adtech/jdbc/utils/opgen/ant/CompositionTask.java,v $\n");
writer.write("# Created by: Generated by Composition Ant Task\n");
writer.write("# Created on: " + DateFormat.getDateInstance(DateFormat.SHORT).format(Calendar.getInstance().getTime()) + "\n");
writer.write("# Revision: $Id: CompositionTask.java 176 2007-07-31 14:22:30Z mroy $\n");
writer.write("# \n");
writer.write("# Contributors:\n");
writer.write("# IBM Corporation - initial API and implementation\n");
writer.write("#*******************************************************************************\n");
writer.write("#\n");
writer.write("#\n");
for (Iterator<DDLTask> iter = ddlTasks.iterator(); iter.hasNext();) {
DDLTask task = iter.next();
task.write(writer, outputFormat);
}
for (Iterator<PSTask> iter = psTasks.iterator(); iter.hasNext();) {
PSTask task = iter.next();
task.write(writer, outputFormat);
}
writer.flush();
writer.close();
} catch (Exception e) {
throw new BuildException(e);
}
}
/**
* Set the outputStream for this task
*
* @param outputFormat
* for this task
*/
public void setOutputFormat(String outputFormat) {
this.outputFormat = outputFormat;
}
/**
* Set the output format for this task
*
* @return the output format for this task
*/
public String getOutputFormat() {
return outputFormat;
}
/**
* Provides file listings of prepared statements.
*
* @author Joe Betz
*
*/
public static class PSTask extends Task {
List<FileSet> fileSets = new Vector<FileSet>();
String javaClass;
String destBase;
String rethrowExceptionName = "org.openanzo.jdbc.utils.RdbException";
private boolean excludeNamespace = false;
private boolean rethrowSQLException = false;
/**
* Add a fileset to this task
*
* @param fileSet
* to add
*/
public void addFileset(FileSet fileSet) {
fileSets.add(fileSet);
}
/**
* Set the type of exception to use in generated code
*
* @param rethrowExceptionName
* type of exception to use in generated code
*/
public void setException(String rethrowExceptionName) {
this.rethrowExceptionName = rethrowExceptionName;
}
/**
* Get the files that make up the fileset for this task
*
* @return the files that make up the fileset for this task
*/
public List<FileSet> getFiles() {
return fileSets;
}
/**
* Set the name for the class
*
* @param javaClass
* the name for the class
*/
public void setJavaClass(String javaClass) {
this.javaClass = javaClass;
}
/**
* Get the name for the class
*
* @return the name for the class
*/
public String getJavaClass() {
return javaClass;
}
/**
* Set the destination directory
*
* @param destBase
* the destination directory
*/
public void setDestBase(String destBase) {
this.destBase = destBase;
}
/**
* Get the destination directory
*
* @return the destination directory
*/
public String getDestBase() {
return destBase;
}
@Override
public void execute() {
}
/**
* Write out the transformed SQL file
*
* @param writer
* output writer used to write file
* @param outputFormat
* format of output file
* @throws FileNotFoundException
* @throws IOException
* @throws ParserConfigurationException
* @throws FactoryConfigurationError
* @throws SAXException
*/
public void write(Writer writer, String outputFormat) throws FileNotFoundException, IOException, ParserConfigurationException, FactoryConfigurationError, SAXException {
Map<String, String> map = new HashMap<String, String>();
for (Iterator<FileSet> setIter = getFiles().iterator(); setIter.hasNext();) {
FileSet set = setIter.next();
DirectoryScanner ds = set.getDirectoryScanner(getProject());
String files[] = ds.getIncludedFiles();
String base = ds.getBasedir().getAbsolutePath();
for (int i = 0; i < files.length; i++) {
String filename = files[i];
String file = base + "/" + filename;
map.putAll(getXmlSqlStatements(filename, file));
generateXmlSqlWrappers(filename, file);
}
}
for (Map.Entry<String, String> entry : map.entrySet()) {
writer.write(entry.getKey());
writer.write("=");
writer.write(entry.getValue());
writer.write("\n");
}
}
/**
* Get the set of SQL statements from a file
*
* @param filename
* name of file to generate
* @param file
* file containing input
* @return map of statements to their text
* @throws FileNotFoundException
* @throws IOException
* @throws ParserConfigurationException
* @throws FactoryConfigurationError
* @throws SAXException
*/
private Map<String, String> getXmlSqlStatements(String filename, String file) throws FileNotFoundException, IOException, ParserConfigurationException, FactoryConfigurationError, SAXException {
Map<String, String> map = new HashMap<String, String>();
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
File f = new File(file);
Document document = builder.parse(f.toURI().toString());
Element el = document.getDocumentElement();
String sqlPackageName;
if (isExcludeNamespace()) {
sqlPackageName = "";
} else {
sqlPackageName = filename.replaceFirst("\\.sql$", "");
}
RdbStatementSet preparedStatements = new RdbStatementSet(sqlPackageName, el);
for (RdbStatement preparedStatement : preparedStatements.getList()) {
String text = Pattern.compile("([\\s]+)").matcher(preparedStatement.getSql()).replaceAll(" ").trim();
text = Pattern.compile(";\\z").matcher(text).replaceAll("");
map.put(preparedStatement.getQualifiedName(), text);
}
return map;
}
private void generateXmlSqlWrappers(String filename, String file) throws FileNotFoundException, IOException, ParserConfigurationException, FactoryConfigurationError, SAXException {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
File f = new File(file);
Document document = builder.parse(f.toURI().toString());
Element el = document.getDocumentElement();
String sqlPackageName;
if (isExcludeNamespace()) {
sqlPackageName = "";
} else {
sqlPackageName = filename.replaceFirst("\\.sql$", "");
}
RdbStatementSet preparedStatements = new RdbStatementSet(sqlPackageName, el);
if (destBase != null || javaClass != null) {
if (destBase == null)
throw new InvalidParameterException("javaclass set on 'preparedstatements' task so destbase must be set.");
if (javaClass == null)
throw new InvalidParameterException("destbase set on 'preparedstatements' task so javaclass must be set.");
int lastDot = javaClass.lastIndexOf(".");
String packageName = javaClass.substring(0, lastDot);
String className = javaClass.substring(lastDot + 1, javaClass.length());
String path = destBase + packageName.replace('.', '/');
new File(path).mkdirs();
String fileName = path + "/" + className + ".java";
File destFile = new File(fileName);
preparedStatements.writeJavaStub(destFile, className, packageName, rethrowExceptionName, rethrowSQLException);
}
}
/**
* Set whether to exclude the namespace of the sql statements
*
* @param excludeNamespace
* whether to exclude the namespace of the sql statements
*/
public void setExcludeNamespace(boolean excludeNamespace) {
this.excludeNamespace = excludeNamespace;
}
/**
* Return true if parser should ignore the namespce of the sql statements
*
* @return true if parser should ignore the namespce of the sql statements
*/
public boolean isExcludeNamespace() {
return excludeNamespace;
}
/**
* Set if SQL exceptions should be rethrown or wrapped
*
* @param rethrowSQLException
* if SQL exceptions should be rethrown or wrapped
*/
public void setRethrowSQLException(boolean rethrowSQLException) {
this.rethrowSQLException = rethrowSQLException;
}
/**
* Get if SQL exceptions should be rethrown or wrapped
*
* @return true if SQL exceptions should be rethrown, else wrapped
*/
public boolean isRethrowSQLException() {
return rethrowSQLException;
}
}
}