All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.kuali.core.db.torque.KualiXmlToAppData Maven / Gradle / Ivy
package org.kuali.core.db.torque;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Stack;
import java.util.Vector;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.torque.engine.EngineException;
import org.apache.torque.engine.database.model.Column;
import org.apache.torque.engine.database.model.Domain;
import org.apache.torque.engine.database.model.ForeignKey;
import org.apache.torque.engine.database.model.Index;
import org.apache.torque.engine.database.model.Table;
import org.apache.torque.engine.database.model.Unique;
import org.apache.torque.engine.database.transform.DTDResolver;
import org.kuali.common.impex.KualiDatabase;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
public class KualiXmlToAppData extends DefaultHandler implements DatabaseParser {
/** Logging class from commons.logging */
private static Log log = LogFactory.getLog(KualiXmlToAppData.class);
private KualiDatabase database;
private Table currTable;
// private View currView;
// private Sequence currSequence;
private Column currColumn;
private ForeignKey currFK;
private Index currIndex;
private Unique currUnique;
private boolean firstPass;
private boolean isExternalSchema;
private String currentPackage;
private String currentXmlFile;
private String defaultPackage;
private static SAXParserFactory saxFactory;
/** remember all files we have already parsed to detect looping. */
private Vector alreadyReadFiles;
/** this is the stack to store parsing data */
private Stack parsingStack = new Stack();
static {
saxFactory = SAXParserFactory.newInstance();
saxFactory.setValidating(true);
}
/**
* Creates a new instance for the specified database type.
*
* @param databaseType
* The type of database for the application.
*/
public KualiXmlToAppData(String databaseType) {
database = new KualiDatabase(databaseType);
firstPass = true;
}
/**
* Creates a new instance for the specified database type.
*
* @param databaseType
* The type of database for the application.
* @param defaultPackage
* the default java package used for the om
*/
public KualiXmlToAppData(String databaseType, String defaultPackage) {
database = new KualiDatabase(databaseType);
this.defaultPackage = defaultPackage;
firstPass = true;
}
protected InputStream getInputStream(String xmlFile) throws IOException {
File file = new File(xmlFile);
if (file.exists()) {
return new BufferedInputStream(new FileInputStream(file));
}
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource resource = loader.getResource(xmlFile);
if (resource.exists()) {
return resource.getInputStream();
}
throw new IOException("Unable to locate " + xmlFile);
}
/**
* Parses a XML input file and returns a newly created and populated Database structure.
*
* @param xmlFile
* The input file to parse.
* @return Database populated by xmlFile
.
*/
@Override
public KualiDatabase parseResource(String location) throws EngineException {
try {
// in case I am missing something, make it obvious
if (!firstPass) {
throw new Error("No more double pass");
}
// check to see if we alread have parsed the file
if ((alreadyReadFiles != null) && alreadyReadFiles.contains(location)) {
return database;
} else if (alreadyReadFiles == null) {
alreadyReadFiles = new Vector(3, 1);
}
// remember the file to avoid looping
alreadyReadFiles.add(location);
currentXmlFile = location;
saxFactory.setValidating(false);
SAXParser parser = saxFactory.newSAXParser();
InputStream in = null;
try {
in = getInputStream(location);
InputSource is = new InputSource(in);
is.setSystemId(location);
parser.parse(is, this);
} finally {
IOUtils.closeQuietly(in);
}
} catch (SAXParseException e) {
throw new EngineException("Sax error on line " + e.getLineNumber() + " column " + e.getColumnNumber() + " : " + e.getMessage(), e);
} catch (Exception e) {
throw new EngineException(e);
}
if (!isExternalSchema) {
firstPass = false;
}
database.doFinalInitialization();
return database;
}
/**
* EntityResolver implementation. Called by the XML parser
*
* @param publicId
* The public identifier of the external entity
* @param systemId
* The system identifier of the external entity
* @return an InputSource for the database.dtd file
* @see DTDResolver#resolveEntity(String, String)
*/
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
try {
return new ImpexDTDResolver().resolveEntity(publicId, systemId);
} catch (Exception e) {
throw new SAXException(e);
}
}
/**
* Handles opening elements of the xml file.
*
* @param uri
* @param localName
* The local name (without prefix), or the empty string if Namespace processing is not being performed.
* @param rawName
* The qualified name (with prefix), or the empty string if qualified names are not available.
* @param attributes
* The specified or defaulted attributes
*/
@Override
public void startElement(String uri, String localName, String rawName, Attributes attributes) throws SAXException {
try {
if (rawName.equals("database")) {
if (isExternalSchema) {
currentPackage = attributes.getValue("package");
if (currentPackage == null) {
currentPackage = defaultPackage;
}
} else {
database.loadFromXML(attributes);
if (database.getPackage() == null) {
database.setPackage(defaultPackage);
}
}
} else if (rawName.equals("external-schema")) {
String xmlFile = attributes.getValue("filename");
if (xmlFile.charAt(0) != '/') {
File f = new File(currentXmlFile);
xmlFile = new File(f.getParent(), xmlFile).getPath();
}
// put current state onto the stack
ParseStackElement.pushState(this);
isExternalSchema = true;
parseResource(xmlFile);
// get the last state from the stack
ParseStackElement.popState(this);
} else if (rawName.equals("domain")) {
Domain domain = new Domain();
domain.loadFromXML(attributes, database.getPlatform());
database.addDomain(domain);
} else if (rawName.equals("table")) {
currTable = database.addTable(attributes);
if (isExternalSchema) {
currTable.setForReferenceOnly(true);
currTable.setPackage(currentPackage);
}
} else if (rawName.equals("view")) {
database.addView(attributes);
} else if (rawName.equals("sequence")) {
database.addSequence(attributes);
} else if (rawName.equals("column")) {
currColumn = currTable.addColumn(attributes);
} else if (rawName.equals("inheritance")) {
currColumn.addInheritance(attributes);
} else if (rawName.equals("foreign-key")) {
currFK = currTable.addForeignKey(attributes);
} else if (rawName.equals("reference")) {
currFK.addReference(attributes);
} else if (rawName.equals("index")) {
currIndex = currTable.addIndex(attributes);
} else if (rawName.equals("index-column")) {
currIndex.addColumn(attributes);
} else if (rawName.equals("unique")) {
currUnique = currTable.addUnique(attributes);
} else if (rawName.equals("unique-column")) {
currUnique.addColumn(attributes);
} else if (rawName.equals("id-method-parameter")) {
currTable.addIdMethodParameter(attributes);
} else if (rawName.equals("option")) {
setOption(attributes);
}
} catch (Exception e) {
throw new SAXException(e);
}
}
/**
* Handles closing elements of the xml file.
*
* @param uri
* @param localName
* The local name (without prefix), or the empty string if Namespace processing is not being performed.
* @param rawName
* The qualified name (with prefix), or the empty string if qualified names are not available.
*/
@Override
public void endElement(String uri, String localName, String rawName) throws SAXException {
if (log.isDebugEnabled()) {
log.debug("endElement(" + uri + ", " + localName + ", " + rawName + ") called");
}
try {
// Reset working objects to null to allow option to know
// which element it is associated with.
if (rawName.equals("table")) {
currTable = null;
} else if (rawName.equals("view")) {
// currView = null;
} else if (rawName.equals("sequence")) {
// currSequence = null;
} else if (rawName.equals("column")) {
currColumn = null;
} else if (rawName.equals("foreign-key")) {
currFK = null;
} else if (rawName.equals("index")) {
currIndex = null;
} else if (rawName.equals("unique")) {
currUnique = null;
}
} catch (Exception e) {
throw new SAXException(e);
}
}
public void setOption(Attributes attributes) {
// Look thru supported model elements in reverse order to
// find one that this option statement applies to.
String key = attributes.getValue("key");
String value = attributes.getValue("value");
if (currUnique != null) {
currUnique.addOption(key, value);
} else if (currIndex != null) {
currIndex.addOption(key, value);
} else if (currFK != null) {
currFK.addOption(key, value);
} else if (currColumn != null) {
currColumn.addOption(key, value);
} else if (currTable != null) {
currTable.addOption(key, value);
} else { // Must be a db level option.
database.addOption(key, value);
}
}
/**
* Handles exception which occur when the xml file is parsed
*
* @param e
* the exception which occured while parsing
* @throws SAXException
* always
*/
@Override
public void error(SAXParseException e) throws SAXException {
log.error("Sax parser threw an Exception", e);
throw new SAXException("Error while parsing " + currentXmlFile + " at line " + e.getLineNumber() + " column " + e.getColumnNumber() + " : " + e.getMessage());
}
/**
* When parsing multiple files that use nested tags we need to use a stack to remember some values.
*/
private static class ParseStackElement {
private boolean isExternalSchema;
private String currentPackage;
private String currentXmlFile;
private boolean firstPass;
/**
*
* @param parser
*/
public ParseStackElement(KualiXmlToAppData parser) {
// remember current state of parent object
isExternalSchema = parser.isExternalSchema;
currentPackage = parser.currentPackage;
currentXmlFile = parser.currentXmlFile;
firstPass = parser.firstPass;
// push the state onto the stack
parser.parsingStack.push(this);
}
/**
* Removes the top element from the stack and activates the stored state
*
* @param parser
*/
public static void popState(KualiXmlToAppData parser) {
if (!parser.parsingStack.isEmpty()) {
ParseStackElement elem = (ParseStackElement) parser.parsingStack.pop();
// activate stored state
parser.isExternalSchema = elem.isExternalSchema;
parser.currentPackage = elem.currentPackage;
parser.currentXmlFile = elem.currentXmlFile;
parser.firstPass = elem.firstPass;
}
}
/**
* Stores the current state on the top of the stack.
*
* @param parser
*/
public static void pushState(KualiXmlToAppData parser) {
new ParseStackElement(parser);
}
}
}