ALF-10771: schema validation and differences rules

Validation serialized and deserialized in XML.



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@31942 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Matt Ward
2011-11-14 16:25:49 +00:00
parent 6b3eb6181f
commit 3df35a9d06
15 changed files with 432 additions and 62 deletions

View File

@@ -19,6 +19,7 @@
package org.alfresco.util.schemacomp;
import java.util.Collection;
import java.util.List;
import org.alfresco.util.schemacomp.model.Column;
import org.alfresco.util.schemacomp.model.DbObject;
@@ -27,6 +28,8 @@ 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.Table;
import org.alfresco.util.schemacomp.validator.DbValidator;
import org.apache.poi.hssf.record.DVALRecord;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
@@ -65,21 +68,62 @@ public class DbObjectXMLTransformer
// All DbObjects result in an XML element with the DbObject's class name as the tag
// and a name attribute corresponding to the value of getName(),
// e.g. For an instance of a Column: <column name="the_column_name"/>
String tagName = dbObject.getClass().getSimpleName().toLowerCase();
final AttributesImpl attribs = new AttributesImpl();
attribs.addAttribute("", "", "name", "CDATA", dbObject.getName());
attribs.addAttribute("", "", XML.ATTR_NAME, "CDATA", dbObject.getName());
// Add class-specific attributes.
addAttributes(dbObject, attribs);
String tagName = dbObject.getClass().getSimpleName().toLowerCase();
xmlOut.startElement("", "", tagName, attribs);
// The element's contents can optionally be populated with class-specific content.
transformDbObject(dbObject);
// All DbObjects potentially have validator configuration present in the XML.
transformValidators(dbObject.getValidators());
// Provide the end tag, or close an empty element.
xmlOut.endElement("", "", tagName);
}
/**
* @param validators
* @throws SAXException
*/
private void transformValidators(List<DbValidator<? extends DbObject>> validators) throws SAXException
{
if (validators.size() > 0)
{
simpleStartTag(XML.EL_VALIDATORS);
for (DbValidator<? extends DbObject> dbv : validators)
{
final AttributesImpl attribs = new AttributesImpl();
attribs.addAttribute("", "", XML.ATTR_CLASS, "CDATA", dbv.getClass().getName());
xmlOut.startElement("", "", XML.EL_VALIDATOR, attribs);
if (dbv.getPropertyNames().size() > 0)
{
simpleStartTag(XML.EL_PROPERTIES);
for (String propName : dbv.getPropertyNames())
{
final AttributesImpl propAttrs = new AttributesImpl();
propAttrs.addAttribute("", "", XML.ATTR_NAME, "CDATA", propName);
xmlOut.startElement("", "", XML.EL_PROPERTY, propAttrs);
String propValue = dbv.getProperty(propName);
char[] chars = propValue.toCharArray();
xmlOut.characters(chars, 0, chars.length);
simpleEndTag(XML.EL_PROPERTY);
}
simpleEndTag(XML.EL_PROPERTIES);
}
simpleEndTag(XML.EL_VALIDATOR);
}
simpleEndTag(XML.EL_VALIDATORS);
}
}
/**
* Add class-specific attributes.
*
@@ -91,7 +135,7 @@ public class DbObjectXMLTransformer
if (dbObject instanceof Index)
{
Index index = (Index) dbObject;
attribs.addAttribute("", "", "unique", "CDATA", Boolean.toString(index.isUnique()));
attribs.addAttribute("", "", XML.ATTR_UNIQUE, "CDATA", Boolean.toString(index.isUnique()));
}
}
@@ -127,55 +171,55 @@ public class DbObjectXMLTransformer
private void transformSchema(Schema schema) throws SAXException
{
simpleStartTag("objects");
simpleStartTag(XML.EL_OBJECTS);
for (DbObject dbo : schema)
{
output(dbo);
}
simpleEndTag("objects");
simpleEndTag(XML.EL_OBJECTS);
}
private void transformTable(Table table) throws SAXException
{
// Output columns
simpleStartTag("columns");
simpleStartTag(XML.EL_COLUMNS);
for (Column column : table.getColumns())
{
output(column);
}
simpleEndTag("columns");
simpleEndTag(XML.EL_COLUMNS);
// Output primary key
output(table.getPrimaryKey());
// Output foreign keys
simpleStartTag("foreignkeys");
simpleStartTag(XML.EL_FOREIGN_KEYS);
for (ForeignKey fk : table.getForeignKeys())
{
output(fk);
}
simpleEndTag("foreignkeys");
simpleEndTag(XML.EL_FOREIGN_KEYS);
// Output indexes
simpleStartTag("indexes");
simpleStartTag(XML.EL_INDEXES);
for (Index index : table.getIndexes())
{
output(index);
}
simpleEndTag("indexes");
simpleEndTag(XML.EL_INDEXES);
}
private void transformColumn(Column column) throws SAXException
{
simpleElement("type", column.getType());
simpleElement("nullable", Boolean.toString(column.isNullable()));
simpleElement(XML.EL_TYPE, column.getType());
simpleElement(XML.EL_NULLABLE, Boolean.toString(column.isNullable()));
}
private void transformForeignKey(ForeignKey fk) throws SAXException
{
simpleElement("localcolumn", fk.getLocalColumn());
simpleElement("targettable", fk.getTargetTable());
simpleElement("targetcolumn", fk.getTargetColumn());
simpleElement(XML.EL_LOCAL_COLUMN, fk.getLocalColumn());
simpleElement(XML.EL_TARGET_TABLE, fk.getTargetTable());
simpleElement(XML.EL_TARGET_COLUMN, fk.getTargetColumn());
}
private void transformIndex(Index index) throws SAXException
@@ -219,11 +263,11 @@ public class DbObjectXMLTransformer
private void columnNameList(Collection<String> columnNames) throws SAXException
{
simpleStartTag("columnnames");
simpleStartTag(XML.EL_COLUMN_NAMES);
for (String columnName : columnNames)
{
simpleElement("columnname", columnName);
simpleElement(XML.EL_COLUMN_NAME, columnName);
}
simpleEndTag("columnnames");
simpleEndTag(XML.EL_COLUMN_NAMES);
}
}

View File

@@ -31,8 +31,12 @@ import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
@@ -43,12 +47,15 @@ import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
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.alfresco.util.schemacomp.validator.DbValidator;
import org.alfresco.util.schemacomp.validator.NameValidator;
import org.junit.Before;
import org.junit.Test;
@@ -248,6 +255,53 @@ public class DbObjectXMLTransformerTest
assertEquals("</table>", reader.readLine());
}
@Test
public void transformObjectWithValidators() throws IOException
{
Collection<Column> columns = columns("one VARCHAR2(100)", "two NUMBER(10)");
PrimaryKey pk = new PrimaryKey(null, "pk_for_my_table", Arrays.asList("id"));
Collection<ForeignKey> fks = fkeys(fk("fk_one", "lc", "tt", "tc"), fk("fk_two", "lc", "tt", "tc"));
Collection<Index> indexes = indexes("index_one col1 col2", "index_two col3 col4");
Table table = new Table(null, "my_table", columns, pk, fks, indexes);
NameValidator nameValidator = new NameValidator();
nameValidator.setPattern(Pattern.compile("match_me_if_you_can"));
List<DbValidator<? extends DbObject>> validators = new ArrayList<DbValidator<? extends DbObject>>();
validators.add(nameValidator);
table.setValidators(validators);
transformer.output(table);
BufferedReader reader = new BufferedReader(new StringReader(writer.toString()));
dumpOutput();
assertHasPreamble(reader);
assertEquals("<table name=\"my_table\">", reader.readLine());
assertEquals(" <columns>", reader.readLine());
skipUntilEnd(" {column}", reader);
skipUntilEnd(" {column}", reader);
assertEquals(" </columns>", reader.readLine());
skipUntilEnd(" {primarykey}", reader);
assertEquals(" <foreignkeys>", reader.readLine());
skipUntilEnd(" {foreignkey}", reader);
skipUntilEnd(" {foreignkey}", reader);
assertEquals(" </foreignkeys>", reader.readLine());
assertEquals(" <indexes>", reader.readLine());
skipUntilEnd(" {index}", reader);
skipUntilEnd(" {index}", reader);
assertEquals(" </indexes>", reader.readLine());
assertEquals(" <validators>", reader.readLine());
assertEquals(" <validator class=\"org.alfresco.util.schemacomp.validator.NameValidator\">", reader.readLine());
assertEquals(" <properties>", reader.readLine());
assertEquals(" <property name=\"pattern\">match_me_if_you_can</property>", reader.readLine());
assertEquals(" </properties>", reader.readLine());
assertEquals(" </validator>", reader.readLine());
assertEquals(" </validators>", reader.readLine());
assertEquals("</table>", reader.readLine());
}
/**
* Ignore lines that are tested elsewhere, e.g. ignore serialized Column objects
* in the context of a Table since we only need to know that there was text for a

View File

@@ -30,9 +30,12 @@ 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_COLUMNS = "columns";
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_FOREIGN_KEYS = "foreignkeys";
public static final String EL_INDEX = Index.class.getSimpleName().toLowerCase();
public static final String EL_INDEXES = "indexes";
public static final String EL_SEQUENCE = Sequence.class.getSimpleName().toLowerCase();
public static final String EL_TYPE = "type";
public static final String EL_NULLABLE = "nullable";
@@ -41,7 +44,13 @@ public abstract class XML
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 EL_VALIDATORS = "validators";
public static final String EL_VALIDATOR = "validator";
public static final String EL_OBJECTS = "objects";
public static final String EL_PROPERTIES = "properties";
public static final String EL_PROPERTY = "property";
public static final String ATTR_NAME = "name";
public static final String ATTR_UNIQUE = "unique";
public static final String ATTR_CLASS = "class";
}

View File

@@ -20,6 +20,8 @@ package org.alfresco.util.schemacomp;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import javax.xml.parsers.SAXParser;
@@ -33,6 +35,7 @@ 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.alfresco.util.schemacomp.validator.DbValidator;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
@@ -47,7 +50,7 @@ public class XMLToSchema extends DefaultHandler
private SAXParser parser;
private InputStream in;
private Schema schema;
private Stack<DbObject> dboStack = new Stack<DbObject>();
private Stack<Object> stack = new Stack<Object>();
private String lastTag;
private String lastText;
@@ -97,43 +100,53 @@ public class XMLToSchema extends DefaultHandler
{
if (qName.equals(XML.EL_TABLE))
{
Table table = (Table) dboStack.pop();
Table table = (Table) stack.pop();
schema.add(table);
}
else if (qName.equals(XML.EL_COLUMN))
{
Column column = (Column) dboStack.pop();
Table table = (Table) dboStack.peek();
Column column = (Column) stack.pop();
Table table = (Table) stack.peek();
table.getColumns().add(column);
}
else if (qName.equals(XML.EL_PRIMARY_KEY))
{
PrimaryKey pk = (PrimaryKey) dboStack.pop();
Table table = (Table) dboStack.peek();
PrimaryKey pk = (PrimaryKey) stack.pop();
Table table = (Table) stack.peek();
table.setPrimaryKey(pk);
}
else if (qName.equals(XML.EL_FOREIGN_KEY))
{
ForeignKey fk = (ForeignKey) dboStack.pop();
Table table = (Table) dboStack.peek();
ForeignKey fk = (ForeignKey) stack.pop();
Table table = (Table) stack.peek();
table.getForeignKeys().add(fk);
}
else if (qName.equals(XML.EL_INDEX))
{
Index index = (Index) dboStack.pop();
Table table = (Table) dboStack.peek();
Index index = (Index) stack.pop();
Table table = (Table) stack.peek();
table.getIndexes().add(index);
}
else if (qName.equals(XML.EL_SEQUENCE))
{
Sequence seq = (Sequence) dboStack.pop();
Sequence seq = (Sequence) stack.pop();
schema.add(seq);
}
else if (qName.equals(XML.EL_VALIDATOR))
{
@SuppressWarnings("unchecked")
DbValidator<? extends DbObject> validator = (DbValidator<? extends DbObject>) stack.pop();
DbObject dbo = (DbObject) stack.peek();
dbo.getValidators().add(validator);
}
else if (qName.equals(XML.EL_PROPERTY))
{
//stack.pop();
}
}
@SuppressWarnings("unchecked")
@Override
public void startElement(String uri, String localName, String qName, Attributes atts)
throws SAXException
@@ -146,30 +159,50 @@ public class XMLToSchema extends DefaultHandler
}
else if (qName.equals(XML.EL_TABLE))
{
dboStack.push(new Table(atts.getValue(XML.ATTR_NAME)));
stack.push(new Table(atts.getValue(XML.ATTR_NAME)));
}
else if (qName.equals(XML.EL_COLUMN))
{
dboStack.push(new Column(atts.getValue(XML.ATTR_NAME)));
stack.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)));
stack.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)));
stack.push(new ForeignKey(atts.getValue(XML.ATTR_NAME)));
}
else if (qName.equals(XML.EL_INDEX))
{
Index index = new Index(atts.getValue(XML.ATTR_NAME));
boolean unique = Boolean.parseBoolean(atts.getValue(XML.ATTR_UNIQUE));
index.setUnique(unique);
dboStack.push(index);
stack.push(index);
}
else if (qName.equals(XML.EL_SEQUENCE))
{
dboStack.push(new Sequence(atts.getValue(XML.ATTR_NAME)));
stack.push(new Sequence(atts.getValue(XML.ATTR_NAME)));
}
else if (qName.equals(XML.EL_VALIDATOR))
{
String className = atts.getValue(XML.ATTR_CLASS);
DbValidator<? extends DbObject> validator = null;
try
{
validator = (DbValidator<? extends DbObject>) Class.forName(className).newInstance();
}
catch (Throwable e)
{
throw new RuntimeException("Couldn't create validator, class: " + className, e);
}
stack.push(validator);
}
else if (qName.equals(XML.EL_PROPERTY))
{
String name = atts.getValue(XML.ATTR_NAME);
stack.push(name);
}
}
@@ -182,42 +215,53 @@ public class XMLToSchema extends DefaultHandler
{
if (lastTag.equals(XML.EL_TYPE))
{
Column column = (Column) dboStack.peek();
Column column = (Column) stack.peek();
column.setType(lastText);
}
else if (lastTag.equals(XML.EL_NULLABLE))
{
Column column = (Column) dboStack.peek();
Column column = (Column) stack.peek();
column.setNullable(Boolean.parseBoolean(lastText));
}
else if (lastTag.equals(XML.EL_COLUMN_NAME))
{
if (dboStack.peek() instanceof PrimaryKey)
if (stack.peek() instanceof PrimaryKey)
{
PrimaryKey pk = (PrimaryKey) dboStack.peek();
PrimaryKey pk = (PrimaryKey) stack.peek();
pk.getColumnNames().add(lastText);
}
else if (dboStack.peek() instanceof Index)
else if (stack.peek() instanceof Index)
{
Index index = (Index) dboStack.peek();
Index index = (Index) stack.peek();
index.getColumnNames().add(lastText);
}
}
else if (lastTag.equals(XML.EL_LOCAL_COLUMN))
{
ForeignKey fk = (ForeignKey) dboStack.peek();
ForeignKey fk = (ForeignKey) stack.peek();
fk.setLocalColumn(lastText);
}
else if (lastTag.equals(XML.EL_TARGET_TABLE))
{
ForeignKey fk = (ForeignKey) dboStack.peek();
ForeignKey fk = (ForeignKey) stack.peek();
fk.setTargetTable(lastText);
}
else if (lastTag.equals(XML.EL_TARGET_COLUMN))
{
ForeignKey fk = (ForeignKey) dboStack.peek();
ForeignKey fk = (ForeignKey) stack.peek();
fk.setTargetColumn(lastText);
}
else if (lastTag.equals(XML.EL_PROPERTY))
{
String propValue = lastText;
String propName = (String) stack.pop();
if (stack.peek() instanceof DbValidator)
{
@SuppressWarnings("unchecked")
DbValidator<? extends DbObject> validator = (DbValidator<? extends DbObject>) stack.peek();
validator.setProperty(propName, propValue);
}
}
}
}
}

View File

@@ -28,9 +28,12 @@ import java.io.InputStream;
import java.util.Iterator;
import org.alfresco.util.schemacomp.model.DbObject;
import org.alfresco.util.schemacomp.model.Index;
import org.alfresco.util.schemacomp.model.Schema;
import org.alfresco.util.schemacomp.model.Sequence;
import org.alfresco.util.schemacomp.model.Table;
import org.alfresco.util.schemacomp.validator.DbValidator;
import org.alfresco.util.schemacomp.validator.NameValidator;
import org.junit.Before;
import org.junit.Test;
@@ -89,11 +92,17 @@ public class XMLToSchemaTest
assertEquals("nodeRef", table.getForeignKeys().get(0).getTargetColumn());
assertEquals(1, table.getIndexes().size());
assertEquals("idx_node_by_id", table.getIndexes().get(0).getName());
assertEquals(true, table.getIndexes().get(0).isUnique());
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));
Index index = table.getIndexes().get(0);
assertEquals("idx_node_by_id", index.getName());
assertEquals(true, index.isUnique());
assertEquals(2, index.getColumnNames().size());
assertEquals("id", index.getColumnNames().get(0));
assertEquals("nodeRef", index.getColumnNames().get(1));
assertEquals(1, index.getValidators().size());
DbValidator<? extends DbObject> validator = index.getValidators().get(0);
assertEquals(NameValidator.class, validator.getClass());
assertEquals(1, validator.getPropertyNames().size());
assertEquals("idx_.+", validator.getProperty("pattern"));
assertEquals("node_seq", ((Sequence) objects.next()).getName());
assertEquals("person_seq", ((Sequence) objects.next()).getName());

View File

@@ -18,12 +18,17 @@
*/
package org.alfresco.util.schemacomp.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.alfresco.util.schemacomp.ComparisonUtils;
import org.alfresco.util.schemacomp.DbProperty;
import org.alfresco.util.schemacomp.DefaultComparisonUtils;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.Result.Strength;
import org.alfresco.util.schemacomp.Results;
import org.alfresco.util.schemacomp.validator.DbValidator;
/**
* Useful base class for many, if not all the {@link DbObject} implementations.
@@ -37,6 +42,7 @@ public abstract class AbstractDbObject implements DbObject
/** How differences in the name field should be reported */
private Strength nameStrength = Strength.ERROR;
protected ComparisonUtils comparisonUtils = new DefaultComparisonUtils();
private List<DbValidator<?>> validators = new ArrayList<DbValidator<?>>();
/**
@@ -203,4 +209,28 @@ public abstract class AbstractDbObject implements DbObject
{
this.comparisonUtils = comparisonUtils;
}
@Override
public List<DbValidator<? extends DbObject>> getValidators()
{
return validators;
}
/**
* @param validators the validators to set
*/
@Override
public void setValidators(List<DbValidator<? extends DbObject>> validators)
{
if (validators == null)
{
this.validators = Collections.emptyList();
}
else
{
this.validators = validators;
}
}
}

