Implemented DDLUTILS-184
Created enum for the cascade settings for DDUTILS-75, and added properties to the foreign key object
git-svn-id: https://svn.apache.org/repos/asf/db/ddlutils/trunk@572524 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/.classpath b/.classpath
index ab8de05..c03a842 100644
--- a/.classpath
+++ b/.classpath
@@ -34,6 +34,5 @@
<classpathentry kind="lib" path="lib/build-only/junit-3.8.2.jar"/>
<classpathentry kind="lib" path="lib/stax-api-1.0.1.jar"/>
<classpathentry kind="lib" path="lib/log4j-1.2.8.jar"/>
- <classpathentry kind="lib" path="lib/commons-betwixt-0.8.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
diff --git a/lib/commons-betwixt-0.8.jar b/lib/commons-betwixt-0.8.jar
deleted file mode 100644
index ab00040..0000000
--- a/lib/commons-betwixt-0.8.jar
+++ /dev/null
Binary files differ
diff --git a/src/java/org/apache/ddlutils/io/DataWriter.java b/src/java/org/apache/ddlutils/io/DataWriter.java
index 8d5d9d6..b90b06c 100644
--- a/src/java/org/apache/ddlutils/io/DataWriter.java
+++ b/src/java/org/apache/ddlutils/io/DataWriter.java
@@ -20,7 +20,6 @@
*/
import java.io.OutputStream;
-import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
@@ -29,10 +28,6 @@
import java.util.List;
import java.util.Map;
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
@@ -51,27 +46,17 @@
*
* @version $Revision: 289996 $
*/
-public class DataWriter
+public class DataWriter extends PrettyPrintingXmlWriter
{
/** String values with a size not bigger than this value will be written to attributes;
if their size is longer, then a sub element is generated instead. */
private static final int MAX_ATTRIBUTE_LENGTH = 255;
- /** The indentation string. */
- private static final String INDENT_STRING = " ";
/** Our log. */
private final Log _log = LogFactory.getLog(DataWriter.class);
/** The converters. */
private ConverterConfiguration _converterConf = new ConverterConfiguration();
- /** The output stream. */
- private PrintWriter _output;
- /** The xml writer. */
- private XMLStreamWriter _writer;
- /** The output encoding. */
- private String _encoding;
- /** Whether we're pretty-printing. */
- private boolean _prettyPrinting = true;
/**
* Creates a data writer instance using UTF-8 encoding.
@@ -91,26 +76,7 @@
*/
public DataWriter(OutputStream output, String encoding) throws DataWriterException
{
- _output = new PrintWriter(output);
- if ((encoding == null) || (encoding.length() == 0))
- {
- _encoding = "UTF-8";
- }
- else
- {
- _encoding = encoding;
- }
-
- try
- {
- XMLOutputFactory factory = XMLOutputFactory.newInstance();
-
- _writer = factory.createXMLStreamWriter(output, _encoding);
- }
- catch (XMLStreamException ex)
- {
- throw new DataWriterException(ex);
- }
+ super(output, encoding);
}
/**
@@ -122,38 +88,15 @@
*/
public DataWriter(Writer output, String encoding) throws DataWriterException
{
- _output = new PrintWriter(output);
- _encoding = encoding;
- try
- {
- XMLOutputFactory factory = XMLOutputFactory.newInstance();
-
- _writer = factory.createXMLStreamWriter(_output);
- }
- catch (XMLStreamException ex)
- {
- throw new DataWriterException(ex);
- }
+ super(output, encoding);
}
/**
- * Determines whether the output shall be pretty-printed.
- *
- * @return <code>true</code> if the output is pretty-printed
+ * {@inheritDoc}
*/
- public boolean isPrettyPrinting()
+ protected void throwException(Exception baseEx) throws DdlUtilsXMLException
{
- return _prettyPrinting;
- }
-
- /**
- * Specifies whether the output shall be pretty-printed.
- *
- * @param prettyPrinting <code>true</code> if the output is pretty-printed
- */
- public void setPrettyPrinting(boolean prettyPrinting)
- {
- _prettyPrinting = prettyPrinting;
+ throw new DataWriterException(baseEx);
}
/**
@@ -167,83 +110,25 @@
}
/**
- * Prints a newline if we're pretty-printing.
+ * Writes the start of the XML document, including the start of the outermost
+ * XML element (<code>data</code>).
*/
- private void printlnIfPrettyPrinting() throws DataWriterException
+ public void writeDocumentStart() throws DdlUtilsXMLException
{
- if (_prettyPrinting)
- {
- try
- {
- _writer.writeCharacters("\n");
- }
- catch (XMLStreamException ex)
- {
- throw new DataWriterException(ex);
- }
- }
+ super.writeDocumentStart();
+ writeElementStart(null, "data");
+ printlnIfPrettyPrinting();
}
/**
- * Prints the indentation if we're pretty-printing.
- *
- * @param level The indentation level
+ * Writes the end of the XML document, including the end of the outermost
+ * XML element (<code>data</code>).
*/
- private void indentIfPrettyPrinting(int level) throws DataWriterException
+ public void writeDocumentEnd() throws DdlUtilsXMLException
{
- if (_prettyPrinting)
- {
- try
- {
- for (int idx = 0; idx < level; idx++)
- {
- _writer.writeCharacters(INDENT_STRING);
- }
- }
- catch (XMLStreamException ex)
- {
- throw new DataWriterException(ex);
- }
- }
- }
-
- /**
- * Writes the start of the XML document, i.e. the "<?xml?>" section and the start of the
- * root node.
- */
- public void writeDocumentStart() throws DataWriterException
- {
- try
- {
- _writer.writeStartDocument(_encoding, "1.0");
- printlnIfPrettyPrinting();
- _writer.writeStartElement("data");
- printlnIfPrettyPrinting();
- }
- catch (XMLStreamException ex)
- {
- throw new DataWriterException(ex);
- }
- }
-
- /**
- * Writes the end of the XML document, i.e. end of the root node.
- */
- public void writeDocumentEnd() throws DataWriterException
- {
- try
- {
- _writer.writeEndElement();
- printlnIfPrettyPrinting();
- _writer.writeEndDocument();
- _writer.flush();
- _writer.close();
- _output.close();
- }
- catch (XMLStreamException ex)
- {
- throw new DataWriterException(ex);
- }
+ writeElementEnd();
+ printlnIfPrettyPrinting();
+ super.writeDocumentEnd();
}
/**
@@ -260,7 +145,7 @@
try
{
indentIfPrettyPrinting(1);
- _writer.writeStartElement(table.getName());
+ writeElementStart(null, table.getName());
for (int idx = 0; idx < table.getColumnCount(); idx++)
{
Column column = table.getColumn(idx);
@@ -290,7 +175,7 @@
}
else
{
- _writer.writeAttribute(column.getName(), valueAsText);
+ writeAttribute(null, column.getName(), valueAsText);
}
}
}
@@ -305,7 +190,7 @@
printlnIfPrettyPrinting();
indentIfPrettyPrinting(2);
- _writer.writeStartElement(entry.getKey().toString());
+ writeElementStart(null, entry.getKey().toString());
// if the content contains special characters, we have to apply base64 encoding to it
// if the content is too short, then it has to contain special characters (otherwise
@@ -316,14 +201,14 @@
if (writeBase64Encoded)
{
- _writer.writeAttribute(DatabaseIO.BASE64_ATTR_NAME, "true");
- _writer.writeCData(new String(Base64.encodeBase64(content.getBytes())));
+ writeAttribute(null, DatabaseIO.BASE64_ATTR_NAME, "true");
+ writeCData(new String(Base64.encodeBase64(content.getBytes())));
}
else
{
if (cutPoints.isEmpty())
{
- _writer.writeCData(content);
+ writeCData(content);
}
else
{
@@ -333,28 +218,24 @@
{
int curPos = ((Integer)cutPointIt.next()).intValue();
- _writer.writeCData(content.substring(lastPos, curPos));
+ writeCData(content.substring(lastPos, curPos));
lastPos = curPos;
}
if (lastPos < content.length())
{
- _writer.writeCData(content.substring(lastPos));
+ writeCData(content.substring(lastPos));
}
}
}
- _writer.writeEndElement();
+ writeElementEnd();
}
printlnIfPrettyPrinting();
indentIfPrettyPrinting(1);
}
- _writer.writeEndElement();
+ writeElementEnd();
printlnIfPrettyPrinting();
}
- catch (XMLStreamException ex)
- {
- throw new DataWriterException(ex);
- }
catch (ConversionException ex)
{
throw new DataWriterException(ex);
diff --git a/src/java/org/apache/ddlutils/io/DataWriterException.java b/src/java/org/apache/ddlutils/io/DataWriterException.java
index 4294fa1..e29bff2 100644
--- a/src/java/org/apache/ddlutils/io/DataWriterException.java
+++ b/src/java/org/apache/ddlutils/io/DataWriterException.java
@@ -19,14 +19,13 @@
* under the License.
*/
-import org.apache.commons.lang.exception.NestableRuntimeException;
/**
* Exception generated by the {@link org.apache.ddlutils.io.DataWriter}.
*
* @version $Revision: 289996 $
*/
-public class DataWriterException extends NestableRuntimeException
+public class DataWriterException extends DdlUtilsXMLException
{
/** Unique id for serialization purposes. */
private static final long serialVersionUID = 6254759931565130848L;
diff --git a/src/java/org/apache/ddlutils/io/DatabaseIO.java b/src/java/org/apache/ddlutils/io/DatabaseIO.java
index d1557c6..5e296b9 100644
--- a/src/java/org/apache/ddlutils/io/DatabaseIO.java
+++ b/src/java/org/apache/ddlutils/io/DatabaseIO.java
@@ -19,9 +19,9 @@
* under the License.
*/
-import java.beans.IntrospectionException;
import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
@@ -29,13 +29,23 @@
import java.io.Reader;
import java.io.Writer;
-import org.apache.commons.betwixt.io.BeanReader;
-import org.apache.commons.betwixt.io.BeanWriter;
-import org.apache.commons.betwixt.strategy.HyphenatedNameMapper;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.commons.lang.StringUtils;
import org.apache.ddlutils.DdlUtilsException;
+import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
+import org.apache.ddlutils.model.ForeignKey;
+import org.apache.ddlutils.model.Index;
+import org.apache.ddlutils.model.IndexColumn;
+import org.apache.ddlutils.model.NonUniqueIndex;
+import org.apache.ddlutils.model.Reference;
+import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.model.UniqueIndex;
import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
/**
* This class provides functions to read and write database models from/to XML.
@@ -48,11 +58,62 @@
element uses Base64 encoding. */
public static final String BASE64_ATTR_NAME = "base64";
+ /** The namespace used by DdlUtils. */
+ public static final String DDLUTILS_NAMESPACE = "http://db.apache.org/torque/";
+
+ /** Qualified name of the column element. */
+ public static final QName QNAME_ELEMENT_COLUMN = new QName(DDLUTILS_NAMESPACE, "column");
+ /** Qualified name of the database element. */
+ public static final QName QNAME_ELEMENT_DATABASE = new QName(DDLUTILS_NAMESPACE, "database");
+ /** Qualified name of the foreign-key element. */
+ public static final QName QNAME_ELEMENT_FOREIGN_KEY = new QName(DDLUTILS_NAMESPACE, "foreign-key");
+ /** Qualified name of the index element. */
+ public static final QName QNAME_ELEMENT_INDEX = new QName(DDLUTILS_NAMESPACE, "index");
+ /** Qualified name of the index-column element. */
+ public static final QName QNAME_ELEMENT_INDEX_COLUMN = new QName(DDLUTILS_NAMESPACE, "index-column");
+ /** Qualified name of the reference element. */
+ public static final QName QNAME_ELEMENT_REFERENCE = new QName(DDLUTILS_NAMESPACE, "reference");
+ /** Qualified name of the table element. */
+ public static final QName QNAME_ELEMENT_TABLE = new QName(DDLUTILS_NAMESPACE, "table");
+ /** Qualified name of the unique element. */
+ public static final QName QNAME_ELEMENT_UNIQUE = new QName(DDLUTILS_NAMESPACE, "unique");
+ /** Qualified name of the unique-column element. */
+ public static final QName QNAME_ELEMENT_UNIQUE_COLUMN = new QName(DDLUTILS_NAMESPACE, "unique-column");
+
+ /** Qualified name of the autoIncrement attribute. */
+ public static final QName QNAME_ATTRIBUTE_AUTO_INCREMENT = new QName(DDLUTILS_NAMESPACE, "autoIncrement");
+ /** Qualified name of the default attribute. */
+ public static final QName QNAME_ATTRIBUTE_DEFAULT = new QName(DDLUTILS_NAMESPACE, "default");
+ /** Qualified name of the defaultIdMethod attribute. */
+ public static final QName QNAME_ATTRIBUTE_DEFAULT_ID_METHOD = new QName(DDLUTILS_NAMESPACE, "defaultIdMethod");
+ /** Qualified name of the description attribute. */
+ public static final QName QNAME_ATTRIBUTE_DESCRIPTION = new QName(DDLUTILS_NAMESPACE, "description");
+ /** Qualified name of the foreign attribute. */
+ public static final QName QNAME_ATTRIBUTE_FOREIGN = new QName(DDLUTILS_NAMESPACE, "foreign");
+ /** Qualified name of the foreignTable attribute. */
+ public static final QName QNAME_ATTRIBUTE_FOREIGN_TABLE = new QName(DDLUTILS_NAMESPACE, "foreignTable");
+ /** Qualified name of the javaName attribute. */
+ public static final QName QNAME_ATTRIBUTE_JAVA_NAME = new QName(DDLUTILS_NAMESPACE, "javaName");
+ /** Qualified name of the local attribute. */
+ public static final QName QNAME_ATTRIBUTE_LOCAL = new QName(DDLUTILS_NAMESPACE, "local");
+ /** Qualified name of the name attribute. */
+ public static final QName QNAME_ATTRIBUTE_NAME = new QName(DDLUTILS_NAMESPACE, "name");
+ /** Qualified name of the primaryKey attribute. */
+ public static final QName QNAME_ATTRIBUTE_PRIMARY_KEY = new QName(DDLUTILS_NAMESPACE, "primaryKey");
+ /** Qualified name of the required attribute. */
+ public static final QName QNAME_ATTRIBUTE_REQUIRED = new QName(DDLUTILS_NAMESPACE, "required");
+ /** Qualified name of the size attribute. */
+ public static final QName QNAME_ATTRIBUTE_SIZE = new QName(DDLUTILS_NAMESPACE, "size");
+ /** Qualified name of the type attribute. */
+ public static final QName QNAME_ATTRIBUTE_TYPE = new QName(DDLUTILS_NAMESPACE, "type");
+ /** Qualified name of the version attribute. */
+ public static final QName QNAME_ATTRIBUTE_VERSION = new QName(DDLUTILS_NAMESPACE, "version");
+
/** Whether to validate the XML. */
private boolean _validateXml = true;
/** Whether to use the internal dtd that comes with DdlUtils. */
private boolean _useInternalDtd = true;
-
+
/**
* Returns whether XML is validated upon reading it.
*
@@ -94,66 +155,6 @@
}
/**
- * Returns the commons-betwixt mapping file as an {@link org.xml.sax.InputSource} object.
- * Per default, this will be classpath resource under the path <code>/mapping.xml</code>.
- *
- * @return The input source for the mapping
- */
- protected InputSource getBetwixtMapping()
- {
- return new InputSource(getClass().getResourceAsStream("/mapping.xml"));
- }
-
- /**
- * Returns a new bean reader configured to read database models.
- *
- * @return The reader
- */
- protected BeanReader getReader() throws IntrospectionException, SAXException, IOException
- {
- BeanReader reader = new BeanReader();
-
- reader.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(true);
- reader.getXMLIntrospector().getConfiguration().setWrapCollectionsInElement(false);
- reader.getXMLIntrospector().getConfiguration().setElementNameMapper(new HyphenatedNameMapper());
- reader.setValidating(isValidateXml());
- if (isUseInternalDtd())
- {
- reader.setEntityResolver(new LocalEntityResolver());
- }
- reader.registerMultiMapping(getBetwixtMapping());
-
- return reader;
- }
-
- /**
- * Returns a new bean writer configured to writer database models.
- *
- * @param output The target output writer
- * @return The writer
- */
- protected BeanWriter getWriter(Writer output) throws DdlUtilsException
- {
- try
- {
- BeanWriter writer = new BeanWriter(output);
-
- writer.getXMLIntrospector().register(getBetwixtMapping());
- writer.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(true);
- writer.getXMLIntrospector().getConfiguration().setWrapCollectionsInElement(false);
- writer.getXMLIntrospector().getConfiguration().setElementNameMapper(new HyphenatedNameMapper());
- writer.getBindingConfiguration().setMapIDs(false);
- writer.enablePrettyPrint();
-
- return writer;
- }
- catch (Exception ex)
- {
- throw new DdlUtilsException(ex);
- }
- }
-
- /**
* Reads the database model contained in the specified file.
*
* @param filename The model file name
@@ -161,18 +162,14 @@
*/
public Database read(String filename) throws DdlUtilsException
{
- Database model = null;
-
try
{
- model = (Database)getReader().parse(filename);
+ return read(new FileReader(filename));
}
- catch (Exception ex)
+ catch (IOException ex)
{
throw new DdlUtilsException(ex);
}
- model.initialize();
- return model;
}
/**
@@ -183,18 +180,14 @@
*/
public Database read(File file) throws DdlUtilsException
{
- Database model = null;
-
try
{
- model = (Database)getReader().parse(file);
+ return read(new FileReader(file));
}
- catch (Exception ex)
+ catch (IOException ex)
{
throw new DdlUtilsException(ex);
}
- model.initialize();
- return model;
}
/**
@@ -205,18 +198,14 @@
*/
public Database read(Reader reader) throws DdlUtilsException
{
- Database model = null;
-
try
{
- model = (Database)getReader().parse(reader);
+ return read(getXMLInputFactory().createXMLStreamReader(reader));
}
- catch (Exception ex)
+ catch (XMLStreamException ex)
{
throw new DdlUtilsException(ex);
}
- model.initialize();
- return model;
}
/**
@@ -227,27 +216,563 @@
*/
public Database read(InputSource source) throws DdlUtilsException
{
+ try
+ {
+ return read(getXMLInputFactory().createXMLStreamReader(source.getCharacterStream()));
+ }
+ catch (XMLStreamException ex)
+ {
+ throw new DdlUtilsException(ex);
+ }
+ }
+
+ /**
+ * Creates a new, initialized XML input factory object.
+ *
+ * @return The factory object
+ */
+ private XMLInputFactory getXMLInputFactory()
+ {
+ XMLInputFactory factory = XMLInputFactory.newInstance();
+
+ factory.setProperty("javax.xml.stream.isCoalescing", Boolean.TRUE);
+ factory.setProperty("javax.xml.stream.isNamespaceAware", Boolean.TRUE);
+ return factory;
+ }
+
+ /**
+ * Reads the database model from the given XML stream reader.
+ *
+ * @param xmlReader The reader
+ * @return The database model
+ */
+ private Database read(XMLStreamReader xmlReader) throws DdlUtilsException
+ {
Database model = null;
try
{
- model = (Database)getReader().parse(source);
+ while (xmlReader.getEventType() != XMLStreamReader.START_ELEMENT)
+ {
+ if (xmlReader.next() == XMLStreamReader.END_DOCUMENT)
+ {
+ return null;
+ }
+ }
+ if (isSameAs(xmlReader.getName(), QNAME_ELEMENT_DATABASE))
+ {
+ model = readDatabaseElement(xmlReader);
+ }
}
- catch (Exception ex)
+ catch (IOException ex)
{
throw new DdlUtilsException(ex);
}
- model.initialize();
+ catch (XMLStreamException ex)
+ {
+ throw new DdlUtilsException(ex);
+ }
+ if (model != null)
+ {
+ model.initialize();
+ }
return model;
}
/**
+ * Reads a database element from the XML stream reader.
+ *
+ * @param xmlReader The reader
+ * @return The database object
+ */
+ private Database readDatabaseElement(XMLStreamReader xmlReader) throws XMLStreamException, IOException
+ {
+ Database model = new Database();
+
+ for (int idx = 0; idx < xmlReader.getAttributeCount(); idx++)
+ {
+ QName attrQName = xmlReader.getAttributeName(idx);
+
+ if (isSameAs(attrQName, QNAME_ATTRIBUTE_NAME))
+ {
+ model.setName(xmlReader.getAttributeValue(idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_DEFAULT_ID_METHOD))
+ {
+ model.setIdMethod(xmlReader.getAttributeValue(idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_VERSION))
+ {
+ model.setVersion(xmlReader.getAttributeValue(idx));
+ }
+ }
+ readTableElements(xmlReader, model);
+ consumeRestOfElement(xmlReader);
+ return model;
+ }
+
+ /**
+ * Reads table elements from the XML stream reader and adds them to the given
+ * database model.
+ *
+ * @param xmlReader The reader
+ * @param model The database model to add the table objects to
+ */
+ private void readTableElements(XMLStreamReader xmlReader, Database model) throws XMLStreamException, IOException
+ {
+ int eventType = XMLStreamReader.START_ELEMENT;
+
+ while (eventType != XMLStreamReader.END_ELEMENT)
+ {
+ eventType = xmlReader.nextTag();
+ if (eventType == XMLStreamReader.START_ELEMENT)
+ {
+ if (isSameAs(xmlReader.getName(), QNAME_ELEMENT_TABLE)) {
+ model.addTable(readTableElement(xmlReader));
+ }
+ else {
+ readOverElement(xmlReader);
+ }
+ }
+ }
+ }
+
+ /**
+ * Reads a table element from the XML stream reader.
+ *
+ * @param xmlReader The reader
+ * @return The table object
+ */
+ private Table readTableElement(XMLStreamReader xmlReader) throws XMLStreamException, IOException
+ {
+ Table table = new Table();
+
+ for (int idx = 0; idx < xmlReader.getAttributeCount(); idx++)
+ {
+ QName attrQName = xmlReader.getAttributeName(idx);
+
+ if (isSameAs(attrQName, QNAME_ATTRIBUTE_NAME))
+ {
+ table.setName(xmlReader.getAttributeValue(idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_DESCRIPTION))
+ {
+ table.setDescription(xmlReader.getAttributeValue(idx));
+ }
+ }
+ readTableSubElements(xmlReader, table);
+ consumeRestOfElement(xmlReader);
+ return table;
+ }
+
+ /**
+ * Reads table sub elements (column, foreign key, index) from the XML stream reader and adds
+ * them to the given table.
+ *
+ * @param xmlReader The reader
+ * @param table The table
+ */
+ private void readTableSubElements(XMLStreamReader xmlReader, Table table) throws XMLStreamException, IOException
+ {
+ int eventType = XMLStreamReader.START_ELEMENT;
+
+ while (eventType != XMLStreamReader.END_ELEMENT)
+ {
+ eventType = xmlReader.nextTag();
+ if (eventType == XMLStreamReader.START_ELEMENT)
+ {
+ QName elemQName = xmlReader.getName();
+
+ if (isSameAs(elemQName, QNAME_ELEMENT_COLUMN))
+ {
+ table.addColumn(readColumnElement(xmlReader));
+ }
+ else if (isSameAs(elemQName, QNAME_ELEMENT_FOREIGN_KEY))
+ {
+ table.addForeignKey(readForeignKeyElement(xmlReader));
+ }
+ else if (isSameAs(elemQName, QNAME_ELEMENT_INDEX))
+ {
+ table.addIndex(readIndexElement(xmlReader));
+ }
+ else if (isSameAs(elemQName, QNAME_ELEMENT_UNIQUE))
+ {
+ table.addIndex(readUniqueElement(xmlReader));
+ }
+ else {
+ readOverElement(xmlReader);
+ }
+ }
+ }
+ }
+
+ /**
+ * Reads a column element from the XML stream reader.
+ *
+ * @param xmlReader The reader
+ * @return The column object
+ */
+ private Column readColumnElement(XMLStreamReader xmlReader) throws XMLStreamException, IOException
+ {
+ Column column = new Column();
+
+ for (int idx = 0; idx < xmlReader.getAttributeCount(); idx++)
+ {
+ QName attrQName = xmlReader.getAttributeName(idx);
+
+ if (isSameAs(attrQName, QNAME_ATTRIBUTE_NAME))
+ {
+ column.setName(xmlReader.getAttributeValue(idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_PRIMARY_KEY))
+ {
+ column.setPrimaryKey(getAttributeValueAsBoolean(xmlReader, idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_REQUIRED))
+ {
+ column.setRequired(getAttributeValueAsBoolean(xmlReader, idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_TYPE))
+ {
+ column.setType(xmlReader.getAttributeValue(idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_SIZE))
+ {
+ column.setSize(xmlReader.getAttributeValue(idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_DEFAULT))
+ {
+ column.setDefaultValue(xmlReader.getAttributeValue(idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_AUTO_INCREMENT))
+ {
+ column.setAutoIncrement(getAttributeValueAsBoolean(xmlReader, idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_DESCRIPTION))
+ {
+ column.setDescription(xmlReader.getAttributeValue(idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_JAVA_NAME))
+ {
+ column.setJavaName(xmlReader.getAttributeValue(idx));
+ }
+ }
+ consumeRestOfElement(xmlReader);
+ return column;
+ }
+
+ /**
+ * Reads a foreign key element from the XML stream reader.
+ *
+ * @param xmlReader The reader
+ * @return The foreign key object
+ */
+ private ForeignKey readForeignKeyElement(XMLStreamReader xmlReader) throws XMLStreamException, IOException
+ {
+ ForeignKey foreignKey = new ForeignKey();
+
+ for (int idx = 0; idx < xmlReader.getAttributeCount(); idx++)
+ {
+ QName attrQName = xmlReader.getAttributeName(idx);
+
+ if (isSameAs(attrQName, QNAME_ATTRIBUTE_FOREIGN_TABLE))
+ {
+ foreignKey.setForeignTableName(xmlReader.getAttributeValue(idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_NAME))
+ {
+ foreignKey.setName(xmlReader.getAttributeValue(idx));
+ }
+ }
+ readReferenceElements(xmlReader, foreignKey);
+ consumeRestOfElement(xmlReader);
+ return foreignKey;
+ }
+
+ /**
+ * Reads reference elements from the XML stream reader and adds them to the given
+ * foreign key.
+ *
+ * @param xmlReader The reader
+ * @param foreignKey The foreign key
+ */
+ private void readReferenceElements(XMLStreamReader xmlReader, ForeignKey foreignKey) throws XMLStreamException, IOException
+ {
+ int eventType = XMLStreamReader.START_ELEMENT;
+
+ while (eventType != XMLStreamReader.END_ELEMENT)
+ {
+ eventType = xmlReader.nextTag();
+ if (eventType == XMLStreamReader.START_ELEMENT)
+ {
+ QName elemQName = xmlReader.getName();
+
+ if (isSameAs(elemQName, QNAME_ELEMENT_REFERENCE))
+ {
+ foreignKey.addReference(readReferenceElement(xmlReader));
+ }
+ else {
+ readOverElement(xmlReader);
+ }
+ }
+ }
+ }
+
+ /**
+ * Reads a reference element from the XML stream reader.
+ *
+ * @param xmlReader The reader
+ * @return The reference object
+ */
+ private Reference readReferenceElement(XMLStreamReader xmlReader) throws XMLStreamException, IOException
+ {
+ Reference reference = new Reference();
+
+ for (int idx = 0; idx < xmlReader.getAttributeCount(); idx++)
+ {
+ QName attrQName = xmlReader.getAttributeName(idx);
+
+ if (isSameAs(attrQName, QNAME_ATTRIBUTE_LOCAL))
+ {
+ reference.setLocalColumnName(xmlReader.getAttributeValue(idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_FOREIGN))
+ {
+ reference.setForeignColumnName(xmlReader.getAttributeValue(idx));
+ }
+ }
+ consumeRestOfElement(xmlReader);
+ return reference;
+ }
+
+ /**
+ * Reads an index element from the XML stream reader.
+ *
+ * @param xmlReader The reader
+ * @return The index object
+ */
+ private Index readIndexElement(XMLStreamReader xmlReader) throws XMLStreamException, IOException
+ {
+ Index index = new NonUniqueIndex();
+
+ for (int idx = 0; idx < xmlReader.getAttributeCount(); idx++)
+ {
+ QName attrQName = xmlReader.getAttributeName(idx);
+
+ if (isSameAs(attrQName, QNAME_ATTRIBUTE_NAME))
+ {
+ index.setName(xmlReader.getAttributeValue(idx));
+ }
+ }
+ readIndexColumnElements(xmlReader, index);
+ consumeRestOfElement(xmlReader);
+ return index;
+ }
+
+ /**
+ * Reads an unique index element from the XML stream reader.
+ *
+ * @param xmlReader The reader
+ * @return The unique index object
+ */
+ private Index readUniqueElement(XMLStreamReader xmlReader) throws XMLStreamException, IOException
+ {
+ Index index = new UniqueIndex();
+
+ for (int idx = 0; idx < xmlReader.getAttributeCount(); idx++)
+ {
+ QName attrQName = xmlReader.getAttributeName(idx);
+
+ if (isSameAs(attrQName, QNAME_ATTRIBUTE_NAME))
+ {
+ index.setName(xmlReader.getAttributeValue(idx));
+ }
+ }
+ readUniqueColumnElements(xmlReader, index);
+ consumeRestOfElement(xmlReader);
+ return index;
+ }
+
+ /**
+ * Reads index column elements from the XML stream reader and adds them to the given
+ * index object.
+ *
+ * @param xmlReader The reader
+ * @param index The index object
+ */
+ private void readIndexColumnElements(XMLStreamReader xmlReader, Index index) throws XMLStreamException, IOException
+ {
+ int eventType = XMLStreamReader.START_ELEMENT;
+
+ while (eventType != XMLStreamReader.END_ELEMENT)
+ {
+ eventType = xmlReader.nextTag();
+ if (eventType == XMLStreamReader.START_ELEMENT)
+ {
+ QName elemQName = xmlReader.getName();
+
+ if (isSameAs(elemQName, QNAME_ELEMENT_INDEX_COLUMN))
+ {
+ index.addColumn(readIndexColumnElement(xmlReader));
+ }
+ else {
+ readOverElement(xmlReader);
+ }
+ }
+ }
+ }
+
+ /**
+ * Reads unique index column elements from the XML stream reader and adds them to the given
+ * index object.
+ *
+ * @param xmlReader The reader
+ * @param index The index object
+ */
+ private void readUniqueColumnElements(XMLStreamReader xmlReader, Index index) throws XMLStreamException, IOException
+ {
+ int eventType = XMLStreamReader.START_ELEMENT;
+
+ while (eventType != XMLStreamReader.END_ELEMENT)
+ {
+ eventType = xmlReader.nextTag();
+ if (eventType == XMLStreamReader.START_ELEMENT)
+ {
+ QName elemQName = xmlReader.getName();
+
+ if (isSameAs(elemQName, QNAME_ELEMENT_UNIQUE_COLUMN))
+ {
+ index.addColumn(readIndexColumnElement(xmlReader));
+ }
+ else {
+ readOverElement(xmlReader);
+ }
+ }
+ }
+ }
+
+ /**
+ * Reads an index column element from the XML stream reader.
+ *
+ * @param xmlReader The reader
+ * @return The index column object
+ */
+ private IndexColumn readIndexColumnElement(XMLStreamReader xmlReader) throws XMLStreamException, IOException
+ {
+ IndexColumn indexColumn = new IndexColumn();
+
+ for (int idx = 0; idx < xmlReader.getAttributeCount(); idx++)
+ {
+ QName attrQName = xmlReader.getAttributeName(idx);
+
+ if (isSameAs(attrQName, QNAME_ATTRIBUTE_NAME))
+ {
+ indexColumn.setName(xmlReader.getAttributeValue(idx));
+ }
+ else if (isSameAs(attrQName, QNAME_ATTRIBUTE_SIZE))
+ {
+ indexColumn.setSize(xmlReader.getAttributeValue(idx));
+ }
+ }
+ consumeRestOfElement(xmlReader);
+ return indexColumn;
+ }
+
+ /**
+ * Compares the given qnames. This specifically ignores the namespace
+ * uri of the other qname if the namespace of the current element is
+ * empty.
+ *
+ * @param curElemQName The qname of the current element
+ * @param qName The qname to compare to
+ * @return <code>true</code> if they are the same
+ */
+ private boolean isSameAs(QName curElemQName, QName qName)
+ {
+ if (StringUtils.isEmpty(curElemQName.getNamespaceURI()))
+ {
+ return qName.getLocalPart().equals(curElemQName.getLocalPart());
+ }
+ else
+ {
+ return qName.equals(curElemQName);
+ }
+ }
+
+ /**
+ * Returns the value of the indicated attribute of the current element as a boolean.
+ * If the value is not a valid boolean, then an exception is thrown.
+ *
+ * @param xmlReader The xml reader
+ * @param attributeIdx The index of the attribute
+ * @return The attribute's value as a boolean
+ */
+ private boolean getAttributeValueAsBoolean(XMLStreamReader xmlReader, int attributeIdx) throws DdlUtilsException
+ {
+ String value = xmlReader.getAttributeValue(attributeIdx);
+
+ if ("true".equalsIgnoreCase(value))
+ {
+ return true;
+ }
+ else if ("false".equalsIgnoreCase(value))
+ {
+ return false;
+ }
+ else
+ {
+ throw new DdlUtilsException("Illegal boolean value '" + value +"' for attribute " + xmlReader.getAttributeLocalName(attributeIdx));
+ }
+ }
+
+ /**
+ * Consumes the rest of the current element. This assumes that the current XML stream
+ * event type is not START_ELEMENT.
+ *
+ * @param reader The xml reader
+ */
+ private void consumeRestOfElement(XMLStreamReader reader) throws XMLStreamException
+ {
+ int eventType = reader.getEventType();
+
+ while ((eventType != XMLStreamReader.END_ELEMENT) && (eventType != XMLStreamReader.END_DOCUMENT))
+ {
+ eventType = reader.nextTag();
+ }
+ }
+
+ /**
+ * Reads over the current element. This assumes that the current XML stream event type is
+ * START_ELEMENT.
+ *
+ * @param reader The xml reader
+ */
+ private void readOverElement(XMLStreamReader reader) throws XMLStreamException
+ {
+ int depth = 1;
+
+ while (depth > 0)
+ {
+ int eventType = reader.nextTag();
+
+ if (eventType == XMLStreamReader.START_ELEMENT)
+ {
+ depth++;
+ }
+ else if (eventType == XMLStreamReader.END_ELEMENT)
+ {
+ depth--;
+ }
+ }
+ }
+
+ /**
* Writes the database model to the specified file.
*
* @param model The database model
* @param filename The model file name
*/
- public void write(Database model, String filename) throws DdlUtilsException
+ public void write(Database model, String filename) throws DdlUtilsXMLException
{
try
{
@@ -276,44 +801,222 @@
/**
* Writes the database model to the given output stream. Note that this method
- * does not flush the stream.
+ * does not flush or close the stream.
*
* @param model The database model
* @param output The output stream
*/
- public void write(Database model, OutputStream output) throws DdlUtilsException
+ public void write(Database model, OutputStream output) throws DdlUtilsXMLException
{
- write(model, getWriter(new OutputStreamWriter(output)));
+ write(model, new OutputStreamWriter(output));
}
/**
* Writes the database model to the given output writer. Note that this method
- * does not flush the writer.
+ * does not flush or close the writer.
*
* @param model The database model
* @param output The output writer
*/
- public void write(Database model, Writer output) throws DdlUtilsException
+ public void write(Database model, Writer output) throws DdlUtilsXMLException
{
- write(model, getWriter(output));
+ PrettyPrintingXmlWriter xmlWriter = new PrettyPrintingXmlWriter(output, "UTF-8");
+
+ xmlWriter.setDefaultNamespace(DDLUTILS_NAMESPACE);
+ xmlWriter.writeDocumentStart();
+ writeDatabaseElement(model, xmlWriter);
+ xmlWriter.writeDocumentEnd();
}
/**
- * Internal method that writes the database model using the given bean writer.
+ * Writes the database model to the given XML writer.
*
- * @param model The database model
- * @param writer The bean writer
+ * @param model The database model
+ * @param xmlWriter The XML writer
*/
- private void write(Database model, BeanWriter writer) throws DdlUtilsException
+ private void writeDatabaseElement(Database model, PrettyPrintingXmlWriter xmlWriter) throws DdlUtilsXMLException
{
- try
+ writeElementStart(xmlWriter, QNAME_ELEMENT_DATABASE);
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_NAME, model.getName());
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_DEFAULT_ID_METHOD, model.getIdMethod());
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_VERSION, model.getVersion());
+ if (model.getTableCount() > 0)
{
- writer.writeXmlDeclaration("<?xml version=\"1.0\"?>\n<!DOCTYPE database SYSTEM \"" + LocalEntityResolver.DTD_PREFIX + "\">");
- writer.write(model);
+ xmlWriter.printlnIfPrettyPrinting();
+ for (int idx = 0; idx < model.getTableCount(); idx++)
+ {
+ writeTableElement(model.getTable(idx), xmlWriter);
+ }
}
- catch (Exception ex)
+ writeElementEnd(xmlWriter);
+ }
+
+ /**
+ * Writes the table object to the given XML writer.
+ *
+ * @param table The table object
+ * @param xmlWriter The XML writer
+ */
+ private void writeTableElement(Table table, PrettyPrintingXmlWriter xmlWriter) throws DdlUtilsXMLException
+ {
+ xmlWriter.indentIfPrettyPrinting(1);
+ writeElementStart(xmlWriter, QNAME_ELEMENT_TABLE);
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_NAME, table.getName());
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_DESCRIPTION, table.getDescription());
+ if ((table.getColumnCount() > 0) || (table.getForeignKeyCount() > 0) || (table.getIndexCount() > 0))
{
- throw new DdlUtilsException(ex);
+ xmlWriter.printlnIfPrettyPrinting();
+ for (int idx = 0; idx < table.getColumnCount(); idx++)
+ {
+ writeColumnElement(table.getColumn(idx), xmlWriter);
+ }
+ for (int idx = 0; idx < table.getForeignKeyCount(); idx++)
+ {
+ writeForeignKeyElement(table.getForeignKey(idx), xmlWriter);
+ }
+ for (int idx = 0; idx < table.getIndexCount(); idx++)
+ {
+ writeIndexElement(table.getIndex(idx), xmlWriter);
+ }
+ xmlWriter.indentIfPrettyPrinting(1);
}
+ writeElementEnd(xmlWriter);
+ }
+
+ /**
+ * Writes the column object to the given XML writer.
+ *
+ * @param column The column object
+ * @param xmlWriter The XML writer
+ */
+ private void writeColumnElement(Column column, PrettyPrintingXmlWriter xmlWriter) throws DdlUtilsXMLException
+ {
+ xmlWriter.indentIfPrettyPrinting(2);
+ writeElementStart(xmlWriter, QNAME_ELEMENT_COLUMN);
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_NAME, column.getName());
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_PRIMARY_KEY, String.valueOf(column.isPrimaryKey()));
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_REQUIRED, String.valueOf(column.isRequired()));
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_TYPE, column.getType());
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_SIZE, column.getSize());
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_DEFAULT, column.getDefaultValue());
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_AUTO_INCREMENT, String.valueOf(column.isAutoIncrement()));
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_DESCRIPTION, column.getDescription());
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_JAVA_NAME, column.getJavaName());
+ writeElementEnd(xmlWriter);
+ }
+
+ /**
+ * Writes the foreign key object to the given XML writer.
+ *
+ * @param foreignKey The foreign key object
+ * @param xmlWriter The XML writer
+ */
+ private void writeForeignKeyElement(ForeignKey foreignKey, PrettyPrintingXmlWriter xmlWriter) throws DdlUtilsXMLException
+ {
+ xmlWriter.indentIfPrettyPrinting(2);
+ writeElementStart(xmlWriter, QNAME_ELEMENT_FOREIGN_KEY);
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_FOREIGN_TABLE, foreignKey.getForeignTableName());
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_NAME, foreignKey.getName());
+ if (foreignKey.getReferenceCount() > 0)
+ {
+ xmlWriter.printlnIfPrettyPrinting();
+ for (int idx = 0; idx < foreignKey.getReferenceCount(); idx++)
+ {
+ writeReferenceElement(foreignKey.getReference(idx), xmlWriter);
+ }
+ xmlWriter.indentIfPrettyPrinting(2);
+ }
+ writeElementEnd(xmlWriter);
+ }
+
+ /**
+ * Writes the reference object to the given XML writer.
+ *
+ * @param reference The reference object
+ * @param xmlWriter The XML writer
+ */
+ private void writeReferenceElement(Reference reference, PrettyPrintingXmlWriter xmlWriter) throws DdlUtilsXMLException
+ {
+ xmlWriter.indentIfPrettyPrinting(3);
+ writeElementStart(xmlWriter, QNAME_ELEMENT_REFERENCE);
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_LOCAL, reference.getLocalColumnName());
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_FOREIGN, reference.getForeignColumnName());
+ writeElementEnd(xmlWriter);
+ }
+
+ /**
+ * Writes the index object to the given XML writer.
+ *
+ * @param index The index object
+ * @param xmlWriter The XML writer
+ */
+ private void writeIndexElement(Index index, PrettyPrintingXmlWriter xmlWriter) throws DdlUtilsXMLException
+ {
+ xmlWriter.indentIfPrettyPrinting(2);
+ writeElementStart(xmlWriter, index.isUnique() ? QNAME_ELEMENT_UNIQUE : QNAME_ELEMENT_INDEX);
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_NAME, index.getName());
+ if (index.getColumnCount() > 0)
+ {
+ xmlWriter.printlnIfPrettyPrinting();
+ for (int idx = 0; idx < index.getColumnCount(); idx++)
+ {
+ writeIndexColumnElement(index.getColumn(idx), index.isUnique(), xmlWriter);
+ }
+ xmlWriter.indentIfPrettyPrinting(2);
+ }
+ writeElementEnd(xmlWriter);
+ }
+
+ /**
+ * Writes the index column object to the given XML writer.
+ *
+ * @param indexColumn The index column object
+ * @param isUnique Whether the index that the index column belongs to, is unique
+ * @param xmlWriter The XML writer
+ */
+ private void writeIndexColumnElement(IndexColumn indexColumn, boolean isUnique, PrettyPrintingXmlWriter xmlWriter) throws DdlUtilsXMLException
+ {
+ xmlWriter.indentIfPrettyPrinting(3);
+ writeElementStart(xmlWriter, isUnique ? QNAME_ELEMENT_UNIQUE_COLUMN : QNAME_ELEMENT_INDEX_COLUMN);
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_NAME, indexColumn.getName());
+ writeAttribute(xmlWriter, QNAME_ATTRIBUTE_SIZE, indexColumn.getSize());
+ writeElementEnd(xmlWriter);
+ }
+
+ /**
+ * Writes the start of the specified XML element to the given XML writer.
+ *
+ * @param xmlWriter The xml writer
+ * @param qName The qname of the XML element
+ */
+ private void writeElementStart(PrettyPrintingXmlWriter xmlWriter, QName qName) throws DdlUtilsXMLException
+ {
+ xmlWriter.writeElementStart(null, qName.getLocalPart());
+ }
+
+ /**
+ * Writes an attribute to the given XML writer.
+ *
+ * @param xmlWriter The xml writer
+ * @param qName The qname of the attribute
+ * @param value The value; if empty, then nothing is written
+ */
+ private void writeAttribute(PrettyPrintingXmlWriter xmlWriter, QName qName, String value) throws DdlUtilsXMLException
+ {
+ if (!StringUtils.isEmpty(value))
+ {
+ xmlWriter.writeAttribute(null, qName.getLocalPart(), value);
+ }
+ }
+
+ /**
+ * Writes the end of the current XML element to the given XML writer.
+ *
+ * @param xmlWriter The xml writer
+ */
+ private void writeElementEnd(PrettyPrintingXmlWriter xmlWriter) throws DdlUtilsXMLException
+ {
+ xmlWriter.writeElementEnd();
+ xmlWriter.printlnIfPrettyPrinting();
}
}
diff --git a/src/java/org/apache/ddlutils/io/DdlUtilsXMLException.java b/src/java/org/apache/ddlutils/io/DdlUtilsXMLException.java
new file mode 100644
index 0000000..7dba914
--- /dev/null
+++ b/src/java/org/apache/ddlutils/io/DdlUtilsXMLException.java
@@ -0,0 +1,72 @@
+package org.apache.ddlutils.io;
+
+/*
+ * 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 org.apache.ddlutils.DdlUtilsException;
+
+/**
+ * Base class for exceptions generated by DdlUtils when handling XML.
+ *
+ * @version $Revision: $
+ */
+public class DdlUtilsXMLException extends DdlUtilsException
+{
+ /** Unique id for serialization purposes. */
+ private static final long serialVersionUID = 3464139163788952051L;
+
+ /**
+ * Creates a new exception object.
+ */
+ public DdlUtilsXMLException()
+ {
+ super();
+ }
+
+ /**
+ * Creates a new exception object.
+ *
+ * @param message The exception message
+ */
+ public DdlUtilsXMLException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Creates a new exception object.
+ *
+ * @param baseEx The base exception
+ */
+ public DdlUtilsXMLException(Throwable baseEx)
+ {
+ super(baseEx);
+ }
+
+ /**
+ * Creates a new exception object.
+ *
+ * @param message The exception message
+ * @param baseEx The base exception
+ */
+ public DdlUtilsXMLException(String message, Throwable baseEx)
+ {
+ super(message, baseEx);
+ }
+}
diff --git a/src/java/org/apache/ddlutils/io/PrettyPrintingXmlWriter.java b/src/java/org/apache/ddlutils/io/PrettyPrintingXmlWriter.java
new file mode 100644
index 0000000..145ba9e
--- /dev/null
+++ b/src/java/org/apache/ddlutils/io/PrettyPrintingXmlWriter.java
@@ -0,0 +1,318 @@
+package org.apache.ddlutils.io;
+
+/*
+ * 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.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+/**
+ * Helper class that writes XML data with or without pretty printing.
+ *
+ * @version $Revision: $
+ */
+public class PrettyPrintingXmlWriter
+{
+ /** The indentation string. */
+ private static final String INDENT_STRING = " ";
+
+ /** The output stream. */
+ private PrintWriter _output;
+ /** The xml writer. */
+ private XMLStreamWriter _writer;
+ /** The output encoding. */
+ private String _encoding;
+ /** Whether we're pretty-printing. */
+ private boolean _prettyPrinting = true;
+
+ /**
+ * Creates a xml writer instance using UTF-8 encoding.
+ *
+ * @param output The target to write the data XML to
+ */
+ public PrettyPrintingXmlWriter(OutputStream output) throws DdlUtilsXMLException
+ {
+ this(output, null);
+ }
+
+ /**
+ * Creates a xml writer instance.
+ *
+ * @param output The target to write the data XML to
+ * @param encoding The encoding of the XML file
+ */
+ public PrettyPrintingXmlWriter(OutputStream output, String encoding) throws DdlUtilsXMLException
+ {
+ _output = new PrintWriter(output);
+ if ((encoding == null) || (encoding.length() == 0))
+ {
+ _encoding = "UTF-8";
+ }
+ else
+ {
+ _encoding = encoding;
+ }
+
+ try
+ {
+ XMLOutputFactory factory = XMLOutputFactory.newInstance();
+
+ _writer = factory.createXMLStreamWriter(output, _encoding);
+ }
+ catch (XMLStreamException ex)
+ {
+ throwException(ex);
+ }
+ }
+
+ /**
+ * Creates a xml writer instance using the specified writer. Note that the writer
+ * needs to be configured using the specified encoding.
+ *
+ * @param output The target to write the data XML to
+ * @param encoding The encoding of the writer
+ */
+ public PrettyPrintingXmlWriter(Writer output, String encoding) throws DdlUtilsXMLException
+ {
+ _output = new PrintWriter(output);
+ _encoding = encoding;
+ try
+ {
+ XMLOutputFactory factory = XMLOutputFactory.newInstance();
+
+ _writer = factory.createXMLStreamWriter(_output);
+ }
+ catch (XMLStreamException ex)
+ {
+ throwException(ex);
+ }
+ }
+
+ /**
+ * Rethrows the given exception, wrapped in a {@link DdlUtilsXMLException}. This
+ * method allows subclasses to throw their own subclasses of this exception.
+ *
+ * @param baseEx The original exception
+ * @throws DdlUtilsXMLException The wrapped exception
+ */
+ protected void throwException(Exception baseEx) throws DdlUtilsXMLException
+ {
+ throw new DdlUtilsXMLException(baseEx);
+ }
+
+ /**
+ * Determines whether the output shall be pretty-printed.
+ *
+ * @return <code>true</code> if the output is pretty-printed
+ */
+ public boolean isPrettyPrinting()
+ {
+ return _prettyPrinting;
+ }
+
+ /**
+ * Specifies whether the output shall be pretty-printed.
+ *
+ * @param prettyPrinting <code>true</code> if the output is pretty-printed
+ */
+ public void setPrettyPrinting(boolean prettyPrinting)
+ {
+ _prettyPrinting = prettyPrinting;
+ }
+
+ /**
+ * Sets the default namespace.
+ *
+ * @param uri The namespace uri
+ */
+ public void setDefaultNamespace(String uri) throws DdlUtilsXMLException
+ {
+ try
+ {
+ _writer.setDefaultNamespace(uri);
+ }
+ catch (XMLStreamException ex)
+ {
+ throwException(ex);
+ }
+ }
+
+ /**
+ * Prints a newline if we're pretty-printing.
+ */
+ public void printlnIfPrettyPrinting() throws DdlUtilsXMLException
+ {
+ if (_prettyPrinting)
+ {
+ try
+ {
+ _writer.writeCharacters("\n");
+ }
+ catch (XMLStreamException ex)
+ {
+ throwException(ex);
+ }
+ }
+ }
+
+ /**
+ * Prints the indentation if we're pretty-printing.
+ *
+ * @param level The indentation level
+ */
+ public void indentIfPrettyPrinting(int level) throws DdlUtilsXMLException
+ {
+ if (_prettyPrinting)
+ {
+ try
+ {
+ for (int idx = 0; idx < level; idx++)
+ {
+ _writer.writeCharacters(INDENT_STRING);
+ }
+ }
+ catch (XMLStreamException ex)
+ {
+ throwException(ex);
+ }
+ }
+ }
+
+ /**
+ * Writes the start of the XML document, i.e. the "<?xml?>" section and the start of the
+ * root node.
+ */
+ public void writeDocumentStart() throws DdlUtilsXMLException
+ {
+ try
+ {
+ _writer.writeStartDocument(_encoding, "1.0");
+ printlnIfPrettyPrinting();
+ }
+ catch (XMLStreamException ex)
+ {
+ throwException(ex);
+ }
+ }
+
+ /**
+ * Writes the end of the XML document, i.e. end of the root node.
+ */
+ public void writeDocumentEnd() throws DdlUtilsXMLException
+ {
+ try
+ {
+ _writer.writeEndDocument();
+ _writer.flush();
+ _writer.close();
+ }
+ catch (XMLStreamException ex)
+ {
+ throwException(ex);
+ }
+ }
+
+ /**
+ * Writes the start of the indicated XML element.
+ *
+ * @param namespaceUri The namespace uri, can be <code>null</code>
+ * @param localPart The local part of the element's qname
+ */
+ public void writeElementStart(String namespaceUri, String localPart) throws DdlUtilsXMLException
+ {
+ try
+ {
+ if (namespaceUri == null)
+ {
+ _writer.writeStartElement(localPart);
+ }
+ else
+ {
+ _writer.writeStartElement(namespaceUri, localPart);
+ }
+ }
+ catch (XMLStreamException ex)
+ {
+ throwException(ex);
+ }
+ }
+
+ /**
+ * Writes the end of the current XML element.
+ */
+ public void writeElementEnd() throws DdlUtilsXMLException
+ {
+ try
+ {
+ _writer.writeEndElement();
+ }
+ catch (XMLStreamException ex)
+ {
+ throwException(ex);
+ }
+ }
+
+ /**
+ * Writes an XML attribute.
+ *
+ * @param namespaceUri The namespace uri, can be <code>null</code>
+ * @param localPart The local part of the attribute's qname
+ * @param value The value; if <code>null</code> then no attribute is written
+ */
+ public void writeAttribute(String namespaceUri, String localPart, String value) throws DdlUtilsXMLException
+ {
+ try
+ {
+ if (namespaceUri == null)
+ {
+ _writer.writeAttribute(localPart, value);
+ }
+ else
+ {
+ _writer.writeAttribute(namespaceUri, localPart, value);
+ }
+ }
+ catch (XMLStreamException ex)
+ {
+ throwException(ex);
+ }
+ }
+
+ /**
+ * Writes a CDATA segment.
+ *
+ * @param data The data to write
+ */
+ public void writeCData(String data) throws DdlUtilsXMLException
+ {
+ try
+ {
+ _writer.writeCData(data);
+ }
+ catch (XMLStreamException ex)
+ {
+ throwException(ex);
+ }
+ }
+}
diff --git a/src/java/org/apache/ddlutils/model/CascadeActionEnum.java b/src/java/org/apache/ddlutils/model/CascadeActionEnum.java
new file mode 100644
index 0000000..22ed94b
--- /dev/null
+++ b/src/java/org/apache/ddlutils/model/CascadeActionEnum.java
@@ -0,0 +1,125 @@
+package org.apache.ddlutils.model;
+
+/*
+ * 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.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.enums.ValuedEnum;
+
+/**
+ * Represents the different cascade actions for {@link ForeignKey#onDelete} and
+ * {@link ForeignKey#onUdate}.
+ *
+ * @version $Revision: $
+ */
+public class CascadeActionEnum extends ValuedEnum
+{
+ /** The integer value for the enum value for a cascading change. */
+ public static final int VALUE_CASCADE = 1;
+ /** The integer value for the enum value for a set-null change. */
+ public static final int VALUE_SETNULL = 2;
+ /** The integer value for the enum value for a restrict change. */
+ public static final int VALUE_RESTRICT = 3;
+ /** The integer value for the enum value for no-change. */
+ public static final int VALUE_NONE = 4;
+
+ /** The enum value for a cascade action which directs the database to change the value
+ of local column to the new value of the referenced column when it changes. */
+ public static final CascadeActionEnum CASCADE = new CascadeActionEnum("cascade", VALUE_CASCADE);
+ /** The enum value for a cascade action which directs the database to set the local
+ column to null when the referenced column changes. */
+ public static final CascadeActionEnum SETNULL = new CascadeActionEnum("setnull", VALUE_SETNULL);
+ /** The enum value for a cascade action which directs the database to restrict the change
+ changes to the referenced column. The interpretation of this is database-dependent. */
+ public static final CascadeActionEnum RESTRICT = new CascadeActionEnum("restrict", VALUE_RESTRICT);
+ /** The enum value for a cascade action which directs the database to take do nothing
+ to the local column when the value of the referenced column changes. */
+ public static final CascadeActionEnum NONE = new CascadeActionEnum("none", VALUE_NONE);
+
+ /** Version id for this class as relevant for serialization. */
+ private static final long serialVersionUID = -6378050861446415790L;
+
+ /**
+ * Creates a new enum object.
+ *
+ * @param defaultTextRep The textual representation
+ * @param value The corresponding integer value
+ */
+ private CascadeActionEnum(String defaultTextRep, int value)
+ {
+ super(defaultTextRep, value);
+ }
+
+ /**
+ * Returns the enum value that corresponds to the given textual
+ * representation.
+ *
+ * @param defaultTextRep The textual representation
+ * @return The enum value
+ */
+ public static CascadeActionEnum getEnum(String defaultTextRep)
+ {
+ return (CascadeActionEnum)getEnum(CascadeActionEnum.class, defaultTextRep);
+ }
+
+ /**
+ * Returns the enum value that corresponds to the given integer
+ * representation.
+ *
+ * @param intValue The integer value
+ * @return The enum value
+ */
+ public static CascadeActionEnum getEnum(int intValue)
+ {
+ return (CascadeActionEnum)getEnum(CascadeActionEnum.class, intValue);
+ }
+
+ /**
+ * Returns the map of enum values.
+ *
+ * @return The map of enum values
+ */
+ public static Map getEnumMap()
+ {
+ return getEnumMap(CascadeActionEnum.class);
+ }
+
+ /**
+ * Returns a list of all enum values.
+ *
+ * @return The list of enum values
+ */
+ public static List getEnumList()
+ {
+ return getEnumList(CascadeActionEnum.class);
+ }
+
+ /**
+ * Returns an iterator of all enum values.
+ *
+ * @return The iterator
+ */
+ public static Iterator iterator()
+ {
+ return iterator(CascadeActionEnum.class);
+ }
+}
diff --git a/src/java/org/apache/ddlutils/model/ForeignKey.java b/src/java/org/apache/ddlutils/model/ForeignKey.java
index 3db04be..3d3fc82 100644
--- a/src/java/org/apache/ddlutils/model/ForeignKey.java
+++ b/src/java/org/apache/ddlutils/model/ForeignKey.java
@@ -39,6 +39,10 @@
private Table _foreignTable;
/** The name of the foreign table. */
private String _foreignTableName;
+ /** The action to perform when the value of the referenced column changes. */
+ private CascadeActionEnum _onUpdate = CascadeActionEnum.NONE;
+ /** The action to perform when the referenced row is deleted. */
+ private CascadeActionEnum _onDelete = CascadeActionEnum.NONE;
/** The references between local and remote columns. */
private ListOrderedSet _references = new ListOrderedSet();
/** Whether this foreign key has an associated auto-generated index. */
@@ -130,6 +134,56 @@
}
/**
+ * Returns the action for this foreignkey for when the referenced row is deleted.
+ *
+ * @return The action
+ */
+ public CascadeActionEnum getOnDelete()
+ {
+ return _onDelete;
+ }
+
+ /**
+ * Sets the action for this foreignkey for when the referenced row is deleted.
+ *
+ * @param onDelete The action
+ * @throws NullPointerException If <code>onDelete</code> is null
+ */
+ public void setOnDelete(CascadeActionEnum onDelete) throws NullPointerException
+ {
+ if (onDelete == null)
+ {
+ throw new NullPointerException("The onDelete action cannot be null");
+ }
+ _onDelete = onDelete;
+ }
+
+ /**
+ * Returns the action for this foreignkey for when the referenced row is changed.
+ *
+ * @return The action
+ */
+ public CascadeActionEnum getOnUpdate()
+ {
+ return _onUpdate;
+ }
+
+ /**
+ * Sets the action for this foreignkey for when the referenced row is changed.
+ *
+ * @param onUpdate The action
+ * @throws NullPointerException If <code>onUdate</code> is null
+ */
+ public void setOnUpdate(CascadeActionEnum onUpdate) throws NullPointerException
+ {
+ if (onUpdate == null)
+ {
+ throw new NullPointerException("The onUpdate action cannot be null");
+ }
+ _onUpdate = onUpdate;
+ }
+
+ /**
* Returns the number of references.
*
* @return The number of references
diff --git a/src/test/org/apache/ddlutils/io/TestDatabaseIO.java b/src/test/org/apache/ddlutils/io/TestDatabaseIO.java
index 17d56f5..e84ddff 100644
--- a/src/test/org/apache/ddlutils/io/TestDatabaseIO.java
+++ b/src/test/org/apache/ddlutils/io/TestDatabaseIO.java
@@ -22,13 +22,11 @@
import java.io.StringReader;
import java.io.StringWriter;
import java.sql.Types;
-import java.util.Arrays;
import junit.framework.TestCase;
import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.ddlutils.model.CascadeActionEnum;
import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.ForeignKey;
@@ -37,17 +35,15 @@
import org.apache.ddlutils.model.ModelException;
import org.apache.ddlutils.model.Reference;
import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.model.TypeMap;
/**
- * Tests the database reading/writing via the {@link org.apache.ddlutils.io.DatabaseIO} class.
+ * Tests the database XML reading/writing via the {@link org.apache.ddlutils.io.DatabaseIO} class.
*
* @version $Revision: 289996 $
*/
public class TestDatabaseIO extends TestCase
{
- /** The log for the tests. */
- private final Log _log = LogFactory.getLog(TestDatabaseIO.class);
-
/**
* Reads the database model from the given string.
*
@@ -78,9 +74,426 @@
}
/**
- * Tests a simple database model.
+ * Asserts the data in a table object.
+ *
+ * @param name The expected name
+ * @param description The expected description
+ * @param numColumns The expected number of columns
+ * @param numPrimaryKeyColumns The expected number of primary key columns
+ * @param numAutoIncrementColumns The expected number of auto increment columns
+ * @param numForeignKeys The expected number of foreign keys
+ * @param numIndexes The expected number of indexes
+ * @param table The table
*/
- public void testSimple() throws Exception
+ private void assertEquals(String name,
+ String description,
+ int numColumns,
+ int numPrimaryKeyColumns,
+ int numAutoIncrementColumns,
+ int numForeignKeys,
+ int numIndexes,
+ Table table)
+ {
+ assertEquals(name, table.getName());
+ assertEquals(description, table.getDescription());
+ assertEquals(numColumns, table.getColumnCount());
+ assertEquals(numPrimaryKeyColumns, table.getPrimaryKeyColumns().length);
+ assertEquals(numAutoIncrementColumns, table.getAutoIncrementColumns().length);
+ assertEquals(numForeignKeys, table.getForeignKeyCount());
+ assertEquals(numIndexes, table.getIndexCount());
+ }
+
+ /**
+ * Asserts the data in a column object.
+ *
+ * @param name The expected name
+ * @param typeCode The exected JDBC type code
+ * @param size The expected size value
+ * @param scale The expected scale value
+ * @param defaultValue The expected default value
+ * @param description The expected description
+ * @param javaName The expected java name
+ * @param isPrimaryKey The expected primary key status
+ * @param isRequired The expected required satus
+ * @param isAutoIncrement The expected auto increment status
+ * @param column The column
+ */
+ private void assertEquals(String name,
+ int typeCode,
+ int size,
+ int scale,
+ String defaultValue,
+ String description,
+ String javaName,
+ boolean isPrimaryKey,
+ boolean isRequired,
+ boolean isAutoIncrement,
+ Column column)
+ {
+ assertEquals(name, column.getName());
+ assertEquals(TypeMap.getJdbcTypeName(typeCode), column.getType());
+ assertEquals(typeCode, column.getTypeCode());
+ assertEquals(size, column.getSizeAsInt());
+ assertEquals(size, column.getPrecisionRadix());
+ assertEquals(scale, column.getScale());
+ if ((size <= 0) && (scale <= 0)) {
+ assertNull(column.getSize());
+ }
+ else if (scale == 0) {
+ assertEquals("" + size, column.getSize());
+ }
+ else {
+ assertEquals("" + size + "," + scale, column.getSize());
+ }
+ assertEquals(defaultValue, column.getDefaultValue());
+ assertEquals(description, column.getDescription());
+ assertEquals(javaName, column.getJavaName());
+ assertEquals(isPrimaryKey, column.isPrimaryKey());
+ assertEquals(isRequired, column.isRequired());
+ assertEquals(isAutoIncrement, column.isAutoIncrement());
+ }
+
+ /**
+ * Asserts data in a foreign key object.
+ *
+ * @param name The expected name
+ * @param onUpdate The expected onUpdate action
+ * @param onDelete The expected onDelete action
+ * @param referencedTable The expected referenced table
+ * @param numReferences The expected number of references
+ * @param foreignKey The foreign key
+ */
+ private void assertEquals(String name,
+ CascadeActionEnum onUpdate,
+ CascadeActionEnum onDelete,
+ Table referencedTable,
+ int numReferences,
+ ForeignKey foreignKey)
+ {
+ assertEquals(name, foreignKey.getName());
+ assertEquals(onUpdate, foreignKey.getOnUpdate());
+ assertEquals(onDelete, foreignKey.getOnDelete());
+ assertEquals(referencedTable, foreignKey.getForeignTable());
+ assertEquals(referencedTable.getName(), foreignKey.getForeignTableName());
+ assertEquals(numReferences, foreignKey.getReferenceCount());
+ }
+
+ /**
+ * Asserts data in a reference object.
+ *
+ * @param localColumn The expected local column
+ * @param foreignColumn The expected foreign column
+ * @param ref The reference
+ */
+ private void assertEquals(Column localColumn, Column foreignColumn, Reference ref)
+ {
+ assertEquals(localColumn, ref.getLocalColumn());
+ assertEquals(localColumn.getName(), ref.getLocalColumnName());
+ assertEquals(foreignColumn, ref.getForeignColumn());
+ assertEquals(foreignColumn.getName(), ref.getForeignColumnName());
+ }
+
+ /**
+ * Asserts data in an index object.
+ *
+ * @param name The expected name
+ * @param isUnique The expected unique status
+ * @param numColumns The expected number of columns
+ * @param index The index
+ */
+ private void assertEquals(String name, boolean isUnique, int numColumns, Index index)
+ {
+ assertEquals(name, index.getName());
+ assertEquals(isUnique, index.isUnique());
+ assertEquals(numColumns, index.getColumnCount());
+ }
+
+ /**
+ * Asserts data in an index column object.
+ *
+ * @param column The expected column
+ * @param size The expected size value
+ * @param indexColumn The index column
+ */
+ private void assertEquals(Column column, String size, IndexColumn indexColumn)
+ {
+ assertEquals(column, indexColumn.getColumn());
+ assertEquals(column.getName(), indexColumn.getName());
+ assertEquals(size, indexColumn.getSize());
+ }
+
+ /**
+ * Asserts that the given database model, written to XML, is equal to the given
+ * expected XML.
+ *
+ * @param expectedXml The expected XML
+ * @param model The database model
+ */
+ private void assertEquals(String expectedXml, Database model)
+ {
+ assertEquals(expectedXml, writeModel(model));
+ }
+
+ /**
+ * Tests an XML document without a database element.
+ */
+ public void testNoDatabaseElement()
+ {
+ assertNull(readModel("<data-base></data-base>"));
+ }
+
+ /**
+ * Tests that an exception is generated when the database element has no name attribute.
+ */
+ public void testDatabaseWithoutName()
+ {
+ try
+ {
+ readModel(
+ "<database>\n" +
+ " <table name='TestTable'>\n" +
+ " <column name='id'\n" +
+ " type='INTEGER'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a database model without tables.
+ */
+ public void testNoTables() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ "</database>");
+
+ assertEquals("test",
+ model.getName());
+ assertEquals(0,
+ model.getTableCount());
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\" />\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with a table without columns.
+ */
+ public void testTableWithoutColumns() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+ assertEquals("SomeTable", "Some table", 0, 0, 0, 0, 0,
+ model.getTable(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\" />\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests that an exception is generated when the table element has no name attribute.
+ */
+ public void testTableWithoutName()
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table>\n" +
+ " <column name='id'\n" +
+ " type='INTEGER'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a database model with a table with a single column.
+ */
+ public void testSingleColumn() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='INTEGER'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", 1, 0, 0, 0, 0,
+ table);
+ assertEquals("ID", Types.INTEGER, 0, 0, null, null, null, false, false, false,
+ table.getColumn(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"false\" required=\"false\" type=\"INTEGER\" autoIncrement=\"false\" />\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests that an exception is generated when the column element has no name attribute.
+ */
+ public void testColumnWithoutName()
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='TestTable'>\n" +
+ " <column type='INTEGER'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests that an exception is generated when the column element has no type attribute.
+ */
+ public void testColumnWithoutType()
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='TestTable'>\n" +
+ " <column name='id'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a database model columns of all possible datatypes.
+ */
+ public void testColumnTypes() throws Exception
+ {
+ StringBuffer modelXml = new StringBuffer();
+ int[] types = TypeMap.getSuportedJdbcTypes();
+
+ modelXml.append("<database name='test'>\n");
+ modelXml.append(" <table name='SomeTable'\n");
+ modelXml.append(" description='Some table'>\n");
+ for (int idx = 0; idx < types.length; idx++)
+ {
+ modelXml.append(" <column name='ID");
+ modelXml.append(idx);
+ modelXml.append("' type='");
+ modelXml.append(TypeMap.getJdbcTypeName(types[idx]));
+ modelXml.append("'/>\n");
+ }
+ modelXml.append(" </table>\n");
+ modelXml.append("</database>");
+
+ Database model = readModel(modelXml.toString());
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", types.length, 0, 0, 0, 0,
+ table);
+
+ for (int idx = 0; idx < types.length; idx++)
+ {
+ assertEquals("ID" + idx, types[idx], 0, 0, null, null, null, false, false, false,
+ table.getColumn(idx));
+ }
+
+ modelXml.setLength(0);
+ modelXml.append("<?xml version='1.0' encoding='UTF-8'?>\n");
+ modelXml.append("<database name=\"test\">\n");
+ modelXml.append(" <table name=\"SomeTable\" description=\"Some table\">\n");
+ for (int idx = 0; idx < types.length; idx++)
+ {
+ modelXml.append(" <column name=\"ID");
+ modelXml.append(idx);
+ modelXml.append("\" primaryKey=\"false\" required=\"false\" type=\"");
+ modelXml.append(TypeMap.getJdbcTypeName(types[idx]));
+ modelXml.append("\" autoIncrement=\"false\" />\n");
+ }
+ modelXml.append(" </table>\n");
+ modelXml.append("</database>\n");
+
+ assertEquals(modelXml.toString(), model);
+ }
+
+ /**
+ * Tests an illegal column type.
+ */
+ public void testColumnWithIllegalType()
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='TestTable'>\n" +
+ " <column name='id'\n" +
+ " type='illegal'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a database model with a table with a primary key column.
+ */
+ public void testPrimaryKeyColumn() throws Exception
{
Database model = readModel(
"<database name='test'>\n" +
@@ -88,61 +501,290 @@
" description='Some table'>\n" +
" <column name='ID'\n" +
" type='INTEGER'\n" +
- " primaryKey='true'\n" +
- " required='true'\n" +
- " description='The primary key'\n" +
- " javaName='javaId'/>\n" +
+ " primaryKey='true'/>\n" +
" </table>\n" +
"</database>");
- assertEquals("test",
- model.getName());
- assertEquals(1,
- model.getTableCount());
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
Table table = model.getTable(0);
- assertEquals("SomeTable",
- table.getName());
- assertEquals("Some table",
- table.getDescription());
- assertEquals(0, table.getAutoIncrementColumns().length);
- assertEquals(1,
- table.getColumnCount());
- assertEquals(0,
- table.getForeignKeyCount());
- assertEquals(0,
- table.getIndexCount());
+ assertEquals("SomeTable", "Some table", 1, 1, 0, 0, 0,
+ table);
Column column = table.getColumn(0);
- assertEquals("ID",
- column.getName());
- assertEquals("INTEGER",
- column.getType());
- assertEquals(Types.INTEGER,
- column.getTypeCode());
- assertTrue(column.isPrimaryKey());
- assertTrue(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertEquals("The primary key",
- column.getDescription());
- assertEquals("javaId", column.getJavaName());
+ assertEquals("ID", Types.INTEGER, 0, 0, null, null, null, true, false, false,
+ column);
+
+ assertEquals(column, table.getPrimaryKeyColumns()[0]);
+
assertEquals(
- "<?xml version=\"1.0\"?>\n<!DOCTYPE database SYSTEM \"" + LocalEntityResolver.DTD_PREFIX + "\">\n" +
- " <database name=\"test\">\n" +
- " <table name=\"SomeTable\" description=\"Some table\">\n" +
- " <column name=\"ID\" primaryKey=\"true\" required=\"true\" type=\"INTEGER\" autoIncrement=\"false\" description=\"The primary key\" javaName=\"javaId\"/>\n" +
- " </table>\n" +
- " </database>\n",
- writeModel(model));
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"true\" required=\"false\" type=\"INTEGER\" autoIncrement=\"false\" />\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
}
/**
- * Tests a database model containing a foreignkey.
+ * Tests a database model with a table with a required column.
*/
- public void testForeignkey() throws Exception
+ public void testRequiredColumn() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='INTEGER'\n" +
+ " required='true'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", 1, 0, 0, 0, 0,
+ table);
+ assertEquals("ID", Types.INTEGER, 0, 0, null, null, null, false, true, false,
+ table.getColumn(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"false\" required=\"true\" type=\"INTEGER\" autoIncrement=\"false\" />\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with a table with an autoincrement column.
+ */
+ public void testAutoIncrementColumn() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='INTEGER'\n" +
+ " autoIncrement='true'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", 1, 0, 1, 0, 0,
+ table);
+
+ Column column = table.getColumn(0);
+
+ assertEquals("ID", Types.INTEGER, 0, 0, null, null, null, false, false, true,
+ column);
+
+ assertEquals(column, table.getAutoIncrementColumns()[0]);
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"false\" required=\"false\" type=\"INTEGER\" autoIncrement=\"true\" />\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with a table with a column with a size spec.
+ */
+ public void testColumnWithSize1() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='20'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", 1, 0, 0, 0, 0,
+ table);
+ assertEquals("ID", Types.VARCHAR, 20, 0, null, null, null, false, false, false,
+ table.getColumn(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"false\" required=\"false\" type=\"VARCHAR\" size=\"20\" autoIncrement=\"false\" />\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with a table with a column with a size spec.
+ */
+ public void testColumnWithSize2() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='DECIMAL'\n" +
+ " size='10,3'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", 1, 0, 0, 0, 0,
+ table);
+ assertEquals("ID", Types.DECIMAL, 10, 3, null, null, null, false, false, false,
+ table.getColumn(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"false\" required=\"false\" type=\"DECIMAL\" size=\"10,3\" autoIncrement=\"false\" />\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with a table with a column with a description.
+ */
+ public void testColumnWithDescription() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='INTEGER'\n" +
+ " description='Foo'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", 1, 0, 0, 0, 0,
+ table);
+ assertEquals("ID", Types.INTEGER, 0, 0, null, "Foo", null, false, false, false,
+ table.getColumn(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"false\" required=\"false\" type=\"INTEGER\" autoIncrement=\"false\" description=\"Foo\" />\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with a table with a column with a default.
+ */
+ public void testColumnWithDefault() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='32'\n" +
+ " default='Test string'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", 1, 0, 0, 0, 0,
+ table);
+ assertEquals("ID", Types.VARCHAR, 32, 0, "Test string", null, null, false, false, false,
+ table.getColumn(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"false\" required=\"false\" type=\"VARCHAR\" size=\"32\" default=\"Test string\" autoIncrement=\"false\" />\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with a table with a column with a java name.
+ */
+ public void testColumnWithJavaName() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='DOUBLE'\n" +
+ " javaName='testString'/>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", 1, 0, 0, 0, 0,
+ table);
+ assertEquals("ID", Types.DOUBLE, 0, 0, null, null, "testString", false, false, false,
+ table.getColumn(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"false\" required=\"false\" type=\"DOUBLE\" autoIncrement=\"false\" javaName=\"testString\" />\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model containing a single foreignkey.
+ */
+ public void testSingleForeignkey() throws Exception
{
Database model = readModel(
"<database name='test'>\n" +
@@ -167,117 +809,612 @@
" </table>\n" +
"</database>");
- assertEquals("test",
- model.getName());
- assertEquals(2,
- model.getTableCount());
+ assertEquals("test", model.getName());
+ assertEquals(2, model.getTableCount());
Table someTable = model.getTable(0);
- assertEquals("SomeTable",
- someTable.getName());
- assertEquals("Some table",
- someTable.getDescription());
- assertEquals(0, someTable.getAutoIncrementColumns().length);
- assertEquals(1,
- someTable.getColumnCount());
- assertEquals(0,
- someTable.getForeignKeyCount());
- assertEquals(0,
- someTable.getIndexCount());
+ assertEquals("SomeTable", "Some table", 1, 1, 0, 0, 0,
+ someTable);
Column pkColumn = someTable.getColumn(0);
- assertEquals("ID",
- pkColumn.getName());
- assertEquals("VARCHAR",
- pkColumn.getType());
- assertEquals(Types.VARCHAR,
- pkColumn.getTypeCode());
- assertEquals(16,
- pkColumn.getSizeAsInt());
- assertTrue(pkColumn.isPrimaryKey());
- assertTrue(pkColumn.isRequired());
- assertFalse(pkColumn.isAutoIncrement());
- assertNull(pkColumn.getDefaultValue());
- assertEquals("The primary key",
- pkColumn.getDescription());
+ assertEquals("ID", Types.VARCHAR, 16, 0, null, "The primary key", null, true, true, false,
+ pkColumn);
Table anotherTable = model.getTable(1);
- assertEquals("AnotherTable",
- anotherTable.getName());
- assertEquals("And another table",
- anotherTable.getDescription());
- assertEquals(0, anotherTable.getAutoIncrementColumns().length);
- assertEquals(1,
- anotherTable.getColumnCount());
- assertEquals(1,
- anotherTable.getForeignKeyCount());
- assertEquals(0,
- anotherTable.getIndexCount());
+ assertEquals("AnotherTable", "And another table", 1, 0, 0, 1, 0,
+ anotherTable);
Column fkColumn = anotherTable.getColumn(0);
- assertEquals("Some_ID",
- fkColumn.getName());
- assertEquals("VARCHAR",
- fkColumn.getType());
- assertEquals(Types.VARCHAR,
- fkColumn.getTypeCode());
- assertEquals(16,
- fkColumn.getSizeAsInt());
- assertFalse(fkColumn.isPrimaryKey());
- assertFalse(fkColumn.isRequired());
- assertFalse(fkColumn.isAutoIncrement());
- assertEquals("The foreign key",
- fkColumn.getDescription());
+ assertEquals("Some_ID", Types.VARCHAR, 16, 0, null, "The foreign key", null, false, false, false,
+ fkColumn);
ForeignKey fk = anotherTable.getForeignKey(0);
- assertNull(fk.getName());
- assertEquals(someTable,
- fk.getForeignTable());
- assertEquals(someTable.getName(),
- fk.getForeignTableName());
- assertEquals(1,
- fk.getReferenceCount());
-
- Reference ref = fk.getFirstReference();
-
- assertEquals(fkColumn,
- ref.getLocalColumn());
- assertEquals("Some_ID",
- ref.getLocalColumnName());
- assertEquals(pkColumn,
- ref.getForeignColumn());
- assertEquals("ID",
- ref.getForeignColumnName());
+ assertEquals(null, CascadeActionEnum.NONE, CascadeActionEnum.NONE, someTable, 1, fk);
+ assertEquals(fkColumn, pkColumn, fk.getFirstReference());
assertEquals(
- "<?xml version=\"1.0\"?>\n<!DOCTYPE database SYSTEM \"" + LocalEntityResolver.DTD_PREFIX + "\">\n" +
- " <database name=\"test\">\n" +
- " <table name=\"SomeTable\" description=\"Some table\">\n" +
- " <column name=\"ID\" primaryKey=\"true\" required=\"true\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" description=\"The primary key\"/>\n" +
- " </table>\n" +
- " <table name=\"AnotherTable\" description=\"And another table\">\n" +
- " <column name=\"Some_ID\" primaryKey=\"false\" required=\"false\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" description=\"The foreign key\"/>\n" +
- " <foreign-key foreignTable=\"SomeTable\">\n" +
- " <reference local=\"Some_ID\" foreign=\"ID\"/>\n" +
- " </foreign-key>\n" +
- " </table>\n" +
- " </database>\n",
- writeModel(model));
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"true\" required=\"true\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" description=\"The primary key\" />\n" +
+ " </table>\n" +
+ " <table name=\"AnotherTable\" description=\"And another table\">\n" +
+ " <column name=\"Some_ID\" primaryKey=\"false\" required=\"false\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" description=\"The foreign key\" />\n" +
+ " <foreign-key foreignTable=\"SomeTable\">\n" +
+ " <reference local=\"Some_ID\" foreign=\"ID\" />\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
}
/**
- * Tests a database model with indices.
+ * Tests a database model containing a foreignkey with two references.
*/
- public void testIndices1() throws Exception
+ public void testForeignkeyWithTwoReferences() throws Exception
{
Database model = readModel(
"<database name='test'>\n" +
- " <table name='TableWidthIndex'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " primaryKey='true'\n" +
+ " required='true'\n" +
+ " description='The primary key'/>\n" +
+ " <column name='VALUE1'\n" +
+ " type='INTEGER'\n" +
+ " required='false'\n" +
+ " description='A value'/>\n" +
+ " <column name='VALUE2'\n" +
+ " type='DOUBLE'\n" +
+ " required='false'\n" +
+ " description='Another value'/>\n" +
+ " </table>\n" +
+ " <table name='AnotherTable'\n" +
+ " description='And another table'>\n" +
+ " <column name='Some_ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " description='The foreign key'/>\n" +
+ " <column name='Some_Value'\n" +
+ " type='DOUBLE'/>\n" +
+ " <foreign-key foreignTable='SomeTable'>\n" +
+ " <reference local='Some_ID' foreign='ID'/>\n" +
+ " <reference local='Some_Value' foreign='VALUE2'/>\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(2, model.getTableCount());
+
+ Table someTable = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", 3, 1, 0, 0, 0,
+ someTable);
+ assertEquals("ID", Types.VARCHAR, 16, 0, null, "The primary key", null, true, true, false,
+ someTable.getColumn(0));
+
+ Table anotherTable = model.getTable(1);
+
+ assertEquals("AnotherTable", "And another table", 2, 0, 0, 1, 0,
+ anotherTable);
+ assertEquals("Some_ID", Types.VARCHAR, 16, 0, null, "The foreign key", null, false, false, false,
+ anotherTable.getColumn(0));
+
+ ForeignKey fk = anotherTable.getForeignKey(0);
+
+ assertEquals(null, CascadeActionEnum.NONE, CascadeActionEnum.NONE, someTable, 2, fk);
+ assertEquals(anotherTable.getColumn(0), someTable.getColumn(0), fk.getReference(0));
+ assertEquals(anotherTable.getColumn(1), someTable.getColumn(2), fk.getReference(1));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"true\" required=\"true\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" description=\"The primary key\" />\n" +
+ " <column name=\"VALUE1\" primaryKey=\"false\" required=\"false\" type=\"INTEGER\" autoIncrement=\"false\" description=\"A value\" />\n" +
+ " <column name=\"VALUE2\" primaryKey=\"false\" required=\"false\" type=\"DOUBLE\" autoIncrement=\"false\" description=\"Another value\" />\n" +
+ " </table>\n" +
+ " <table name=\"AnotherTable\" description=\"And another table\">\n" +
+ " <column name=\"Some_ID\" primaryKey=\"false\" required=\"false\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" description=\"The foreign key\" />\n" +
+ " <column name=\"Some_Value\" primaryKey=\"false\" required=\"false\" type=\"DOUBLE\" autoIncrement=\"false\" />\n" +
+ " <foreign-key foreignTable=\"SomeTable\">\n" +
+ " <reference local=\"Some_ID\" foreign=\"ID\" />\n" +
+ " <reference local=\"Some_Value\" foreign=\"VALUE2\" />\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a foreign key without references.
+ */
+ public void testForeignKeyWithoutReferences()
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " primaryKey='true'\n" +
+ " required='true'\n" +
+ " description='The primary key'/>\n" +
+ " </table>\n" +
+ " <table name='AnotherTable'\n" +
+ " description='And another table'>\n" +
+ " <column name='Some_ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " description='The foreign key'/>\n" +
+ " <foreign-key foreignTable='SomeTable'>\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a database model containing a named foreignkey.
+ */
+ public void testNamedForeignkey() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " primaryKey='true'\n" +
+ " required='true'\n" +
+ " description='The primary key'/>\n" +
+ " </table>\n" +
+ " <table name='AnotherTable'\n" +
+ " description='And another table'>\n" +
+ " <column name='Some_ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " description='The foreign key'/>\n" +
+ " <foreign-key name='The foreignkey' foreignTable='SomeTable'>\n" +
+ " <reference local='Some_ID' foreign='ID'/>\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(2, model.getTableCount());
+
+ Table someTable = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", 1, 1, 0, 0, 0,
+ someTable);
+ assertEquals("ID", Types.VARCHAR, 16, 0, null, "The primary key", null, true, true, false,
+ someTable.getColumn(0));
+
+ Table anotherTable = model.getTable(1);
+
+ assertEquals("AnotherTable", "And another table", 1, 0, 0, 1, 0,
+ anotherTable);
+ assertEquals("Some_ID", Types.VARCHAR, 16, 0, null, "The foreign key", null, false, false, false,
+ anotherTable.getColumn(0));
+
+ ForeignKey fk = anotherTable.getForeignKey(0);
+
+ assertEquals("The foreignkey", CascadeActionEnum.NONE, CascadeActionEnum.NONE, someTable, 1, fk);
+ assertEquals(anotherTable.getColumn(0), someTable.getColumn(0), fk.getReference(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"true\" required=\"true\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" description=\"The primary key\" />\n" +
+ " </table>\n" +
+ " <table name=\"AnotherTable\" description=\"And another table\">\n" +
+ " <column name=\"Some_ID\" primaryKey=\"false\" required=\"false\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" description=\"The foreign key\" />\n" +
+ " <foreign-key foreignTable=\"SomeTable\" name=\"The foreignkey\">\n" +
+ " <reference local=\"Some_ID\" foreign=\"ID\" />\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a foreign key referencing a non-existing table.
+ */
+ public void testForeignKeyReferencingUndefinedTable()
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " primaryKey='true'\n" +
+ " required='true'\n" +
+ " description='The primary key'/>\n" +
+ " </table>\n" +
+ " <table name='AnotherTable'\n" +
+ " description='And another table'>\n" +
+ " <column name='Some_ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " description='The foreign key'/>\n" +
+ " <foreign-key foreignTable='TheTable'>\n" +
+ " <reference local='Some_ID' foreign='ID'/>\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a foreign key using a non-existing column in the local table.
+ */
+ public void testForeignKeyUsingUndefinedColumn()
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " primaryKey='true'\n" +
+ " required='true'\n" +
+ " description='The primary key'/>\n" +
+ " </table>\n" +
+ " <table name='AnotherTable'\n" +
+ " description='And another table'>\n" +
+ " <column name='Some_ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " description='The foreign key'/>\n" +
+ " <foreign-key foreignTable='SomeTable'>\n" +
+ " <reference local='ID' foreign='ID'/>\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a foreign key referencing a non-existing column in the foreign table.
+ */
+ public void testForeignKeyReferencingUndefinedColumn()
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " primaryKey='true'\n" +
+ " required='true'\n" +
+ " description='The primary key'/>\n" +
+ " </table>\n" +
+ " <table name='AnotherTable'\n" +
+ " description='And another table'>\n" +
+ " <column name='Some_ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " description='The foreign key'/>\n" +
+ " <foreign-key foreignTable='SomeTable'>\n" +
+ " <reference local='Some_ID' foreign='TheID'/>\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a foreign key without a local column.
+ */
+ public void testForeignKeyWithoutLocalColumn()
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " primaryKey='true'\n" +
+ " required='true'\n" +
+ " description='The primary key'/>\n" +
+ " </table>\n" +
+ " <table name='AnotherTable'\n" +
+ " description='And another table'>\n" +
+ " <column name='Some_ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " description='The foreign key'/>\n" +
+ " <foreign-key foreignTable='SomeTable'>\n" +
+ " <reference foreign='ID'/>\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a foreign key without a remote column.
+ */
+ public void testForeignKeyWithoutRemoteColumn()
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " primaryKey='true'\n" +
+ " required='true'\n" +
+ " description='The primary key'/>\n" +
+ " </table>\n" +
+ " <table name='AnotherTable'\n" +
+ " description='And another table'>\n" +
+ " <column name='Some_ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " description='The foreign key'/>\n" +
+ " <foreign-key foreignTable='SomeTable'>\n" +
+ " <reference local='Some_ID'/>\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a database model containing two foreignkeys.
+ */
+ public void testTwoForeignkeys() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " primaryKey='true'\n" +
+ " required='true'\n" +
+ " description='The primary key'/>\n" +
+ " <column name='VALUE1'\n" +
+ " type='INTEGER'\n" +
+ " required='false'\n" +
+ " description='A value'/>\n" +
+ " <column name='VALUE2'\n" +
+ " type='DOUBLE'\n" +
+ " required='false'\n" +
+ " description='Another value'/>\n" +
+ " </table>\n" +
+ " <table name='AnotherTable'\n" +
+ " description='And another table'>\n" +
+ " <column name='Some_ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " description='The foreign key'/>\n" +
+ " <column name='Some_Value'\n" +
+ " type='DOUBLE'/>\n" +
+ " <foreign-key foreignTable='SomeTable'>\n" +
+ " <reference local='Some_ID' foreign='ID'/>\n" +
+ " </foreign-key>\n" +
+ " <foreign-key foreignTable='SomeTable'>\n" +
+ " <reference local='Some_Value' foreign='VALUE2'/>\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(2, model.getTableCount());
+
+ Table someTable = model.getTable(0);
+
+ assertEquals("SomeTable", "Some table", 3, 1, 0, 0, 0,
+ someTable);
+ assertEquals("ID", Types.VARCHAR, 16, 0, null, "The primary key", null, true, true, false,
+ someTable.getColumn(0));
+
+ Table anotherTable = model.getTable(1);
+
+ assertEquals("AnotherTable", "And another table", 2, 0, 0, 2, 0,
+ anotherTable);
+ assertEquals("Some_ID", Types.VARCHAR, 16, 0, null, "The foreign key", null, false, false, false,
+ anotherTable.getColumn(0));
+
+ ForeignKey fk = anotherTable.getForeignKey(0);
+
+ assertEquals(null, CascadeActionEnum.NONE, CascadeActionEnum.NONE, someTable, 1, fk);
+ assertEquals(anotherTable.getColumn(0), someTable.getColumn(0), fk.getReference(0));
+
+ fk = anotherTable.getForeignKey(1);
+
+ assertEquals(null, CascadeActionEnum.NONE, CascadeActionEnum.NONE, someTable, 1, fk);
+ assertEquals(anotherTable.getColumn(1), someTable.getColumn(2), fk.getReference(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\" description=\"Some table\">\n" +
+ " <column name=\"ID\" primaryKey=\"true\" required=\"true\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" description=\"The primary key\" />\n" +
+ " <column name=\"VALUE1\" primaryKey=\"false\" required=\"false\" type=\"INTEGER\" autoIncrement=\"false\" description=\"A value\" />\n" +
+ " <column name=\"VALUE2\" primaryKey=\"false\" required=\"false\" type=\"DOUBLE\" autoIncrement=\"false\" description=\"Another value\" />\n" +
+ " </table>\n" +
+ " <table name=\"AnotherTable\" description=\"And another table\">\n" +
+ " <column name=\"Some_ID\" primaryKey=\"false\" required=\"false\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" description=\"The foreign key\" />\n" +
+ " <column name=\"Some_Value\" primaryKey=\"false\" required=\"false\" type=\"DOUBLE\" autoIncrement=\"false\" />\n" +
+ " <foreign-key foreignTable=\"SomeTable\">\n" +
+ " <reference local=\"Some_ID\" foreign=\"ID\" />\n" +
+ " </foreign-key>\n" +
+ " <foreign-key foreignTable=\"SomeTable\">\n" +
+ " <reference local=\"Some_Value\" foreign=\"VALUE2\" />\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model containing two foreignkeys with the same name.
+ */
+ public void testTwoForeignkeysWithSameName() throws Exception
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='SomeTable'\n" +
+ " description='Some table'>\n" +
+ " <column name='ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " primaryKey='true'\n" +
+ " required='true'\n" +
+ " description='The primary key'/>\n" +
+ " <column name='VALUE1'\n" +
+ " type='INTEGER'\n" +
+ " required='false'\n" +
+ " description='A value'/>\n" +
+ " <column name='VALUE2'\n" +
+ " type='DOUBLE'\n" +
+ " required='false'\n" +
+ " description='Another value'/>\n" +
+ " </table>\n" +
+ " <table name='AnotherTable'\n" +
+ " description='And another table'>\n" +
+ " <column name='Some_ID'\n" +
+ " type='VARCHAR'\n" +
+ " size='16'\n" +
+ " description='The foreign key'/>\n" +
+ " <column name='Some_Value'\n" +
+ " type='DOUBLE'/>\n" +
+ " <foreign-key name='The foreignkey' foreignTable='SomeTable'>\n" +
+ " <reference local='Some_ID' foreign='ID'/>\n" +
+ " </foreign-key>\n" +
+ " <foreign-key name='The foreignkey' foreignTable='SomeTable'>\n" +
+ " <reference local='Some_Value' foreign='VALUE2'/>\n" +
+ " </foreign-key>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a database model with an index.
+ */
+ public void testSingleIndex() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
+ " <column name='id'\n" +
+ " type='DOUBLE'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " <column name='value'\n" +
+ " type='SMALLINT'\n" +
+ " default='1'/>\n" +
+ " <index>\n" +
+ " <index-column name='value'/>\n" +
+ " </index>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("TableWithIndex", null, 2, 1, 0, 0, 1,
+ table);
+ assertEquals("id", Types.DOUBLE, 0, 0, null, null, null, true, true, false,
+ table.getColumn(0));
+ assertEquals("value", Types.SMALLINT, 0, 0, "1", null, null, false, false, false,
+ table.getColumn(1));
+
+ Index index = table.getIndex(0);
+
+ assertEquals(null, false, 1, index);
+ assertEquals(table.getColumn(1), null, index.getColumn(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"TableWithIndex\">\n" +
+ " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"DOUBLE\" autoIncrement=\"false\" />\n" +
+ " <column name=\"value\" primaryKey=\"false\" required=\"false\" type=\"SMALLINT\" default=\"1\" autoIncrement=\"false\" />\n" +
+ " <index>\n" +
+ " <index-column name=\"value\" />\n" +
+ " </index>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with an index with two columns.
+ */
+ public void testIndexWithTwoColumns() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
" <column name='id'\n" +
" type='DOUBLE'\n" +
" primaryKey='true'\n" +
@@ -288,9 +1425,6 @@
" <column name='value'\n" +
" type='SMALLINT'\n" +
" default='1'/>\n" +
- " <index name='test index'>\n" +
- " <index-column name='value'/>\n" +
- " </index>\n" +
" <index>\n" +
" <index-column name='when'/>\n" +
" <index-column name='id'/>\n" +
@@ -298,128 +1432,440 @@
" </table>\n" +
"</database>");
- assertEquals("test",
- model.getName());
- assertEquals(1,
- model.getTableCount());
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
Table table = model.getTable(0);
- assertEquals("TableWidthIndex",
- table.getName());
- assertNull(table.getDescription());
- assertEquals(0, table.getAutoIncrementColumns().length);
- assertEquals(3,
- table.getColumnCount());
- assertEquals(0,
- table.getForeignKeyCount());
- assertEquals(2,
- table.getIndexCount());
-
- Column column = table.getColumn(0);
-
- assertEquals("id",
- column.getName());
- assertEquals("DOUBLE",
- column.getType());
- assertEquals(Types.DOUBLE,
- column.getTypeCode());
- assertTrue(column.isPrimaryKey());
- assertTrue(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertNull(column.getDefaultValue());
- assertNull(column.getDescription());
-
- column = table.getColumn(1);
-
- assertEquals("when",
- column.getName());
- assertEquals("TIMESTAMP",
- column.getType());
- assertEquals(Types.TIMESTAMP,
- column.getTypeCode());
- assertFalse(column.isPrimaryKey());
- assertTrue(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertNull(column.getDescription());
-
- column = table.getColumn(2);
-
- assertEquals("value",
- column.getName());
- assertEquals("SMALLINT",
- column.getType());
- assertEquals(Types.SMALLINT,
- column.getTypeCode());
- assertFalse(column.isPrimaryKey());
- assertFalse(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertEquals("1",
- column.getDefaultValue());
- assertNull(column.getDescription());
+ assertEquals("TableWithIndex", null, 3, 1, 0, 0, 1,
+ table);
+ assertEquals("id", Types.DOUBLE, 0, 0, null, null, null, true, true, false,
+ table.getColumn(0));
+ assertEquals("when", Types.TIMESTAMP, 0, 0, null, null, null, false, true, false,
+ table.getColumn(1));
+ assertEquals("value", Types.SMALLINT, 0, 0, "1", null, null, false, false, false,
+ table.getColumn(2));
Index index = table.getIndex(0);
- assertEquals("test index",
- index.getName());
- assertFalse(index.isUnique());
- assertEquals(1,
- index.getColumnCount());
-
- IndexColumn indexColumn = index.getColumn(0);
-
- assertEquals("value",
- indexColumn.getName());
- assertNull(indexColumn.getSize());
-
- index = table.getIndex(1);
-
- assertNull(index.getName());
- assertFalse(index.isUnique());
- assertEquals(2,
- index.getColumnCount());
-
- indexColumn = index.getColumn(0);
-
- assertEquals("when",
- indexColumn.getName());
- assertNull(indexColumn.getSize());
-
- indexColumn = index.getColumn(1);
-
- assertEquals("id",
- indexColumn.getName());
- assertNull(indexColumn.getSize());
+ assertEquals(null, false, 2, index);
+ assertEquals(table.getColumn(1), null, index.getColumn(0));
+ assertEquals(table.getColumn(0), null, index.getColumn(1));
assertEquals(
- "<?xml version=\"1.0\"?>\n<!DOCTYPE database SYSTEM \"" + LocalEntityResolver.DTD_PREFIX + "\">\n" +
- " <database name=\"test\">\n" +
- " <table name=\"TableWidthIndex\">\n" +
- " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"DOUBLE\" autoIncrement=\"false\"/>\n" +
- " <column name=\"when\" primaryKey=\"false\" required=\"true\" type=\"TIMESTAMP\" autoIncrement=\"false\"/>\n" +
- " <column name=\"value\" primaryKey=\"false\" required=\"false\" type=\"SMALLINT\" default=\"1\" autoIncrement=\"false\"/>\n" +
- " <index name=\"test index\">\n" +
- " <index-column name=\"value\"/>\n" +
- " </index>\n" +
- " <index>\n" +
- " <index-column name=\"when\"/>\n" +
- " <index-column name=\"id\"/>\n" +
- " </index>\n" +
- " </table>\n" +
- " </database>\n",
- writeModel(model));
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"TableWithIndex\">\n" +
+ " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"DOUBLE\" autoIncrement=\"false\" />\n" +
+ " <column name=\"when\" primaryKey=\"false\" required=\"true\" type=\"TIMESTAMP\" autoIncrement=\"false\" />\n" +
+ " <column name=\"value\" primaryKey=\"false\" required=\"false\" type=\"SMALLINT\" default=\"1\" autoIncrement=\"false\" />\n" +
+ " <index>\n" +
+ " <index-column name=\"when\" />\n" +
+ " <index-column name=\"id\" />\n" +
+ " </index>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with an index with a name.
+ */
+ public void testIndexWithName() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
+ " <column name='id'\n" +
+ " type='DOUBLE'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " <column name='value'\n" +
+ " type='SMALLINT'\n" +
+ " default='1'/>\n" +
+ " <index name='The Index'>\n" +
+ " <index-column name='value'/>\n" +
+ " </index>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("TableWithIndex", null, 2, 1, 0, 0, 1,
+ table);
+ assertEquals("id", Types.DOUBLE, 0, 0, null, null, null, true, true, false,
+ table.getColumn(0));
+ assertEquals("value", Types.SMALLINT, 0, 0, "1", null, null, false, false, false,
+ table.getColumn(1));
+
+ Index index = table.getIndex(0);
+
+ assertEquals("The Index", false, 1, index);
+ assertEquals(table.getColumn(1), null, index.getColumn(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"TableWithIndex\">\n" +
+ " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"DOUBLE\" autoIncrement=\"false\" />\n" +
+ " <column name=\"value\" primaryKey=\"false\" required=\"false\" type=\"SMALLINT\" default=\"1\" autoIncrement=\"false\" />\n" +
+ " <index name=\"The Index\">\n" +
+ " <index-column name=\"value\" />\n" +
+ " </index>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with an index without index columns.
+ */
+ public void testIndexWithoutColumns() throws Exception
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
+ " <column name='id'\n" +
+ " type='DOUBLE'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " <column name='value'\n" +
+ " type='SMALLINT'\n" +
+ " default='1'/>\n" +
+ " <index>\n" +
+ " </index>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a database model with an index with an index column that references an undefined column.
+ */
+ public void testIndexWithUndefinedColumns() throws Exception
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
+ " <column name='id'\n" +
+ " type='DOUBLE'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " <column name='value'\n" +
+ " type='SMALLINT'\n" +
+ " default='1'/>\n" +
+ " <index>\n" +
+ " <index-column name='theValue'/>\n" +
+ " </index>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a database model with an index with an index column that has no name.
+ */
+ public void testIndexWithNoNameColumn() throws Exception
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
+ " <column name='id'\n" +
+ " type='DOUBLE'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " <column name='value'\n" +
+ " type='SMALLINT'\n" +
+ " default='1'/>\n" +
+ " <index>\n" +
+ " <index-column/>\n" +
+ " </index>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+
+ /**
+ * Tests a database model with an unique index.
+ */
+ public void testSingleUniqueIndex() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
+ " <column name='id'\n" +
+ " type='DOUBLE'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " <column name='value'\n" +
+ " type='SMALLINT'\n" +
+ " default='1'/>\n" +
+ " <unique>\n" +
+ " <unique-column name='value'/>\n" +
+ " </unique>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("TableWithIndex", null, 2, 1, 0, 0, 1,
+ table);
+ assertEquals("id", Types.DOUBLE, 0, 0, null, null, null, true, true, false,
+ table.getColumn(0));
+ assertEquals("value", Types.SMALLINT, 0, 0, "1", null, null, false, false, false,
+ table.getColumn(1));
+
+ Index index = table.getIndex(0);
+
+ assertEquals(null, true, 1, index);
+ assertEquals(table.getColumn(1), null, index.getColumn(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"TableWithIndex\">\n" +
+ " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"DOUBLE\" autoIncrement=\"false\" />\n" +
+ " <column name=\"value\" primaryKey=\"false\" required=\"false\" type=\"SMALLINT\" default=\"1\" autoIncrement=\"false\" />\n" +
+ " <unique>\n" +
+ " <unique-column name=\"value\" />\n" +
+ " </unique>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with an unique index with two columns.
+ */
+ public void testUniqueIndexWithTwoColumns() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
+ " <column name='id'\n" +
+ " type='DOUBLE'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " <column name='when'\n" +
+ " type='TIMESTAMP'\n" +
+ " required='true'/>\n" +
+ " <column name='value'\n" +
+ " type='SMALLINT'\n" +
+ " default='1'/>\n" +
+ " <unique>\n" +
+ " <unique-column name='when'/>\n" +
+ " <unique-column name='id'/>\n" +
+ " </unique>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("TableWithIndex", null, 3, 1, 0, 0, 1,
+ table);
+ assertEquals("id", Types.DOUBLE, 0, 0, null, null, null, true, true, false,
+ table.getColumn(0));
+ assertEquals("when", Types.TIMESTAMP, 0, 0, null, null, null, false, true, false,
+ table.getColumn(1));
+ assertEquals("value", Types.SMALLINT, 0, 0, "1", null, null, false, false, false,
+ table.getColumn(2));
+
+ Index index = table.getIndex(0);
+
+ assertEquals(null, true, 2, index);
+ assertEquals(table.getColumn(1), null, index.getColumn(0));
+ assertEquals(table.getColumn(0), null, index.getColumn(1));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"TableWithIndex\">\n" +
+ " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"DOUBLE\" autoIncrement=\"false\" />\n" +
+ " <column name=\"when\" primaryKey=\"false\" required=\"true\" type=\"TIMESTAMP\" autoIncrement=\"false\" />\n" +
+ " <column name=\"value\" primaryKey=\"false\" required=\"false\" type=\"SMALLINT\" default=\"1\" autoIncrement=\"false\" />\n" +
+ " <unique>\n" +
+ " <unique-column name=\"when\" />\n" +
+ " <unique-column name=\"id\" />\n" +
+ " </unique>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with an unique index with a name.
+ */
+ public void testUniqueIndexWithName() throws Exception
+ {
+ Database model = readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
+ " <column name='id'\n" +
+ " type='DOUBLE'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " <column name='value'\n" +
+ " type='SMALLINT'\n" +
+ " default='1'/>\n" +
+ " <unique name='The Index'>\n" +
+ " <unique-column name='value'/>\n" +
+ " </unique>\n" +
+ " </table>\n" +
+ "</database>");
+
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
+
+ Table table = model.getTable(0);
+
+ assertEquals("TableWithIndex", null, 2, 1, 0, 0, 1,
+ table);
+ assertEquals("id", Types.DOUBLE, 0, 0, null, null, null, true, true, false,
+ table.getColumn(0));
+ assertEquals("value", Types.SMALLINT, 0, 0, "1", null, null, false, false, false,
+ table.getColumn(1));
+
+ Index index = table.getIndex(0);
+
+ assertEquals("The Index", true, 1, index);
+ assertEquals(table.getColumn(1), null, index.getColumn(0));
+
+ assertEquals(
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"TableWithIndex\">\n" +
+ " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"DOUBLE\" autoIncrement=\"false\" />\n" +
+ " <column name=\"value\" primaryKey=\"false\" required=\"false\" type=\"SMALLINT\" default=\"1\" autoIncrement=\"false\" />\n" +
+ " <unique name=\"The Index\">\n" +
+ " <unique-column name=\"value\" />\n" +
+ " </unique>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
+ }
+
+ /**
+ * Tests a database model with an unique index without index columns.
+ */
+ public void testUniqueIndexWithoutColumns() throws Exception
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
+ " <column name='id'\n" +
+ " type='DOUBLE'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " <column name='value'\n" +
+ " type='SMALLINT'\n" +
+ " default='1'/>\n" +
+ " <unique>\n" +
+ " </unique>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a database model with an unique index with an index column that references an undefined column.
+ */
+ public void testUniqueIndexWithUndefinedColumns() throws Exception
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
+ " <column name='id'\n" +
+ " type='DOUBLE'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " <column name='value'\n" +
+ " type='SMALLINT'\n" +
+ " default='1'/>\n" +
+ " <unique>\n" +
+ " <unique-column name='theValue'/>\n" +
+ " </unique>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
+ }
+
+ /**
+ * Tests a database model with an unique index with an index column that has no name.
+ */
+ public void testUniqueIndexWithNoNameColumn() throws Exception
+ {
+ try
+ {
+ readModel(
+ "<database name='test'>\n" +
+ " <table name='TableWithIndex'>\n" +
+ " <column name='id'\n" +
+ " type='DOUBLE'\n" +
+ " primaryKey='true'\n" +
+ " required='true'/>\n" +
+ " <column name='value'\n" +
+ " type='SMALLINT'\n" +
+ " default='1'/>\n" +
+ " <unique>\n" +
+ " <unique-column/>\n" +
+ " </unique>\n" +
+ " </table>\n" +
+ "</database>");
+
+ fail();
+ }
+ catch (ModelException ex)
+ {}
}
/**
* Tests a database model with indices, both uniques and non-uniques.
*/
- public void testIndices2() throws Exception
+ public void testMixedIndexes() throws Exception
{
Database model = readModel(
"<database name='test'>\n" +
- " <table name='TableWidthIndices'>\n" +
+ " <table name='TableWithIndexes'>\n" +
" <column name='id'\n" +
" type='SMALLINT'\n" +
" primaryKey='false'\n" +
@@ -436,97 +1882,44 @@
" </table>\n" +
"</database>");
- assertEquals("test",
- model.getName());
- assertEquals(1,
- model.getTableCount());
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
Table table = model.getTable(0);
- assertEquals("TableWidthIndices",
- table.getName());
- assertNull(table.getDescription());
- assertEquals(2,
- table.getColumnCount());
- assertEquals(0,
- table.getForeignKeyCount());
- assertEquals(2,
- table.getIndexCount());
-
- Column column = table.getColumn(0);
-
- assertEquals("id",
- column.getName());
- assertEquals("SMALLINT",
- column.getType());
- assertEquals(Types.SMALLINT,
- column.getTypeCode());
- assertFalse(column.isPrimaryKey());
- assertTrue(column.isRequired());
- assertTrue(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertNull(column.getDefaultValue());
- assertNull(column.getDescription());
-
- assertEquals(1, table.getAutoIncrementColumns().length);
- assertEquals(column, table.getAutoIncrementColumns()[0]);
-
- column = table.getColumn(1);
-
- assertEquals("when",
- column.getName());
- assertEquals("DATE",
- column.getType());
- assertEquals(Types.DATE,
- column.getTypeCode());
- assertFalse(column.isPrimaryKey());
- assertFalse(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertNull(column.getDescription());
+ assertEquals("TableWithIndexes", null, 2, 0, 1, 0, 2,
+ table);
+ assertEquals("id", Types.SMALLINT, 0, 0, null, null, null, false, true, true,
+ table.getColumn(0));
+ assertEquals("when", Types.DATE, 0, 0, null, null, null, false, false, false,
+ table.getColumn(1));
+ assertEquals(table.getColumn(0), table.getAutoIncrementColumns()[0]);
Index index = table.getIndex(0);
- assertEquals("important column",
- index.getName());
- assertTrue(index.isUnique());
- assertEquals(1,
- index.getColumnCount());
-
- IndexColumn indexColumn = index.getColumn(0);
-
- assertEquals("id",
- indexColumn.getName());
- assertNull(indexColumn.getSize());
+ assertEquals("important column", true, 1, index);
+ assertEquals(table.getColumn(0), null, index.getColumn(0));
index = table.getIndex(1);
- assertNull(index.getName());
- assertFalse(index.isUnique());
- assertEquals(1,
- index.getColumnCount());
-
- indexColumn = index.getColumn(0);
-
- assertEquals("when",
- indexColumn.getName());
- assertNull(indexColumn.getSize());
+ assertEquals(null, false, 1, index);
+ assertEquals(table.getColumn(1), null, index.getColumn(0));
assertEquals(
- "<?xml version=\"1.0\"?>\n<!DOCTYPE database SYSTEM \"" + LocalEntityResolver.DTD_PREFIX + "\">\n" +
- " <database name=\"test\">\n" +
- " <table name=\"TableWidthIndices\">\n" +
- " <column name=\"id\" primaryKey=\"false\" required=\"true\" type=\"SMALLINT\" autoIncrement=\"true\"/>\n" +
- " <column name=\"when\" primaryKey=\"false\" required=\"false\" type=\"DATE\" autoIncrement=\"false\"/>\n" +
- " <unique name=\"important column\">\n" +
- " <unique-column name=\"id\"/>\n" +
- " </unique>\n" +
- " <index>\n" +
- " <index-column name=\"when\"/>\n" +
- " </index>\n" +
- " </table>\n" +
- " </database>\n",
- writeModel(model));
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"TableWithIndexes\">\n" +
+ " <column name=\"id\" primaryKey=\"false\" required=\"true\" type=\"SMALLINT\" autoIncrement=\"true\" />\n" +
+ " <column name=\"when\" primaryKey=\"false\" required=\"false\" type=\"DATE\" autoIncrement=\"false\" />\n" +
+ " <unique name=\"important column\">\n" +
+ " <unique-column name=\"id\" />\n" +
+ " </unique>\n" +
+ " <index>\n" +
+ " <index-column name=\"when\" />\n" +
+ " </index>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
}
/**
@@ -605,356 +1998,116 @@
" </table>\n" +
"</database>");
- assertEquals("test",
- model.getName());
- assertEquals(3,
- model.getTableCount());
+ assertEquals("test", model.getName());
+ assertEquals(3, model.getTableCount());
// table A
Table table = model.getTable(0);
- assertEquals("A",
- table.getName());
- assertEquals("Table A",
- table.getDescription());
- assertEquals(3,
- table.getColumnCount());
- assertEquals(1,
- table.getForeignKeyCount());
- assertEquals(1,
- table.getIndexCount());
-
- Column column = table.getColumn(0);
-
- assertEquals("id",
- column.getName());
- assertEquals("INTEGER",
- column.getType());
- assertEquals(Types.INTEGER,
- column.getTypeCode());
- assertNull(column.getSize());
- assertEquals(0,
- column.getSizeAsInt());
- assertTrue(column.isPrimaryKey());
- assertTrue(column.isRequired());
- assertTrue(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertEquals("The primary key of table A",
- column.getDescription());
- assertEquals(1, table.getAutoIncrementColumns().length);
- assertEquals(column,
- table.getAutoIncrementColumns()[0]);
-
- column = table.getColumn(1);
-
- assertEquals("parentId",
- column.getName());
- assertEquals("INTEGER",
- column.getType());
- assertEquals(Types.INTEGER,
- column.getTypeCode());
- assertNull(column.getSize());
- assertEquals(0,
- column.getSizeAsInt());
- assertFalse(column.isPrimaryKey());
- assertFalse(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertEquals("The field for the foreign key parent",
- column.getDescription());
-
- column = table.getColumn(2);
-
- assertEquals("name",
- column.getName());
- assertEquals("VARCHAR",
- column.getType());
- assertEquals(Types.VARCHAR,
- column.getTypeCode());
- assertEquals("32",
- column.getSize());
- assertEquals(32,
- column.getSizeAsInt());
- assertFalse(column.isPrimaryKey());
- assertTrue(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertEquals("The name",
- column.getDescription());
+ assertEquals("A", "Table A", 3, 1, 1, 1, 1,
+ table);
+ assertEquals("id", Types.INTEGER, 0, 0, null, "The primary key of table A", null, true, true, true,
+ table.getColumn(0));
+ assertEquals("parentId", Types.INTEGER, 0, 0, null, "The field for the foreign key parent", null, false, false, false,
+ table.getColumn(1));
+ assertEquals("name", Types.VARCHAR, 32, 0, null, "The name", null, false, true, false,
+ table.getColumn(2));
+ assertEquals(table.getColumn(0), table.getAutoIncrementColumns()[0]);
ForeignKey fk = table.getForeignKey(0);
- assertEquals("parent",
- fk.getName());
- assertEquals(table,
- fk.getForeignTable());
- assertEquals("A",
- fk.getForeignTableName());
- assertEquals(1,
- fk.getReferenceCount());
-
- Reference ref = fk.getFirstReference();
-
- assertEquals(table.getColumn(1),
- ref.getLocalColumn());
- assertEquals("parentId",
- ref.getLocalColumnName());
- assertEquals(table.getColumn(0),
- ref.getForeignColumn());
- assertEquals("id",
- ref.getForeignColumnName());
+ assertEquals("parent", CascadeActionEnum.NONE, CascadeActionEnum.NONE, table, 1, fk);
+ assertEquals(table.getColumn(1), table.getColumn(0), fk.getFirstReference());
Index index = table.getIndex(0);
- assertNull(index.getName());
- assertTrue(index.isUnique());
- assertEquals(1,
- index.getColumnCount());
-
- IndexColumn indexColumn = index.getColumn(0);
-
- assertEquals("name",
- indexColumn.getName());
- assertNull(indexColumn.getSize());
+ assertEquals(null, true, 1, index);
+ assertEquals(table.getColumn(2), null, index.getColumn(0));
// table B
table = model.getTable(1);
- assertEquals("B",
- table.getName());
- assertEquals("Table B",
- table.getDescription());
- assertEquals(0, table.getAutoIncrementColumns().length);
- assertEquals(3,
- table.getColumnCount());
- assertEquals(2,
- table.getForeignKeyCount());
- assertEquals(1,
- table.getIndexCount());
-
- column = table.getColumn(0);
-
- assertEquals("id",
- column.getName());
- assertEquals("TIMESTAMP",
- column.getType());
- assertEquals(Types.TIMESTAMP,
- column.getTypeCode());
- assertNull(column.getSize());
- assertEquals(0,
- column.getSizeAsInt());
- assertTrue(column.isPrimaryKey());
- assertTrue(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertEquals("The primary key of table B",
- column.getDescription());
-
- column = table.getColumn(1);
-
- assertEquals("aid",
- column.getName());
- assertEquals("INTEGER",
- column.getType());
- assertEquals(Types.INTEGER,
- column.getTypeCode());
- assertNull(column.getSize());
- assertEquals(0,
- column.getSizeAsInt());
- assertFalse(column.isPrimaryKey());
- assertFalse(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertEquals("The field for the foreign key towards A",
- column.getDescription());
-
- column = table.getColumn(2);
-
- assertEquals("cid",
- column.getName());
- assertEquals("CHAR",
- column.getType());
- assertEquals(Types.CHAR,
- column.getTypeCode());
- assertEquals("32",
- column.getSize());
- assertEquals(32,
- column.getSizeAsInt());
- assertFalse(column.isPrimaryKey());
- assertFalse(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertEquals("The field for the foreign key towards C",
- column.getDescription());
+ assertEquals("B", "Table B", 3, 1, 0, 2, 1,
+ table);
+ assertEquals("id", Types.TIMESTAMP, 0, 0, null, "The primary key of table B", null, true, true, false,
+ table.getColumn(0));
+ assertEquals("aid", Types.INTEGER, 0, 0, null, "The field for the foreign key towards A", null, false, false, false,
+ table.getColumn(1));
+ assertEquals("cid", Types.CHAR, 32, 0, null, "The field for the foreign key towards C", null, false, false, false,
+ table.getColumn(2));
fk = table.getForeignKey(0);
- assertNull(fk.getName());
- assertEquals(model.getTable(0),
- fk.getForeignTable());
- assertEquals("A",
- fk.getForeignTableName());
- assertEquals(1,
- fk.getReferenceCount());
-
- ref = fk.getFirstReference();
-
- assertEquals(table.getColumn(1),
- ref.getLocalColumn());
- assertEquals("aid",
- ref.getLocalColumnName());
- assertEquals(model.getTable(0).getColumn(0),
- ref.getForeignColumn());
- assertEquals("id",
- ref.getForeignColumnName());
+ assertEquals(null, CascadeActionEnum.NONE, CascadeActionEnum.NONE, model.getTable(0), 1, fk);
+ assertEquals(table.getColumn(1), model.getTable(0).getColumn(0), fk.getFirstReference());
fk = table.getForeignKey(1);
- assertNull(fk.getName());
- assertEquals(model.getTable(2),
- fk.getForeignTable());
- assertEquals("C",
- fk.getForeignTableName());
- assertEquals(1,
- fk.getReferenceCount());
-
- ref = fk.getFirstReference();
-
- assertEquals(table.getColumn(2),
- ref.getLocalColumn());
- assertEquals("cid",
- ref.getLocalColumnName());
- assertEquals(model.getTable(2).getColumn(0),
- ref.getForeignColumn());
- assertEquals("id",
- ref.getForeignColumnName());
+ assertEquals(null, CascadeActionEnum.NONE, CascadeActionEnum.NONE, model.getTable(2), 1, fk);
+ assertEquals(table.getColumn(2), model.getTable(2).getColumn(0), fk.getFirstReference());
index = table.getIndex(0);
- assertNull(index.getName());
- assertFalse(index.isUnique());
- assertEquals(2,
- index.getColumnCount());
-
- indexColumn = index.getColumn(0);
-
- assertEquals("aid",
- indexColumn.getName());
- assertNull(indexColumn.getSize());
-
- indexColumn = index.getColumn(1);
-
- assertEquals("cid",
- indexColumn.getName());
- assertNull(indexColumn.getSize());
+ assertEquals(null, false, 2, index);
+ assertEquals(table.getColumn(1), null, index.getColumn(0));
+ assertEquals(table.getColumn(2), null, index.getColumn(1));
// table C
table = model.getTable(2);
- assertEquals("C",
- table.getName());
- assertEquals("Table C",
- table.getDescription());
- assertEquals(0, table.getAutoIncrementColumns().length);
- assertEquals(2,
- table.getColumnCount());
- assertEquals(0,
- table.getForeignKeyCount());
- assertEquals(1,
- table.getIndexCount());
-
- column = table.getColumn(0);
-
- assertEquals("id",
- column.getName());
- assertEquals("CHAR",
- column.getType());
- assertEquals(Types.CHAR,
- column.getTypeCode());
- assertEquals("32",
- column.getSize());
- assertEquals(32,
- column.getSizeAsInt());
- assertTrue(column.isPrimaryKey());
- assertTrue(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertEquals("The primary key of table C",
- column.getDescription());
-
- column = table.getColumn(1);
-
- assertEquals("text",
- column.getName());
- assertEquals("LONGVARCHAR",
- column.getType());
- assertEquals(Types.LONGVARCHAR,
- column.getTypeCode());
- assertNull(column.getSize());
- assertEquals(0,
- column.getSizeAsInt());
- assertFalse(column.isPrimaryKey());
- assertFalse(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertEquals("The text",
- column.getDescription());
+ assertEquals("C", "Table C", 2, 1, 0, 0, 1,
+ table);
+ assertEquals("id", Types.CHAR, 32, 0, null, "The primary key of table C", null, true, true, false,
+ table.getColumn(0));
+ assertEquals("text", Types.LONGVARCHAR, 0, 0, null, "The text", null, false, false, false,
+ table.getColumn(1));
index = table.getIndex(0);
- assertEquals("byText",
- index.getName());
- assertFalse(index.isUnique());
- assertEquals(1,
- index.getColumnCount());
-
- indexColumn = index.getColumn(0);
-
- assertEquals("text",
- indexColumn.getName());
- assertNull(indexColumn.getSize());
+ assertEquals("byText", false, 1, index);
+ assertEquals(table.getColumn(1), null, index.getColumn(0));
assertEquals(
- "<?xml version=\"1.0\"?>\n<!DOCTYPE database SYSTEM \"" + LocalEntityResolver.DTD_PREFIX + "\">\n" +
- " <database name=\"test\">\n" +
- " <table name=\"A\" description=\"Table A\">\n" +
- " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"INTEGER\" autoIncrement=\"true\" description=\"The primary key of table A\"/>\n" +
- " <column name=\"parentId\" primaryKey=\"false\" required=\"false\" type=\"INTEGER\" autoIncrement=\"false\" description=\"The field for the foreign key parent\"/>\n" +
- " <column name=\"name\" primaryKey=\"false\" required=\"true\" type=\"VARCHAR\" size=\"32\" autoIncrement=\"false\" description=\"The name\"/>\n" +
- " <foreign-key foreignTable=\"A\" name=\"parent\">\n" +
- " <reference local=\"parentId\" foreign=\"id\"/>\n" +
- " </foreign-key>\n" +
- " <unique>\n" +
- " <unique-column name=\"name\"/>\n" +
- " </unique>\n" +
- " </table>\n" +
- " <table name=\"B\" description=\"Table B\">\n" +
- " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"TIMESTAMP\" autoIncrement=\"false\" description=\"The primary key of table B\"/>\n" +
- " <column name=\"aid\" primaryKey=\"false\" required=\"false\" type=\"INTEGER\" autoIncrement=\"false\" description=\"The field for the foreign key towards A\"/>\n" +
- " <column name=\"cid\" primaryKey=\"false\" required=\"false\" type=\"CHAR\" size=\"32\" autoIncrement=\"false\" description=\"The field for the foreign key towards C\"/>\n" +
- " <foreign-key foreignTable=\"A\">\n" +
- " <reference local=\"aid\" foreign=\"id\"/>\n" +
- " </foreign-key>\n" +
- " <foreign-key foreignTable=\"C\">\n" +
- " <reference local=\"cid\" foreign=\"id\"/>\n" +
- " </foreign-key>\n" +
- " <index>\n" +
- " <index-column name=\"aid\"/>\n" +
- " <index-column name=\"cid\"/>\n" +
- " </index>\n" +
- " </table>\n" +
- " <table name=\"C\" description=\"Table C\">\n" +
- " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"CHAR\" size=\"32\" autoIncrement=\"false\" description=\"The primary key of table C\"/>\n" +
- " <column name=\"text\" primaryKey=\"false\" required=\"false\" type=\"LONGVARCHAR\" autoIncrement=\"false\" description=\"The text\"/>\n" +
- " <index name=\"byText\">\n" +
- " <index-column name=\"text\"/>\n" +
- " </index>\n" +
- " </table>\n" +
- " </database>\n",
- writeModel(model));
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"A\" description=\"Table A\">\n" +
+ " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"INTEGER\" autoIncrement=\"true\" description=\"The primary key of table A\" />\n" +
+ " <column name=\"parentId\" primaryKey=\"false\" required=\"false\" type=\"INTEGER\" autoIncrement=\"false\" description=\"The field for the foreign key parent\" />\n" +
+ " <column name=\"name\" primaryKey=\"false\" required=\"true\" type=\"VARCHAR\" size=\"32\" autoIncrement=\"false\" description=\"The name\" />\n" +
+ " <foreign-key foreignTable=\"A\" name=\"parent\">\n" +
+ " <reference local=\"parentId\" foreign=\"id\" />\n" +
+ " </foreign-key>\n" +
+ " <unique>\n" +
+ " <unique-column name=\"name\" />\n" +
+ " </unique>\n" +
+ " </table>\n" +
+ " <table name=\"B\" description=\"Table B\">\n" +
+ " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"TIMESTAMP\" autoIncrement=\"false\" description=\"The primary key of table B\" />\n" +
+ " <column name=\"aid\" primaryKey=\"false\" required=\"false\" type=\"INTEGER\" autoIncrement=\"false\" description=\"The field for the foreign key towards A\" />\n" +
+ " <column name=\"cid\" primaryKey=\"false\" required=\"false\" type=\"CHAR\" size=\"32\" autoIncrement=\"false\" description=\"The field for the foreign key towards C\" />\n" +
+ " <foreign-key foreignTable=\"A\">\n" +
+ " <reference local=\"aid\" foreign=\"id\" />\n" +
+ " </foreign-key>\n" +
+ " <foreign-key foreignTable=\"C\">\n" +
+ " <reference local=\"cid\" foreign=\"id\" />\n" +
+ " </foreign-key>\n" +
+ " <index>\n" +
+ " <index-column name=\"aid\" />\n" +
+ " <index-column name=\"cid\" />\n" +
+ " </index>\n" +
+ " </table>\n" +
+ " <table name=\"C\" description=\"Table C\">\n" +
+ " <column name=\"id\" primaryKey=\"true\" required=\"true\" type=\"CHAR\" size=\"32\" autoIncrement=\"false\" description=\"The primary key of table C\" />\n" +
+ " <column name=\"text\" primaryKey=\"false\" required=\"false\" type=\"LONGVARCHAR\" autoIncrement=\"false\" description=\"The text\" />\n" +
+ " <index name=\"byText\">\n" +
+ " <index-column name=\"text\" />\n" +
+ " </index>\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
}
/**
@@ -985,52 +2138,6 @@
}
/**
- * Tests that an exception is generated when the database element has no name attribute.
- */
- public void testDatabaseWithoutName()
- {
- try
- {
- readModel(
- "<database>\n" +
- " <table name='TestTable'>\n" +
- " <column name='id'\n" +
- " type='INTEGER'\n" +
- " primaryKey='true'\n" +
- " required='true'/>\n" +
- " </table>\n" +
- "</database>");
-
- fail();
- }
- catch (ModelException ex)
- {}
- }
-
- /**
- * Tests that an exception is generated when the table element has no name attribute.
- */
- public void testTableWithoutName()
- {
- try
- {
- readModel(
- "<database name='test'>\n" +
- " <table>\n" +
- " <column name='id'\n" +
- " type='INTEGER'\n" +
- " primaryKey='true'\n" +
- " required='true'/>\n" +
- " </table>\n" +
- "</database>");
-
- fail();
- }
- catch (ModelException ex)
- {}
- }
-
- /**
* Tests that an exception is generated when two table elements have the same value in their name attributes.
*/
public void testTwoTablesWithTheSameName()
@@ -1060,28 +2167,6 @@
}
/**
- * Tests that an exception is generated when the column element has no name attribute.
- */
- public void testColumnWithoutName()
- {
- try
- {
- readModel(
- "<database name='test'>\n" +
- " <table name='TestTable'>\n" +
- " <column type='INTEGER'\n" +
- " primaryKey='true'\n" +
- " required='true'/>\n" +
- " </table>\n" +
- "</database>");
-
- fail();
- }
- catch (ModelException ex)
- {}
- }
-
- /**
* Tests that an exception is generated when two column elements within the same table
* element have the same value in their name attributes.
*/
@@ -1108,28 +2193,6 @@
}
/**
- * Tests that an exception is generated when the column element has no type attribute.
- */
- public void testColumnWithoutType()
- {
- try
- {
- readModel(
- "<database name='test'>\n" +
- " <table name='TestTable'>\n" +
- " <column name='id'\n" +
- " primaryKey='true'\n" +
- " required='true'/>\n" +
- " </table>\n" +
- "</database>");
-
- fail();
- }
- catch (ModelException ex)
- {}
- }
-
- /**
* Tests that an exception is generated when the a unique index references an undefined column.
*/
public void testUndefinedUniqueColumn()
@@ -1272,7 +2335,6 @@
" <index name='NotATable'/>\n" +
"</database>");
- _log.debug("Table : " + Arrays.asList(database.getTables()));
assertEquals(0, database.getTableCount());
}
@@ -1287,70 +2349,30 @@
" <column name='intField'\n" +
" type='BOOLEANINT'/>\n" +
" <column name='charField'\n" +
- " type='BOOLEANCHAR'/>\n" +
+ " type='BOOLEANCHAR' />\n" +
" </table>\n" +
"</database>");
- assertEquals("test",
- model.getName());
- assertEquals(1,
- model.getTableCount());
+ assertEquals("test", model.getName());
+ assertEquals(1, model.getTableCount());
Table table = model.getTable(0);
- assertEquals("SomeTable",
- table.getName());
- assertNull(table.getDescription());
- assertEquals(0, table.getAutoIncrementColumns().length);
- assertEquals(2,
- table.getColumnCount());
- assertEquals(0,
- table.getForeignKeyCount());
- assertEquals(0,
- table.getIndexCount());
-
- Column column = table.getColumn(0);
-
- assertEquals("intField",
- column.getName());
- assertEquals("TINYINT",
- column.getType());
- assertEquals(Types.TINYINT,
- column.getTypeCode());
- assertFalse(column.isPrimaryKey());
- assertFalse(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertNull(column.getDescription());
-
- column = table.getColumn(1);
-
- assertEquals("charField",
- column.getName());
- assertEquals("CHAR",
- column.getType());
- assertEquals(Types.CHAR,
- column.getTypeCode());
- assertFalse(column.isPrimaryKey());
- assertFalse(column.isRequired());
- assertFalse(column.isAutoIncrement());
- assertNull(column.getDefaultValue());
- assertNull(column.getDescription());
+ assertEquals("SomeTable", null, 2, 0, 0, 0, 0,
+ table);
+ assertEquals("intField", Types.TINYINT, 0, 0, null, null, null, false, false, false,
+ table.getColumn(0));
+ assertEquals("charField", Types.CHAR, 0, 0, null, null, null, false, false, false,
+ table.getColumn(1));
assertEquals(
- "<?xml version=\"1.0\"?>\n<!DOCTYPE database SYSTEM \"" + LocalEntityResolver.DTD_PREFIX + "\">\n" +
- " <database name=\"test\">\n" +
- " <table name=\"SomeTable\">\n" +
- " <column name=\"intField\" primaryKey=\"false\" required=\"false\" type=\"TINYINT\" autoIncrement=\"false\"/>\n" +
- " <column name=\"charField\" primaryKey=\"false\" required=\"false\" type=\"CHAR\" autoIncrement=\"false\"/>\n" +
- " </table>\n" +
- " </database>\n",
- writeModel(model));
+ "<?xml version='1.0' encoding='UTF-8'?>\n" +
+ "<database name=\"test\">\n" +
+ " <table name=\"SomeTable\">\n" +
+ " <column name=\"intField\" primaryKey=\"false\" required=\"false\" type=\"TINYINT\" autoIncrement=\"false\" />\n" +
+ " <column name=\"charField\" primaryKey=\"false\" required=\"false\" type=\"CHAR\" autoIncrement=\"false\" />\n" +
+ " </table>\n" +
+ "</database>\n",
+ model);
}
-
- // TODO: Tests that include:
- // * foreign key references undefined table
- // * foreign key references undefined local column
- // * foreign key references undefined foreign column
- // * two foreign keys with the same name
}