Author: tomdz
Date: Wed Sep  5 22:12:08 2007
New Revision: 573150

URL: http://svn.apache.org/viewvc?rev=573150&view=rev
Log:
Added reading and writing of onUpdate and onDelete attributes from/to XML

Modified:
    db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DatabaseIO.java
    db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDatabaseIO.java

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DatabaseIO.java
URL: 
http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DatabaseIO.java?rev=573150&r1=573149&r2=573150&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DatabaseIO.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DatabaseIO.java Wed Sep  
5 22:12:08 2007
@@ -35,7 +35,7 @@
 import javax.xml.stream.XMLStreamReader;
 
 import org.apache.commons.lang.StringUtils;
-import org.apache.ddlutils.DdlUtilsException;
+import org.apache.ddlutils.model.CascadeActionEnum;
 import org.apache.ddlutils.model.Column;
 import org.apache.ddlutils.model.Database;
 import org.apache.ddlutils.model.ForeignKey;
@@ -98,6 +98,10 @@
     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 onDelete attribute. */
+    public static final QName QNAME_ATTRIBUTE_ON_DELETE         = new 
QName(DDLUTILS_NAMESPACE, "onDelete");
+    /** Qualified name of the onUpdate attribute. */
+    public static final QName QNAME_ATTRIBUTE_ON_UPDATE         = new 
QName(DDLUTILS_NAMESPACE, "onUpdate");
     /** 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. */
@@ -160,7 +164,7 @@
      * @param filename The model file name
      * @return The database model
      */
-    public Database read(String filename) throws DdlUtilsException
+    public Database read(String filename) throws DdlUtilsXMLException
     {
         try
         {
@@ -168,7 +172,7 @@
         }
         catch (IOException ex)
         {
-            throw new DdlUtilsException(ex);
+            throw new DdlUtilsXMLException(ex);
         }
     }
 
@@ -178,7 +182,7 @@
      * @param file The model file
      * @return The database model
      */
-    public Database read(File file) throws DdlUtilsException
+    public Database read(File file) throws DdlUtilsXMLException
     {
         try
         {
@@ -186,7 +190,7 @@
         }
         catch (IOException ex)
         {
-            throw new DdlUtilsException(ex);
+            throw new DdlUtilsXMLException(ex);
         }
     }
 
@@ -196,7 +200,7 @@
      * @param reader The reader that returns the model XML
      * @return The database model
      */
-    public Database read(Reader reader) throws DdlUtilsException
+    public Database read(Reader reader) throws DdlUtilsXMLException
     {
         try
         {
@@ -204,7 +208,7 @@
         }
         catch (XMLStreamException ex)
         {
-            throw new DdlUtilsException(ex);
+            throw new DdlUtilsXMLException(ex);
         }
     }
 
@@ -214,7 +218,7 @@
      * @param source The input source
      * @return The database model
      */
-    public Database read(InputSource source) throws DdlUtilsException
+    public Database read(InputSource source) throws DdlUtilsXMLException
     {
         try
         {
@@ -222,7 +226,7 @@
         }
         catch (XMLStreamException ex)
         {
-            throw new DdlUtilsException(ex);
+            throw new DdlUtilsXMLException(ex);
         }
     }
 
@@ -246,7 +250,7 @@
      * @param xmlReader The reader
      * @return The database model
      */
-    private Database read(XMLStreamReader xmlReader) throws DdlUtilsException
+    private Database read(XMLStreamReader xmlReader) throws 
DdlUtilsXMLException
     {
         Database model = null;
 
@@ -266,11 +270,11 @@
         }
         catch (IOException ex)
         {
-            throw new DdlUtilsException(ex);
+            throw new DdlUtilsXMLException(ex);
         }
         catch (XMLStreamException ex)
         {
-            throw new DdlUtilsException(ex);
+            throw new DdlUtilsXMLException(ex);
         }
         if (model != null)
         {
@@ -483,6 +487,14 @@
             {
                 foreignKey.setName(xmlReader.getAttributeValue(idx));
             }
+            else if (isSameAs(attrQName, QNAME_ATTRIBUTE_ON_UPDATE))
+            {
+                
foreignKey.setOnUpdate(getAttributeValueAsCascadeEnum(xmlReader, idx));
+            }
+            else if (isSameAs(attrQName, QNAME_ATTRIBUTE_ON_DELETE))
+            {
+                
foreignKey.setOnDelete(getAttributeValueAsCascadeEnum(xmlReader, idx));
+            }
         }
         readReferenceElements(xmlReader, foreignKey);
         consumeRestOfElement(xmlReader);