View File

@@ -24,6 +24,8 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.inOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.alfresco.util.schemacomp.DbObjectVisitor;
import org.alfresco.util.schemacomp.DbProperty;
@@ -32,6 +34,8 @@ import org.alfresco.util.schemacomp.Difference.Where;
import org.alfresco.util.schemacomp.Result.Strength;
import org.alfresco.util.schemacomp.Results;
import org.alfresco.util.schemacomp.ValidationResult;
import org.alfresco.util.schemacomp.validator.AbstractDbValidator;
import org.alfresco.util.schemacomp.validator.DbValidator;
import org.hibernate.dialect.Dialect;
import org.junit.Before;
import org.junit.Test;
@@ -83,8 +87,7 @@ public class AbstractDbObjectTest
assertTrue("Logically the same object.", dbObject.sameAs(new ConcreteDbObject("the_name")));
assertTrue("The very same object with non-null name", dbObject.sameAs(dbObject));
}
@Test
public void diff()
{
@@ -110,6 +113,25 @@ public class AbstractDbObjectTest
}
@SuppressWarnings("unchecked")
@Test
public void canGetValidators()
{
List<DbValidator<? extends DbObject>> validators = dbObject.getValidators();
assertEquals(0, validators.size());
dbObject.setValidators(null);
validators = dbObject.getValidators();
assertEquals(0, validators.size());
dbObject.setValidators(validatorList(new TestValidator1(), new TestValidator2()));
validators = dbObject.getValidators();
assertEquals(2, validators.size());
assertEquals(TestValidator1.class, validators.get(0).getClass());
assertEquals(TestValidator2.class, validators.get(1).getClass());
}
/**
* Concrete DbObject for testing the AbstractDbObject base class.
*/
@@ -142,4 +164,27 @@ public class AbstractDbObjectTest
return this.someProp;
}
}
private List<DbValidator<? extends DbObject>> validatorList(DbValidator<? extends DbObject>... validators)
{
return Arrays.asList(validators);
}
private static class TestValidator extends AbstractDbValidator<DbObject>
{
@Override
public void validate(DbObject reference, DbObject target, DiffContext ctx)
{
}
}
private static class TestValidator1 extends TestValidator
{
}
private static class TestValidator2 extends TestValidator
{
}
}

