diff --git a/source/java/org/alfresco/util/schemacomp/SchemaCompTestSuite.java b/source/java/org/alfresco/util/schemacomp/SchemaCompTestSuite.java
index 570c454001..33d505d5d2 100644
--- a/source/java/org/alfresco/util/schemacomp/SchemaCompTestSuite.java
+++ b/source/java/org/alfresco/util/schemacomp/SchemaCompTestSuite.java
@@ -34,7 +34,8 @@ import org.junit.runners.Suite;
DefaultComparisonUtilsTest.class,
SchemaComparatorTest.class,
ValidatingVisitorTest.class,
- SchemaToXMLTest.class
+ SchemaToXMLTest.class,
+ XMLToSchemaTest.class
})
public class SchemaCompTestSuite
{
diff --git a/source/java/org/alfresco/util/schemacomp/SchemaCompTestingUtils.java b/source/java/org/alfresco/util/schemacomp/SchemaCompTestingUtils.java
index 555df4751d..9cf7c50935 100644
--- a/source/java/org/alfresco/util/schemacomp/SchemaCompTestingUtils.java
+++ b/source/java/org/alfresco/util/schemacomp/SchemaCompTestingUtils.java
@@ -29,6 +29,7 @@ import org.alfresco.util.schemacomp.model.Column;
import org.alfresco.util.schemacomp.model.ForeignKey;
import org.alfresco.util.schemacomp.model.Index;
import org.alfresco.util.schemacomp.model.PrimaryKey;
+import org.alfresco.util.schemacomp.model.Sequence;
import org.alfresco.util.schemacomp.model.Table;
import org.apache.commons.lang.ArrayUtils;
@@ -112,4 +113,9 @@ public class SchemaCompTestingUtils
}
return Arrays.asList(indexes);
}
+
+ public static Sequence sequence(String name)
+ {
+ return new Sequence(name);
+ }
}
diff --git a/source/java/org/alfresco/util/schemacomp/SchemaToXMLTest.java b/source/java/org/alfresco/util/schemacomp/SchemaToXMLTest.java
index a25ec005ae..4e9b2f4263 100644
--- a/source/java/org/alfresco/util/schemacomp/SchemaToXMLTest.java
+++ b/source/java/org/alfresco/util/schemacomp/SchemaToXMLTest.java
@@ -25,6 +25,7 @@ import static org.alfresco.util.schemacomp.SchemaCompTestingUtils.fkeys;
import static org.alfresco.util.schemacomp.SchemaCompTestingUtils.indexes;
import static org.alfresco.util.schemacomp.SchemaCompTestingUtils.pk;
import static org.alfresco.util.schemacomp.SchemaCompTestingUtils.table;
+import static org.alfresco.util.schemacomp.SchemaCompTestingUtils.sequence;
import static org.junit.Assert.assertEquals;
import java.io.BufferedReader;
@@ -65,7 +66,9 @@ public class SchemaToXMLTest
"name VARCHAR2(150)"),
pk("pk_node", "id"),
fkeys(fk("fk_node_noderef", "nodeRef", "node", "nodeRef")),
- indexes("idx_node_by_id id nodeRef")) );
+ indexes("idx_node_by_id id nodeRef")));
+ schema.add(sequence("node_seq"));
+ schema.add(sequence("content_seq"));
SchemaToXML transformer = new SchemaToXML(schema, out);
diff --git a/source/java/org/alfresco/util/schemacomp/XML.java b/source/java/org/alfresco/util/schemacomp/XML.java
new file mode 100644
index 0000000000..7b7cd569bc
--- /dev/null
+++ b/source/java/org/alfresco/util/schemacomp/XML.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.util.schemacomp;
+
+import org.alfresco.util.schemacomp.model.*;
+
+/**
+ * Constants relating to the XML representation of the schema data model.
+ *
+ * @author Matt Ward
+ */
+public abstract class XML
+{
+ public static final String EL_SCHEMA = Schema.class.getSimpleName().toLowerCase();
+ public static final String EL_TABLE = Table.class.getSimpleName().toLowerCase();
+ public static final String EL_COLUMN = Column.class.getSimpleName().toLowerCase();
+ public static final String EL_PRIMARY_KEY = PrimaryKey.class.getSimpleName().toLowerCase();
+ public static final String EL_FOREIGN_KEY = ForeignKey.class.getSimpleName().toLowerCase();
+ public static final String EL_INDEX = Index.class.getSimpleName().toLowerCase();
+ public static final String EL_SEQUENCE = Sequence.class.getSimpleName().toLowerCase();
+ public static final String EL_TYPE = "type";
+ public static final String EL_NULLABLE = "nullable";
+ public static final String EL_COLUMN_NAME = "columnname";
+ public static final String EL_COLUMN_NAMES = "columnnames";
+ public static final String EL_LOCAL_COLUMN = "localcolumn";
+ public static final String EL_TARGET_COLUMN = "targetcolumn";
+ public static final String EL_TARGET_TABLE = "targettable";
+
+ public static final String ATTR_NAME = "name";
+}
diff --git a/source/java/org/alfresco/util/schemacomp/XMLToSchema.java b/source/java/org/alfresco/util/schemacomp/XMLToSchema.java
new file mode 100644
index 0000000000..75459e888b
--- /dev/null
+++ b/source/java/org/alfresco/util/schemacomp/XMLToSchema.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.util.schemacomp;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Stack;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.alfresco.util.schemacomp.model.Column;
+import org.alfresco.util.schemacomp.model.DbObject;
+import org.alfresco.util.schemacomp.model.ForeignKey;
+import org.alfresco.util.schemacomp.model.Index;
+import org.alfresco.util.schemacomp.model.PrimaryKey;
+import org.alfresco.util.schemacomp.model.Schema;
+import org.alfresco.util.schemacomp.model.Sequence;
+import org.alfresco.util.schemacomp.model.Table;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Parse an XML document representing a database schema.
+ *
+ * @author Matt Ward
+ */
+public class XMLToSchema extends DefaultHandler
+{
+ private SAXParser parser;
+ private InputStream in;
+ private Schema schema;
+ private Stack dboStack = new Stack();
+ private String lastTag;
+ private String lastText;
+
+
+ public XMLToSchema(InputStream in, SAXParserFactory saxParserFactory)
+ {
+ this.in = in;
+ try
+ {
+ parser = saxParserFactory.newSAXParser();
+ }
+ catch (Throwable e)
+ {
+ throw new RuntimeException("Cannot create parser.", e);
+ }
+ }
+
+ public XMLToSchema(InputStream in)
+ {
+ this(in, SAXParserFactory.newInstance());
+ }
+
+ public void parse()
+ {
+ try
+ {
+ parser.parse(in, this);
+ }
+ catch (SAXException error)
+ {
+ throw new RuntimeException("Unable to parse input stream.", error);
+ }
+ catch (IOException error)
+ {
+ throw new RuntimeException("Unable to parse input stream.", error);
+ }
+ }
+
+ public Schema getSchema()
+ {
+ return this.schema;
+ }
+
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException
+ {
+ if (qName.equals(XML.EL_TABLE))
+ {
+ Table table = (Table) dboStack.pop();
+ schema.add(table);
+ }
+ else if (qName.equals(XML.EL_COLUMN))
+ {
+ Column column = (Column) dboStack.pop();
+ Table table = (Table) dboStack.peek();
+ table.getColumns().add(column);
+ }
+ else if (qName.equals(XML.EL_PRIMARY_KEY))
+ {
+ PrimaryKey pk = (PrimaryKey) dboStack.pop();
+ Table table = (Table) dboStack.peek();
+ table.setPrimaryKey(pk);
+ }
+ else if (qName.equals(XML.EL_FOREIGN_KEY))
+ {
+ ForeignKey fk = (ForeignKey) dboStack.pop();
+ Table table = (Table) dboStack.peek();
+ table.getForeignKeys().add(fk);
+ }
+ else if (qName.equals(XML.EL_INDEX))
+ {
+ Index index = (Index) dboStack.pop();
+ Table table = (Table) dboStack.peek();
+ table.getIndexes().add(index);
+ }
+ else if (qName.equals(XML.EL_SEQUENCE))
+ {
+ Sequence seq = (Sequence) dboStack.pop();
+ schema.add(seq);
+ }
+ }
+
+
+
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes atts)
+ throws SAXException
+ {
+ lastTag = qName;
+
+ if (qName.equals(XML.EL_SCHEMA))
+ {
+ schema = new Schema(atts.getValue(XML.ATTR_NAME));
+ }
+ else if (qName.equals(XML.EL_TABLE))
+ {
+ dboStack.push(new Table(atts.getValue(XML.ATTR_NAME)));
+ }
+ else if (qName.equals(XML.EL_COLUMN))
+ {
+ dboStack.push(new Column(atts.getValue(XML.ATTR_NAME)));
+ }
+ else if (qName.equals(XML.EL_PRIMARY_KEY))
+ {
+ dboStack.push(new PrimaryKey(atts.getValue(XML.ATTR_NAME)));
+ }
+ else if (qName.equals(XML.EL_FOREIGN_KEY))
+ {
+ dboStack.push(new ForeignKey(atts.getValue(XML.ATTR_NAME)));
+ }
+ else if (qName.equals(XML.EL_INDEX))
+ {
+ dboStack.push(new Index(atts.getValue(XML.ATTR_NAME)));
+ }
+ else if (qName.equals(XML.EL_SEQUENCE))
+ {
+ dboStack.push(new Sequence(atts.getValue(XML.ATTR_NAME)));
+ }
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException
+ {
+ lastText = new String(ch, start, length).trim();
+
+ if (lastText.length() != 0)
+ {
+ if (lastTag.equals(XML.EL_TYPE))
+ {
+ Column column = (Column) dboStack.peek();
+ column.setType(lastText);
+ }
+ else if (lastTag.equals(XML.EL_NULLABLE))
+ {
+ Column column = (Column) dboStack.peek();
+ column.setNullable(Boolean.parseBoolean(lastText));
+ }
+ else if (lastTag.equals(XML.EL_COLUMN_NAME))
+ {
+ if (dboStack.peek() instanceof PrimaryKey)
+ {
+ PrimaryKey pk = (PrimaryKey) dboStack.peek();
+ pk.getColumnNames().add(lastText);
+ }
+ else if (dboStack.peek() instanceof Index)
+ {
+ Index index = (Index) dboStack.peek();
+ index.getColumnNames().add(lastText);
+ }
+ }
+ else if (lastTag.equals(XML.EL_LOCAL_COLUMN))
+ {
+ ForeignKey fk = (ForeignKey) dboStack.peek();
+ fk.setLocalColumn(lastText);
+ }
+ else if (lastTag.equals(XML.EL_TARGET_TABLE))
+ {
+ ForeignKey fk = (ForeignKey) dboStack.peek();
+ fk.setTargetTable(lastText);
+ }
+ else if (lastTag.equals(XML.EL_TARGET_COLUMN))
+ {
+ ForeignKey fk = (ForeignKey) dboStack.peek();
+ fk.setTargetColumn(lastText);
+ }
+ }
+ }
+}
diff --git a/source/java/org/alfresco/util/schemacomp/XMLToSchemaTest.java b/source/java/org/alfresco/util/schemacomp/XMLToSchemaTest.java
new file mode 100644
index 0000000000..512f460499
--- /dev/null
+++ b/source/java/org/alfresco/util/schemacomp/XMLToSchemaTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.util.schemacomp;
+
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.util.Iterator;
+
+import org.alfresco.util.schemacomp.model.DbObject;
+import org.alfresco.util.schemacomp.model.Schema;
+import org.alfresco.util.schemacomp.model.Sequence;
+import org.alfresco.util.schemacomp.model.Table;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ * Tests for the XMLToSchema class.
+ *
+ * @author Matt Ward
+ */
+public class XMLToSchemaTest
+{
+ private XMLToSchema xmlToSchema;
+ private InputStream in;
+
+ @Before
+ public void setUp() throws Exception
+ {
+ in = new BufferedInputStream(getClass().getResourceAsStream("xml_to_schema_test.xml"));
+ xmlToSchema = new XMLToSchema(in);
+ }
+
+ @Test
+ public void canReadSchemaXML()
+ {
+ xmlToSchema.parse();
+ Schema schema = xmlToSchema.getSchema();
+
+ assertNotNull("A null Schema object was returned", schema);
+ assertEquals("alfresco", schema.getName());
+
+ Iterator objects = schema.iterator();
+
+ Table table = (Table) objects.next();
+ assertEquals("node", table.getName());
+ assertEquals(3, table.getColumns().size());
+
+ assertEquals("id", table.getColumns().get(0).getName());
+ assertEquals("NUMBER(10)", table.getColumns().get(0).getType());
+ assertEquals(false, table.getColumns().get(0).isNullable());
+
+ assertEquals("nodeRef", table.getColumns().get(1).getName());
+ assertEquals("VARCHAR2(200)", table.getColumns().get(1).getType());
+ assertEquals(false, table.getColumns().get(1).isNullable());
+
+ assertEquals("name", table.getColumns().get(2).getName());
+ assertEquals("VARCHAR2(150)", table.getColumns().get(2).getType());
+ assertEquals(true, table.getColumns().get(2).isNullable());
+
+ assertEquals("pk_node", table.getPrimaryKey().getName());
+ assertEquals(1, table.getPrimaryKey().getColumnNames().size());
+ assertEquals("id", table.getPrimaryKey().getColumnNames().get(0));
+
+ assertEquals(1, table.getForeignKeys().size());
+ assertEquals("fk_node_noderef", table.getForeignKeys().get(0).getName());
+ assertEquals("nodeRef", table.getForeignKeys().get(0).getLocalColumn());
+ assertEquals("node", table.getForeignKeys().get(0).getTargetTable());
+ assertEquals("nodeRef", table.getForeignKeys().get(0).getTargetColumn());
+
+ assertEquals(1, table.getIndexes().size());
+ assertEquals("idx_node_by_id", table.getIndexes().get(0).getName());
+ assertEquals(2, table.getIndexes().get(0).getColumnNames().size());
+ assertEquals("id", table.getIndexes().get(0).getColumnNames().get(0));
+ assertEquals("nodeRef", table.getIndexes().get(0).getColumnNames().get(1));
+
+ assertEquals("node_seq", ((Sequence) objects.next()).getName());
+ assertEquals("person_seq", ((Sequence) objects.next()).getName());
+ assertEquals("content_seq", ((Sequence) objects.next()).getName());
+
+ assertFalse("Should be no more DB objects", objects.hasNext());
+ }
+}
diff --git a/source/java/org/alfresco/util/schemacomp/model/Column.java b/source/java/org/alfresco/util/schemacomp/model/Column.java
index b5861aa116..358f7c2962 100644
--- a/source/java/org/alfresco/util/schemacomp/model/Column.java
+++ b/source/java/org/alfresco/util/schemacomp/model/Column.java
@@ -35,6 +35,11 @@ public class Column extends AbstractDbObject
private boolean nullable;
+ public Column(String name)
+ {
+ super(null, name);
+ }
+
/**
* Construct a Column.
*
diff --git a/source/java/org/alfresco/util/schemacomp/model/ForeignKey.java b/source/java/org/alfresco/util/schemacomp/model/ForeignKey.java
index ecc42e2c7e..d17756e706 100644
--- a/source/java/org/alfresco/util/schemacomp/model/ForeignKey.java
+++ b/source/java/org/alfresco/util/schemacomp/model/ForeignKey.java
@@ -21,7 +21,6 @@ package org.alfresco.util.schemacomp.model;
import org.alfresco.util.schemacomp.DbObjectVisitor;
import org.alfresco.util.schemacomp.DbProperty;
import org.alfresco.util.schemacomp.DiffContext;
-import org.alfresco.util.schemacomp.Results;
import org.alfresco.util.schemacomp.Result.Strength;
@@ -38,6 +37,11 @@ public class ForeignKey extends AbstractDbObject
private String targetColumn;
+ public ForeignKey(String name)
+ {
+ super(null, name);
+ }
+
/**
* Constructor.
*
diff --git a/source/java/org/alfresco/util/schemacomp/model/Index.java b/source/java/org/alfresco/util/schemacomp/model/Index.java
index ab5ce00617..56bf52390b 100644
--- a/source/java/org/alfresco/util/schemacomp/model/Index.java
+++ b/source/java/org/alfresco/util/schemacomp/model/Index.java
@@ -18,6 +18,7 @@
*/
package org.alfresco.util.schemacomp.model;
+import java.util.ArrayList;
import java.util.List;
import org.alfresco.util.schemacomp.DbObjectVisitor;
@@ -32,9 +33,14 @@ import org.alfresco.util.schemacomp.Result.Strength;
*/
public class Index extends AbstractDbObject
{
- private List columnNames;
+ private final List columnNames = new ArrayList();
+ public Index(String name)
+ {
+ super(null, name);
+ }
+
/**
* @param table the parent table
* @param columnNames
@@ -42,7 +48,7 @@ public class Index extends AbstractDbObject
public Index(Table table, String name, List columnNames)
{
super(table, name);
- this.columnNames = columnNames;
+ this.columnNames.addAll(columnNames);
setNameStrength(Strength.WARN);
}
@@ -59,7 +65,8 @@ public class Index extends AbstractDbObject
*/
public void setColumnNames(List columnNames)
{
- this.columnNames = columnNames;
+ this.columnNames.clear();
+ this.columnNames.addAll(columnNames);
}
@Override
diff --git a/source/java/org/alfresco/util/schemacomp/model/PrimaryKey.java b/source/java/org/alfresco/util/schemacomp/model/PrimaryKey.java
index 2bb41e5fd4..9175d24cf6 100644
--- a/source/java/org/alfresco/util/schemacomp/model/PrimaryKey.java
+++ b/source/java/org/alfresco/util/schemacomp/model/PrimaryKey.java
@@ -18,6 +18,7 @@
*/
package org.alfresco.util.schemacomp.model;
+import java.util.ArrayList;
import java.util.List;
import org.alfresco.util.schemacomp.DbObjectVisitor;
@@ -32,9 +33,14 @@ import org.alfresco.util.schemacomp.Result.Strength;
*/
public class PrimaryKey extends AbstractDbObject
{
- private List columnNames;
+ private final List columnNames = new ArrayList();
+ public PrimaryKey(String name)
+ {
+ super(null, name);
+ }
+
/**
* Constructor
* @param table the parent table
@@ -44,7 +50,7 @@ public class PrimaryKey extends AbstractDbObject
public PrimaryKey(Table table, String name, List columnNames)
{
super(table, name);
- this.columnNames = columnNames;
+ this.columnNames.addAll(columnNames);
}
/**
@@ -60,7 +66,8 @@ public class PrimaryKey extends AbstractDbObject
*/
public void setColumnNames(List columnNames)
{
- this.columnNames = columnNames;
+ this.columnNames.clear();
+ this.columnNames.addAll(columnNames);
}
@Override
diff --git a/source/java/org/alfresco/util/schemacomp/model/Sequence.java b/source/java/org/alfresco/util/schemacomp/model/Sequence.java
index 71ac0b80dd..6b2ebd02fc 100644
--- a/source/java/org/alfresco/util/schemacomp/model/Sequence.java
+++ b/source/java/org/alfresco/util/schemacomp/model/Sequence.java
@@ -28,6 +28,12 @@ import org.alfresco.util.schemacomp.DbObjectVisitor;
*/
public class Sequence extends AbstractDbObject
{
+
+ public Sequence(String name)
+ {
+ super(null, name);
+ }
+
public Sequence(DbObject parent, String name)
{
super(parent, name);
diff --git a/source/java/org/alfresco/util/schemacomp/model/Table.java b/source/java/org/alfresco/util/schemacomp/model/Table.java
index 65f9d17dbe..159552b469 100644
--- a/source/java/org/alfresco/util/schemacomp/model/Table.java
+++ b/source/java/org/alfresco/util/schemacomp/model/Table.java
@@ -39,6 +39,17 @@ public class Table extends AbstractDbObject
private final List indexes = new ArrayList();
+ public Table(String name)
+ {
+ super(null, name);
+ }
+
+ public Table(String name, Collection columns, PrimaryKey primaryKey,
+ Collection foreignKeys, Collection indexes)
+ {
+ this(null, name, columns, primaryKey, foreignKeys, indexes);
+ }
+
public Table(Schema parentSchema, String name, Collection columns, PrimaryKey primaryKey,
Collection foreignKeys, Collection indexes)
{
diff --git a/source/java/org/alfresco/util/schemacomp/xml_to_schema_test.xml b/source/java/org/alfresco/util/schemacomp/xml_to_schema_test.xml
new file mode 100644
index 0000000000..9788c96a47
--- /dev/null
+++ b/source/java/org/alfresco/util/schemacomp/xml_to_schema_test.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+ NUMBER(10)
+ false
+
+
+ VARCHAR2(200)
+ false
+
+
+ VARCHAR2(150)
+ true
+
+
+
+
+ id
+
+
+
+
+ nodeRef
+ node
+ nodeRef
+
+
+
+
+
+ id
+ nodeRef
+
+
+
+
+
+
+
+
+