@@ -707,7 +719,7 @@
      * @param attributeIdx The index of the attribute
      * @return The attribute's value as a boolean
      */
-    private boolean getAttributeValueAsBoolean(XMLStreamReader xmlReader, int 
attributeIdx) throws DdlUtilsException
+    private boolean getAttributeValueAsBoolean(XMLStreamReader xmlReader, int 
attributeIdx) throws DdlUtilsXMLException
     {
         String value = xmlReader.getAttributeValue(attributeIdx);
 
@@ -721,7 +733,30 @@
         }
         else
         {
-            throw new DdlUtilsException("Illegal boolean value '" + value +"' 
for attribute " + xmlReader.getAttributeLocalName(attributeIdx));
+            throw new DdlUtilsXMLException("Illegal boolean value '" + value 
+"' for attribute " + xmlReader.getAttributeLocalName(attributeIdx));
+        }
+    }
+
+    /**
+     * 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 CascadeActionEnum getAttributeValueAsCascadeEnum(XMLStreamReader 
xmlReader, int attributeIdx) throws DdlUtilsXMLException
+    {
+        String            value     = 
xmlReader.getAttributeValue(attributeIdx);
+        CascadeActionEnum enumValue = value == null ? null : 
CascadeActionEnum.getEnum(value.toLowerCase());
+
+        if (enumValue == null)
+        {
+            throw new DdlUtilsXMLException("Illegal boolean value '" + value 
+"' for attribute " + xmlReader.getAttributeLocalName(attributeIdx));
+        }
+        else
+        {
+            return enumValue;
         }
     }
 
@@ -795,7 +830,7 @@
         }
         catch (Exception ex)
         {
-            throw new DdlUtilsException(ex);
+            throw new DdlUtilsXMLException(ex);
         }
     }
 
@@ -917,6 +952,14 @@
         writeElementStart(xmlWriter, QNAME_ELEMENT_FOREIGN_KEY);
         writeAttribute(xmlWriter, QNAME_ATTRIBUTE_FOREIGN_TABLE, 
foreignKey.getForeignTableName());
         writeAttribute(xmlWriter, QNAME_ATTRIBUTE_NAME,          
foreignKey.getName());
+        if (foreignKey.getOnUpdate() != CascadeActionEnum.NONE)
+        {
+            writeAttribute(xmlWriter, QNAME_ATTRIBUTE_ON_UPDATE, 
foreignKey.getOnUpdate().getName());
+        }
+        if (foreignKey.getOnDelete() != CascadeActionEnum.NONE)
+        {
+            writeAttribute(xmlWriter, QNAME_ATTRIBUTE_ON_DELETE, 
foreignKey.getOnDelete().getName());
+        }
         if (foreignKey.getReferenceCount() > 0)
         {
             xmlWriter.printlnIfPrettyPrinting();

Modified: db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDatabaseIO.java
URL: 
http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDatabaseIO.java?rev=573150&r1=573149&r2=573150&view=diff
==============================================================================
--- db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDatabaseIO.java 
(original)
+++ db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDatabaseIO.java Wed 
Sep  5 22:12:08 2007
@@ -22,6 +22,7 @@
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.sql.Types;
+import java.util.Iterator;
 
 import junit.framework.TestCase;
 
@@ -1034,6 +1035,344 @@
             "  </table>\n" +
             "</database>\n",
             model);
+    }
+
+    /**
+     * Tests a database model containing foreignkeys with onUpdate values.
+     */
+    public void testForeignkeysWithOnUpdate() throws Exception
+    {
+        StringBuffer modelXml = new StringBuffer();
+
+        modelXml.append("<database name='test'>\n");
+        modelXml.append("  <table name='SomeTable'\n");
+        modelXml.append("         description='Some table'>\n");
+        modelXml.append("    <column name='ID'\n");
+        modelXml.append("            type='VARCHAR'\n");
+        modelXml.append("            size='16'\n");
+        modelXml.append("            primaryKey='true'\n");
+        modelXml.append("            required='true'\n");
+        modelXml.append("            description='The primary key'/>\n");
+        modelXml.append("  </table>\n");
+        modelXml.append("  <table name='AnotherTable'\n");
+        modelXml.append("         description='And another table'>\n");
+        modelXml.append("    <column name='Some_ID'\n");
+        modelXml.append("            type='VARCHAR'\n");
+        modelXml.append("            size='16'\n");
+        modelXml.append("            description='The foreign key'/>\n");
+        for (Iterator it = CascadeActionEnum.iterator(); it.hasNext();)
+        {
+            CascadeActionEnum enumValue = (CascadeActionEnum)it.next();
+
+            modelXml.append("    <foreign-key name='foreignkey ");
+            modelXml.append(enumValue.getName());
+            modelXml.append("' foreignTable='SomeTable' onUpdate='");
+            modelXml.append(enumValue.getName());
+            modelXml.append("'>\n");
+            modelXml.append("       <reference local='Some_ID' 
foreign='ID'/>\n");
+            modelXml.append("    </foreign-key>\n");
+        }
+        modelXml.append("  </table>\n");
+        modelXml.append("</database>");
+
+        Database model = readModel(modelXml.toString());
+
+        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, 
CascadeActionEnum.getEnumList().size(), 0,
+                     anotherTable);
+        assertEquals("Some_ID", Types.VARCHAR, 16, 0, null, "The foreign key", 
null, false, false, false,
+                     anotherTable.getColumn(0));
+
+        int idx = 0;
+        
+        for (Iterator it = CascadeActionEnum.iterator(); it.hasNext(); idx++)
+        {
+            CascadeActionEnum enumValue = (CascadeActionEnum)it.next();
+            ForeignKey        fk        = anotherTable.getForeignKey(idx);
+
+            assertEquals("foreignkey " + enumValue.getName(), enumValue, 
CascadeActionEnum.NONE, someTable, 1, fk);
+            assertEquals(anotherTable.getColumn(0), someTable.getColumn(0), 
fk.getReference(0));
+        }
+
+        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");
+        modelXml.append("    <column name=\"ID\" primaryKey=\"true\" 
required=\"true\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" 
description=\"The primary key\" />\n");
+        modelXml.append("  </table>\n");
+        modelXml.append("  <table name=\"AnotherTable\" description=\"And 
another table\">\n");
+        modelXml.append("    <column name=\"Some_ID\" primaryKey=\"false\" 
required=\"false\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" 
description=\"The foreign key\" />\n");
+        for (Iterator it = CascadeActionEnum.iterator(); it.hasNext(); idx++)
+        {
+            CascadeActionEnum enumValue = (CascadeActionEnum)it.next();
+
+            modelXml.append("    <foreign-key foreignTable=\"SomeTable\" 
name=\"foreignkey ");
+            modelXml.append(enumValue.getName());
+            if (enumValue != CascadeActionEnum.NONE)
+            {
+                modelXml.append("\" onUpdate=\"");
+                modelXml.append(enumValue.getName());
+            }
+            modelXml.append("\">\n");
+            modelXml.append("      <reference local=\"Some_ID\" foreign=\"ID\" 
/>\n");
+            modelXml.append("    </foreign-key>\n");
+        }
+        modelXml.append("  </table>\n");
+        modelXml.append("</database>\n");
+
+        assertEquals(modelXml.toString(), model);
+    }
+
+    /**
+     * Tests a database model containing foreignkeys with onDelete values.
+     */
+    public void testForeignkeysWithOnDelete() throws Exception
+    {
+        StringBuffer modelXml = new StringBuffer();
+
+        modelXml.append("<database name='test'>\n");
+        modelXml.append("  <table name='SomeTable'\n");
+        modelXml.append("         description='Some table'>\n");
+        modelXml.append("    <column name='ID'\n");
+        modelXml.append("            type='VARCHAR'\n");
+        modelXml.append("            size='16'\n");
+        modelXml.append("            primaryKey='true'\n");
+        modelXml.append("            required='true'\n");
+        modelXml.append("            description='The primary key'/>\n");
+        modelXml.append("  </table>\n");
+        modelXml.append("  <table name='AnotherTable'\n");
+        modelXml.append("         description='And another table'>\n");
+        modelXml.append("    <column name='Some_ID'\n");
+        modelXml.append("            type='VARCHAR'\n");
+        modelXml.append("            size='16'\n");
+        modelXml.append("            description='The foreign key'/>\n");
+        for (Iterator it = CascadeActionEnum.iterator(); it.hasNext();)
+        {
+            CascadeActionEnum enumValue = (CascadeActionEnum)it.next();
+
+            modelXml.append("    <foreign-key name='foreignkey ");
+            modelXml.append(enumValue.getName());
+            modelXml.append("' foreignTable='SomeTable' onDelete='");
+            modelXml.append(enumValue.getName());
+            modelXml.append("'>\n");
+            modelXml.append("       <reference local='Some_ID' 
foreign='ID'/>\n");
+            modelXml.append("    </foreign-key>\n");
+        }
+        modelXml.append("  </table>\n");
+        modelXml.append("</database>");
+
+        Database model = readModel(modelXml.toString());
+
+        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, 
CascadeActionEnum.getEnumList().size(), 0,
+                     anotherTable);
+        assertEquals("Some_ID", Types.VARCHAR, 16, 0, null, "The foreign key", 
null, false, false, false,
+                     anotherTable.getColumn(0));
+
+        int idx = 0;
+        
+        for (Iterator it = CascadeActionEnum.iterator(); it.hasNext(); idx++)
+        {
+            CascadeActionEnum enumValue = (CascadeActionEnum)it.next();
+            ForeignKey        fk        = anotherTable.getForeignKey(idx);
+
+            assertEquals("foreignkey " + enumValue.getName(), 
CascadeActionEnum.NONE, enumValue, someTable, 1, fk);
+            assertEquals(anotherTable.getColumn(0), someTable.getColumn(0), 
fk.getReference(0));
+        }
+
+        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");
+        modelXml.append("    <column name=\"ID\" primaryKey=\"true\" 
required=\"true\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" 
description=\"The primary key\" />\n");
+        modelXml.append("  </table>\n");
+        modelXml.append("  <table name=\"AnotherTable\" description=\"And 
another table\">\n");
+        modelXml.append("    <column name=\"Some_ID\" primaryKey=\"false\" 
required=\"false\" type=\"VARCHAR\" size=\"16\" autoIncrement=\"false\" 
description=\"The foreign key\" />\n");
+        for (Iterator it = CascadeActionEnum.iterator(); it.hasNext(); idx++)
+        {
+            CascadeActionEnum enumValue = (CascadeActionEnum)it.next();
+
+            modelXml.append("    <foreign-key foreignTable=\"SomeTable\" 
name=\"foreignkey ");
+            modelXml.append(enumValue.getName());
+            if (enumValue != CascadeActionEnum.NONE)
+            {
+                modelXml.append("\" onDelete=\"");
+                modelXml.append(enumValue.getName());
+            }
+            modelXml.append("\">\n");
+            modelXml.append("      <reference local=\"Some_ID\" foreign=\"ID\" 
/>\n");
+            modelXml.append("    </foreign-key>\n");
+        }
+        modelXml.append("  </table>\n");
+        modelXml.append("</database>\n");
+
+        assertEquals(modelXml.toString(), model);
+    }
+
+    /**
+     * Tests a foreign key with an illegal onUpdate value.
+     */
+    public void testForeignKeyWithIllegalOnUpdateValue()
+    {
+        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' 
onUpdate='illegal'>\n" +
+                "       <reference local='Some_ID' foreign='ID'/>\n" +
+                "    </foreign-key>\n" +
+                "  </table>\n" +
+                "</database>");
+
+            fail();
+        }
+        catch (DdlUtilsXMLException ex)
+        {}
+    }
+
+    /**
+     * Tests a foreign key with an empty onUpdate value.
+     */
+    public void testForeignKeyWithEmptyOnUpdateValue()
+    {
+        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' onUpdate=''>\n" +
+                "       <reference local='Some_ID' foreign='ID'/>\n" +
+                "    </foreign-key>\n" +
+                "  </table>\n" +
+                "</database>");
+
+            fail();
+        }
+        catch (DdlUtilsXMLException ex)
+        {}
+    }
+
+    /**
+     * Tests a foreign key with an illegal onDelete value.
+     */
+    public void testForeignKeyWithIllegalOnDeleteValue()
+    {
+        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' 
onDelete='illegal'>\n" +
+                "       <reference local='Some_ID' foreign='ID'/>\n" +
+                "    </foreign-key>\n" +
+                "  </table>\n" +
+                "</database>");
+
+            fail();
+        }
+        catch (DdlUtilsXMLException ex)
+        {}
+    }
+
+    /**
+     * Tests a foreign key with an empty onDelete value.
+     */
+    public void testForeignKeyWithEmptyOnDeleteValue()
+    {
+        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' onDelete=''>\n" +
+                "       <reference local='Some_ID' foreign='ID'/>\n" +
+                "    </foreign-key>\n" +
+                "  </table>\n" +
+                "</database>");
+
+            fail();
+        }
+        catch (DdlUtilsXMLException ex)
+        {}
     }
 
     /**


Reply via email to