View File

@@ -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;
/**
@@ -116,7 +115,6 @@ public class Column extends AbstractDbObject
@Override
protected void doDiff(DbObject right, DiffContext ctx, Strength strength)
{
Results differences = ctx.getDifferences();
DbProperty thisTypeProp = new DbProperty(this, "type");
DbProperty thisNullableProp = new DbProperty(this, "nullable");

View File

@@ -18,10 +18,14 @@
*/
package org.alfresco.util.schemacomp.model;
import java.util.Collection;
import java.util.List;
import org.alfresco.util.schemacomp.DbObjectVisitor;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.Results;
import org.alfresco.util.schemacomp.Result.Strength;
import org.alfresco.util.schemacomp.validator.DbValidator;
/**
* All database objects to be modelled for schema comparisons must implement this interface, examples
@@ -86,4 +90,20 @@ public interface DbObject
* @param parent
*/
void setParent(DbObject parent);
/**
* Retrieve the list of validators associated with this database object.
*
* @see DbValidator
* @return DbValidator List
*/
List<DbValidator<? extends DbObject>> getValidators();
/**
* Set/override the validators associated with this database object.
*
* @param validators
*/
void setValidators(List<DbValidator<? extends DbObject>> validators);
}

View File

@@ -0,0 +1,54 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.util.schemacomp.validator;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.alfresco.util.schemacomp.model.DbObject;
/**
* Base class providing DbValidator support.
*
* @author Matt Ward
*/
public abstract class AbstractDbValidator<T extends DbObject> implements DbValidator<T>
{
private final Map<String, String> properties = new HashMap<String, String>();
@Override
public void setProperty(String name, String value)
{
properties.put(name, value);
}
@Override
public String getProperty(String name)
{
return properties.get(name);
}
@Override
public Set<String> getPropertyNames()
{
return properties.keySet();
}
}

View File

@@ -18,6 +18,8 @@
*/
package org.alfresco.util.schemacomp.validator;
import java.util.Set;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.model.DbObject;
@@ -27,7 +29,13 @@ import org.alfresco.util.schemacomp.model.DbObject;
*
* @author Matt Ward
*/
public interface DbValidator
public interface DbValidator<T extends DbObject>
{
void validate(DbObject reference, DbObject target, DiffContext ctx);
void validate(T reference, T target, DiffContext ctx);
void setProperty(String name, String value);
String getProperty(String name);
Set<String> getPropertyNames();
}

View File

@@ -18,8 +18,8 @@
*/
package org.alfresco.util.schemacomp.validator;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;
import org.alfresco.util.schemacomp.DbProperty;
@@ -36,7 +36,7 @@ import org.hibernate.dialect.Dialect;
*
* @author Matt Ward
*/
public class NameValidator implements DbValidator
public class NameValidator implements DbValidator<DbObject>
{
private Pattern pattern;
@@ -58,4 +58,41 @@ public class NameValidator implements DbValidator
{
this.pattern = pattern;
}
public Pattern getPattern()
{
return this.pattern;
}
@Override
public void setProperty(String name, String value)
{
if (name.equals("pattern") && value != null)
{
Pattern pattern = Pattern.compile(value);
setPattern(pattern);
}
}
@Override
public String getProperty(String name)
{
if (name.equals("pattern") && pattern != null)
{
return pattern.toString();
}
return null;
}
@Override
public Set<String> getPropertyNames()
{
Set<String> props = new TreeSet<String>();
props.add("pattern");
return props;
}
}

View File

@@ -22,7 +22,10 @@ package org.alfresco.util.schemacomp.validator;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.alfresco.util.schemacomp.DiffContext;
@@ -80,6 +83,14 @@ public class NameValidatorTest
}
@Test
public void canSetPatternUsingProperties()
{
validator.setProperty("pattern", "ORA_[A-Z_]+");
assertEquals("ORA_[A-Z_]+", validator.getPattern().toString());
}
private DbObject indexForName(String name)
{
return new Index(null, name, new ArrayList<String>());

View File

@@ -26,7 +26,7 @@ import org.alfresco.util.schemacomp.model.DbObject;
*
* @author Matt Ward
*/
public class NullValidator implements DbValidator
public class NullValidator extends AbstractDbValidator<DbObject>
{
@Override
public void validate(DbObject reference, DbObject target, DiffContext ctx)

View File

@@ -37,6 +37,13 @@
<columnname>id</columnname>
<columnname>nodeRef</columnname>
</columnnames>
<validators>
<validator class="org.alfresco.util.schemacomp.validator.NameValidator">
<properties>
<property name="pattern">idx_.+</property>
</properties>
</validator>
</validators>
</index>
</indexes>
</table>