ALF-10771: adding validation to schema compare tool

Added support to DbObjects to accept visitors
Added ValidatingVisitor to invoke suitable validator on each DbObject
Added NameValidator and NullValidator to operate on DbObject types
Added test suites



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@31494 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Matt Ward
2011-10-26 16:01:38 +00:00
parent 7764900451
commit ec302df6ed
33 changed files with 896 additions and 30 deletions

View File

@@ -0,0 +1,44 @@
/*
* 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;
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;
/**
* Defines a visitor that can operate on a DbObject.
* @author Matt Ward
*/
public interface DbObjectVisitor
{
void visit(DbObject dbObject);
// void visit(Column column);
// void visit(ForeignKey fk);
// void visit(Index index);
// void visit(PrimaryKey pk);
// void visit(Schema schema);
// void visit(Sequence sequence);
// void visit(Table table);
}

View File

@@ -57,7 +57,7 @@ public class DefaultComparisonUtilsTest
public void setUp()
{
comparisonUtils = new DefaultComparisonUtils();
ctx = new DiffContext(dialect, differences);
ctx = new DiffContext(dialect, differences, new ArrayList<ValidationResult>());
}
@Test

View File

@@ -18,6 +18,8 @@
*/
package org.alfresco.util.schemacomp;
import java.util.List;
import org.hibernate.dialect.Dialect;
/**
@@ -31,16 +33,17 @@ public class DiffContext
{
private final Dialect dialect;
private final Differences differences;
private final List<ValidationResult> validationResults;
/**
* @param dialect
* @param differences
*/
public DiffContext(Dialect dialect, Differences differences)
public DiffContext(Dialect dialect, Differences differences, List<ValidationResult> validationResults)
{
this.dialect = dialect;
this.differences = differences;
this.validationResults = validationResults;
}
/**
@@ -58,4 +61,14 @@ public class DiffContext
{
return this.differences;
}
/**
* @return the validationResults
*/
public List<ValidationResult> getValidationResults()
{
return this.validationResults;
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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;
import org.alfresco.util.schemacomp.model.ModelTestSuite;
import org.alfresco.util.schemacomp.validator.ValidatorTestSuite;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
/**
* Test suite running all the tests in the schemacomp package - and subpackages.
* @author Matt Ward
*/
@RunWith(Suite.class)
@Suite.SuiteClasses(
{
ModelTestSuite.class,
ValidatorTestSuite.class,
SchemaCompTestSuite.class
})
public class SchemaCompPackagetTestSuite
{
}

View File

@@ -30,7 +30,8 @@ import org.junit.runners.Suite;
@Suite.SuiteClasses(
{
DefaultComparisonUtilsTest.class,
SchemaComparatorTest.class
SchemaComparatorTest.class,
ValidatingVisitorTest.class
})
public class SchemaCompTestSuite
{

View File

@@ -18,6 +18,9 @@
*/
package org.alfresco.util.schemacomp;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.util.schemacomp.Result.Strength;
import org.alfresco.util.schemacomp.model.Schema;
import org.hibernate.dialect.Dialect;
@@ -44,22 +47,51 @@ public class SchemaComparator
{
this.leftSchema = left;
this.rightSchema = right;
this.ctx = new DiffContext(dialect, new Differences());
this.ctx = new DiffContext(dialect, new Differences(), new ArrayList<ValidationResult>());
}
public void compare()
public void validateAndCompare()
{
validate();
compare();
}
/**
* Check the left schema against the right schema and record any differences.
*/
private void compare()
{
// Check the left schema against the right schema and record any differences.
leftSchema.diff(rightSchema, ctx, Strength.ERROR);
}
/**
* Validate both schemas.
*/
private void validate()
{
ValidatingVisitor validatingVisitor = new ValidatingVisitor(ctx);
leftSchema.accept(validatingVisitor);
rightSchema.accept(validatingVisitor);
}
/**
* @return the differences
*/
public Differences getDifferences()
{
return this.ctx.getDifferences();
return ctx.getDifferences();
}
/**
* @return the validation results.
*/
public List<ValidationResult> getValidationResults()
{
return ctx.getValidationResults();
}
}

View File

@@ -85,10 +85,11 @@ public class SchemaComparatorTest
comparator = new SchemaComparator(left, right, dialect);
comparator.compare();
comparator.validateAndCompare();
dumpDiffs(comparator.getDifferences(), false);
dumpValidation(comparator.getValidationResults());
dumpDiffs(comparator.getDifferences(), true);
Iterator<Result> it = comparator.getDifferences().iterator();
assertHasDifference("left_schema", "left_schema", "right_schema", it.next()); // schema names
@@ -136,6 +137,16 @@ public class SchemaComparatorTest
}
private void dumpValidation(List<ValidationResult> validationResults)
{
System.out.println("Validation Results (" + validationResults.size() + ")");
for (ValidationResult r : validationResults)
{
System.out.println(r);
}
}
@Test
public void canReportWarnings()
{
@@ -149,10 +160,11 @@ public class SchemaComparatorTest
comparator = new SchemaComparator(left, right, dialect);
comparator.compare();
comparator.validateAndCompare();
dumpDiffs(comparator.getDifferences(), true);
dumpValidation(comparator.getValidationResults());
Iterator<Result> it = comparator.getDifferences().iterator();
assertHasDifference("left_schema", "left_schema", "right_schema", it.next());
assertNoDifference("left_schema.tbl_example", "tbl_example", it.next());
@@ -233,9 +245,7 @@ public class SchemaComparatorTest
assertEquals(value, result.getRight());
}
/**
* @param differences
*/
private void dumpDiffs(Differences differences, boolean showNonDifferences)
{
System.out.println("Differences (" + differences.size() + ")");

View File

@@ -0,0 +1,62 @@
/*
* 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;
import org.alfresco.util.schemacomp.model.DbObject;
import org.alfresco.util.schemacomp.model.Index;
import org.alfresco.util.schemacomp.validator.DbValidator;
import org.alfresco.util.schemacomp.validator.NameValidator;
import org.alfresco.util.schemacomp.validator.NullValidator;
/**
* Invokes the correct validator for a given DbObject.
*
* @author Matt Ward
*/
public class ValidatingVisitor implements DbObjectVisitor
{
private DiffContext ctx;
protected NameValidator indexNameValidator = new NameValidator();
protected NullValidator nullValidator = new NullValidator();
public ValidatingVisitor(DiffContext ctx)
{
this.ctx = ctx;
}
protected DbValidator getValidatorFor(Class<? extends DbObject> c)
{
if (c.equals(Index.class))
{
return indexNameValidator;
}
else
{
return nullValidator;
}
}
@Override
public void visit(DbObject dbObject)
{
DbValidator validator = getValidatorFor(dbObject.getClass());
validator.validate(dbObject, ctx);
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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;
import java.util.ArrayList;
import java.util.Collections;
import javax.faces.validator.Validator;
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.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.alfresco.util.schemacomp.validator.NullValidator;
import org.hibernate.dialect.MySQL5InnoDBDialect;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import static org.junit.Assert.*;
import static org.mockito.Mockito.validateMockitoUsage;
/**
* TODO: comment me!
* @author Matt Ward
*/
public class ValidatingVisitorTest
{
private DiffContext ctx;
private ValidatingVisitor visitor;
@Before
public void setUp() throws Exception
{
ctx = new DiffContext(new MySQL5InnoDBDialect(), new Differences(), new ArrayList<ValidationResult>());
visitor = new ValidatingVisitor(ctx);
}
@Test
public void canGetCorrectValidator()
{
// Get references to the validator instances to test for
DbValidator nullValidator = visitor.nullValidator;
DbValidator nameValidator = visitor.indexNameValidator;
assertSame(nullValidator, visitor.getValidatorFor(Column.class));
assertSame(nullValidator, visitor.getValidatorFor(ForeignKey.class));
assertSame(nameValidator, visitor.getValidatorFor(Index.class));
assertSame(nullValidator, visitor.getValidatorFor(PrimaryKey.class));
assertSame(nullValidator, visitor.getValidatorFor(Schema.class));
assertSame(nullValidator, visitor.getValidatorFor(Sequence.class));
assertSame(nullValidator, visitor.getValidatorFor(Table.class));
}
@Test
public void canValidate()
{
visitor.indexNameValidator = Mockito.mock(NameValidator.class);
Index index = new Index("index_name", new ArrayList<String>());
visitor.visit(index);
Mockito.verify(visitor.indexNameValidator).validate(index, ctx);
}
}

View File

@@ -0,0 +1,44 @@
/*
* 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;
/**
* TODO: comment me!
* @author Matt Ward
*/
public class ValidationResult
{
private Object value;
/**
* @param value
*/
public ValidationResult(Object value)
{
this.value = value;
}
/**
* @return the value
*/
public Object getValue()
{
return this.value;
}
}

View File

@@ -18,7 +18,12 @@
*/
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.DbObjectVisitor;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.Differences;
import org.alfresco.util.schemacomp.Result.Strength;

View File

@@ -23,10 +23,14 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.inOrder;
import java.util.ArrayList;
import org.alfresco.util.schemacomp.DbObjectVisitor;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.Differences;
import org.alfresco.util.schemacomp.Result.Strength;
import org.alfresco.util.schemacomp.Result.Where;
import org.alfresco.util.schemacomp.ValidationResult;
import org.hibernate.dialect.Dialect;
import org.junit.Before;
import org.junit.Test;
@@ -55,7 +59,7 @@ public class AbstractDbObjectTest
public void setUp() throws Exception
{
dbObject = new ConcreteDbObject("the_object");
ctx = new DiffContext(dialect, differences);
ctx = new DiffContext(dialect, differences, new ArrayList<ValidationResult>());
}
@Test
@@ -116,5 +120,10 @@ public class AbstractDbObjectTest
Differences differences = ctx.getDifferences();
differences.add(Where.IN_BOTH_BUT_DIFFERENCE, "left", "right");
}
@Override
public void accept(DbObjectVisitor visitor)
{
}
}
}

View File

@@ -18,6 +18,7 @@
*/
package org.alfresco.util.schemacomp.model;
import org.alfresco.util.schemacomp.DbObjectVisitor;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.Differences;
import org.alfresco.util.schemacomp.Result.Strength;
@@ -113,4 +114,10 @@ public class Column extends AbstractDbObject
comparisonUtils.compareSimple(type, rightColumn.type, ctx);
comparisonUtils.compareSimple(nullable, rightColumn.nullable, ctx);
}
@Override
public void accept(DbObjectVisitor visitor)
{
visitor.visit(this);
}
}

View File

@@ -20,6 +20,8 @@ package org.alfresco.util.schemacomp.model;
import org.junit.Before;
import org.junit.Test;
import static org.mockito.Mockito.*;
/**
* Tests for the Column class.
@@ -56,5 +58,13 @@ public class ColumnTest extends DbObjectTestBase<Column>
inOrder.verify(comparisonUtils).compareSimple(thisColumn.getType(), thatColumn.getType(), ctx);
inOrder.verify(comparisonUtils).compareSimple(thisColumn.isNullable(), thatColumn.isNullable(), ctx);
}
@Test
public void acceptVisitor()
{
thisColumn.accept(visitor);
verify(visitor).visit(thisColumn);
}
}

View File

@@ -18,6 +18,7 @@
*/
package org.alfresco.util.schemacomp.model;
import org.alfresco.util.schemacomp.DbObjectVisitor;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.Differences;
import org.alfresco.util.schemacomp.Result.Strength;
@@ -60,4 +61,13 @@ public interface DbObject
* @param ctx The DiffContext
*/
void diff(DbObject right, DiffContext ctx, Strength strength);
/**
* Allows a visitor to be invoked against this DbObject. Implementations should ensure that child
* objects are visited first (by calling accept on them) before invoking the visitor on itself.
*
* @param visitor
*/
void accept(DbObjectVisitor visitor);
}

View File

@@ -18,15 +18,17 @@
*/
package org.alfresco.util.schemacomp.model;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.*;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.util.schemacomp.ComparisonUtils;
import org.alfresco.util.schemacomp.DbObjectVisitor;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.Differences;
import org.alfresco.util.schemacomp.Result.Strength;
import org.alfresco.util.schemacomp.ValidationResult;
import org.hibernate.dialect.Dialect;
import org.junit.Before;
import org.junit.Test;
@@ -50,14 +52,15 @@ public abstract class DbObjectTestBase<T extends AbstractDbObject>
protected InOrder inOrder;
protected abstract T getThisObject();
protected abstract T getThatObject();
protected @Mock DbObjectVisitor visitor;
@Before
public void baseSetUp()
public final void baseSetUp()
{
// Check that the correct calls happened in the correct order.
List<Object> mocks = getMocksUsedInDiff();
inOrder = inOrder(mocks.toArray());
ctx = new DiffContext(dialect, differences);
ctx = new DiffContext(dialect, differences, new ArrayList<ValidationResult>());
}

View File

@@ -18,6 +18,7 @@
*/
package org.alfresco.util.schemacomp.model;
import org.alfresco.util.schemacomp.DbObjectVisitor;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.Differences;
import org.alfresco.util.schemacomp.Result.Strength;
@@ -145,5 +146,11 @@ public class ForeignKey extends AbstractDbObject
comparisonUtils.compareSimple(localColumn, rightFK.localColumn, ctx);
comparisonUtils.compareSimple(targetTable, rightFK.targetTable, ctx);
comparisonUtils.compareSimple(targetColumn, rightFK.targetColumn, ctx);
}
@Override
public void accept(DbObjectVisitor visitor)
{
visitor.visit(this);
}
}

View File

@@ -19,7 +19,10 @@
package org.alfresco.util.schemacomp.model;
import static org.mockito.Mockito.verify;
import org.junit.Before;
import org.junit.Test;
/**
* Tests for the ForeignKey class.
@@ -60,4 +63,12 @@ public class ForeignKeyTest extends DbObjectTestBase<ForeignKey>
inOrder.verify(comparisonUtils).compareSimple(thisFK.getTargetTable(), thatFK.getTargetTable(), ctx);
inOrder.verify(comparisonUtils).compareSimple(thisFK.getTargetColumn(), thatFK.getTargetColumn(), ctx);
}
@Test
public void acceptVisitor()
{
thisFK.accept(visitor);
verify(visitor).visit(thisFK);
}
}

View File

@@ -20,6 +20,7 @@ package org.alfresco.util.schemacomp.model;
import java.util.List;
import org.alfresco.util.schemacomp.DbObjectVisitor;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.Differences;
import org.alfresco.util.schemacomp.Result.Strength;
@@ -115,4 +116,17 @@ public class Index extends AbstractDbObject
Index rightIndex = (Index) right;
comparisonUtils.compareSimpleCollections(columnNames, rightIndex.columnNames, ctx, strength);
}
public void validate(DiffContext ctx)
{
System.out.println("INVALID INDEX, name is not allowed:" + getName());
}
@Override
public void accept(DbObjectVisitor visitor)
{
visitor.visit(this);
}
}

View File

@@ -24,6 +24,7 @@ import org.alfresco.util.schemacomp.Result.Strength;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.verify;
/**
@@ -90,4 +91,13 @@ public class IndexTest extends DbObjectTestBase<Index>
assertFalse("Indexes should be identified different (different name & different columns)",
thisIndex.sameAs(new Index("different_name", Arrays.asList("node_ref", "url"))));
}
@Test
public void acceptVisitor()
{
thisIndex.accept(visitor);
verify(visitor).visit(thisIndex);
}
}

View File

@@ -20,6 +20,7 @@ package org.alfresco.util.schemacomp.model;
import java.util.List;
import org.alfresco.util.schemacomp.DbObjectVisitor;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.Differences;
import org.alfresco.util.schemacomp.Result.Strength;
@@ -92,4 +93,10 @@ public class PrimaryKey extends AbstractDbObject
PrimaryKey rightPK = (PrimaryKey) right;
comparisonUtils.compareSimpleCollections(columnNames, rightPK.columnNames, ctx, strength);
}
@Override
public void accept(DbObjectVisitor visitor)
{
visitor.visit(this);
}
}

View File

@@ -18,10 +18,13 @@
*/
package org.alfresco.util.schemacomp.model;
import static org.mockito.Mockito.verify;
import java.util.Arrays;
import org.alfresco.util.schemacomp.Result.Strength;
import org.junit.Before;
import org.junit.Test;
/**
@@ -63,4 +66,11 @@ public class PrimaryKeyTest extends DbObjectTestBase<PrimaryKey>
Strength.ERROR);
}
@Test
public void acceptVisitor()
{
thisPK.accept(visitor);
verify(visitor).visit(thisPK);
}
}

View File

@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.alfresco.util.schemacomp.DbObjectVisitor;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.Differences;
import org.alfresco.util.schemacomp.Result.Strength;
@@ -97,4 +98,16 @@ public class Schema extends AbstractDbObject implements Iterable<DbObject>
Schema rightSchema = (Schema) right;
comparisonUtils.compareCollections(objects, rightSchema.objects, ctx);
}
@Override
public void accept(DbObjectVisitor visitor)
{
for (DbObject child : objects)
{
child.accept(visitor);
}
visitor.visit(this);
}
}

View File

@@ -18,8 +18,12 @@
*/
package org.alfresco.util.schemacomp.model;
import static org.mockito.Mockito.verify;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
/**
@@ -59,4 +63,22 @@ public class SchemaTest extends DbObjectTestBase<Schema>
// the DbObjects held in the other schema with its own DbObjects.
inOrder.verify(comparisonUtils).compareCollections(left.objects, right.objects, ctx);
}
@Test
public void acceptVisitor()
{
DbObject dbo1 = Mockito.mock(DbObject.class);
left.add(dbo1);
DbObject dbo2 = Mockito.mock(DbObject.class);
left.add(dbo2);
DbObject dbo3 = Mockito.mock(DbObject.class);
left.add(dbo3);
left.accept(visitor);
verify(dbo1).accept(visitor);
verify(dbo2).accept(visitor);
verify(dbo3).accept(visitor);
verify(visitor).visit(left);
}
}

View File

@@ -18,6 +18,8 @@
*/
package org.alfresco.util.schemacomp.model;
import org.alfresco.util.schemacomp.DbObjectVisitor;
/**
* Represents a database sequence.
@@ -26,5 +28,14 @@ package org.alfresco.util.schemacomp.model;
*/
public class Sequence extends AbstractDbObject
{
// No subclass specific data/behaviour at present.
public Sequence(String name)
{
super(name);
}
@Override
public void accept(DbObjectVisitor visitor)
{
visitor.visit(this);
}
}

View File

@@ -18,6 +18,9 @@
*/
package org.alfresco.util.schemacomp.model;
import static org.mockito.Mockito.verify;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@@ -25,12 +28,41 @@ import org.junit.Test;
* Tests for the Sequence class.
* @author Matt Ward
*/
public class SequenceTest
public class SequenceTest extends DbObjectTestBase<Sequence>
{
@Ignore
@Test
public void noTestsRequired()
private Sequence thisSequence;
private Sequence thatSequence;
@Before
public void setUp()
{
// No functionality over and above AbstractDbObject at present.
thisSequence = new Sequence("this_sequence");
thatSequence = new Sequence("that_sequence");
}
@Test
public void acceptVisitor()
{
thisSequence.accept(visitor);
verify(visitor).visit(thisSequence);
}
@Override
protected Sequence getThisObject()
{
return thisSequence;
}
@Override
protected Sequence getThatObject()
{
return thatSequence;
}
@Override
protected void doDiffTests()
{
// Nothing extra to diff.
}
}

View File

@@ -22,6 +22,7 @@ import java.util.ArrayList;
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.Differences;
import org.alfresco.util.schemacomp.Result.Strength;
@@ -185,4 +186,27 @@ public class Table extends AbstractDbObject
comparisonUtils.compareCollections(foreignKeys, rightTable.foreignKeys, ctx);
comparisonUtils.compareCollections(indexes, rightTable.indexes, ctx);
}
private List<DbObject> getChildren()
{
List<DbObject> children = new ArrayList<DbObject>();
children.addAll(columns);
children.add(primaryKey);
children.addAll(foreignKeys);
children.addAll(indexes);
return children;
}
@Override
public void accept(DbObjectVisitor visitor)
{
for (DbObject child : getChildren())
{
child.accept(visitor);
}
visitor.visit(this);
}
}

View File

@@ -20,14 +20,21 @@ package org.alfresco.util.schemacomp.model;
import static java.util.Arrays.asList;
import static org.mockito.Mockito.verify;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.alfresco.util.schemacomp.Result.Strength;
import org.apache.poi.ss.formula.functions.Columns;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
/**
@@ -40,16 +47,16 @@ public class TableTest extends DbObjectTestBase<Table>
{
private Table table;
private Table otherTable;
private Collection<Column> columns;
private List<Column> columns;
private @Mock PrimaryKey primaryKey;
private Collection<ForeignKey> foreignKeys;
private Collection<Index> indexes;
private List<ForeignKey> foreignKeys;
private List<Index> indexes;
@Before
public void setUp() throws Exception
{
columns = asList(
/*columns = asList(
new Column("columnA", "VARCHAR2(50)", false),
new Column("columnB", "VARCHAR2(100)", false),
new Column("columnC", "VARCHAR2(200)", true));
@@ -58,11 +65,31 @@ public class TableTest extends DbObjectTestBase<Table>
indexes = asList(new Index("an_index", asList("columnA", "columnC")));
table = new Table("the_table", columns, primaryKey, foreignKeys, indexes);
otherTable = new Table("the_other_table", columns, primaryKey, foreignKeys, indexes);*/
columns = listOfMocks(Column.class, 3);
foreignKeys = listOfMocks(ForeignKey.class, 1);
indexes = listOfMocks(Index.class, 1);
table = new Table("the_table", columns, primaryKey, foreignKeys, indexes);
otherTable = new Table("the_other_table", columns, primaryKey, foreignKeys, indexes);
}
private <T> List<T> listOfMocks(Class<T> c, int size)
{
List<T> list = new ArrayList<T>(size);
for (int i = 0; i < size; i++)
{
list.add((T) Mockito.mock(c));
}
return list;
}
@Override
protected List<Object> getMocksUsedInDiff()
{
@@ -99,4 +126,31 @@ public class TableTest extends DbObjectTestBase<Table>
{
return otherTable;
}
@Test
public void acceptVisitor()
{
table.setColumns(columns);
table.setForeignKeys(foreignKeys);
table.setIndexes(indexes);
table.setPrimaryKey(primaryKey);
table.accept(visitor);
// All the children should be visited
List<DbObject> children = new ArrayList<DbObject>();
children.addAll(columns);
children.addAll(foreignKeys);
children.addAll(indexes);
children.add(primaryKey);
for (DbObject child : children)
{
verify(child).accept(visitor);
}
// The parent itself should be visited
verify(visitor).visit(table);
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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 org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.model.DbObject;
/**
* TODO: comment me!
* @author Matt Ward
*/
public interface DbValidator
{
void validate(DbObject dbo, DiffContext ctx);
}

View File

@@ -0,0 +1,85 @@
/*
* 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.regex.Pattern;
import org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.ValidationResult;
import org.alfresco.util.schemacomp.model.DbObject;
import org.hibernate.dialect.Dialect;
/**
* Validates the name of a DbObject using a regular expression. A regular expression
* can be supplied for each supported {@link Dialect database dialect}. In addition to
* dialect specific regular expressions, a default may be supplied - comparisons will fall
* back to the default if no specific dialect is matched.
*
* @author Matt Ward
*/
public class NameValidator implements DbValidator
{
private Map<Class<? extends Dialect>, Pattern> namePatterns = new HashMap<Class<? extends Dialect>, Pattern>();
private Pattern defaultNamePattern;
@Override
public void validate(DbObject dbo, DiffContext ctx)
{
String name = dbo.getName();
Pattern pattern = namePatterns.get(ctx.getDialect().getClass());
ValidationResult result = new ValidationResult(name);
if (pattern != null && !pattern.matcher(name).matches())
{
ctx.getValidationResults().add(result);
}
else if (defaultNamePattern != null && !defaultNamePattern.matcher(name).matches())
{
ctx.getValidationResults().add(result);
}
}
/**
* Specify the set of mappings of database dialect to acceptable name patterns.
*
* @param namePatterns
*/
public void setNamePatterns(Map<Class<? extends Dialect>, Pattern> namePatterns)
{
this.namePatterns = namePatterns;
}
/**
* If during validation, there is no specific name validation pattern for the supplied {@link Dialect}
* then the defaultNamePattern property will be used - if not null.
* <p>
* If defaultNamePattern is null then a validation failure will be produced.
*
* @param defaultNamePattern
*/
public void setDefaultNamePattern(Pattern defaultNamePattern)
{
this.defaultNamePattern = defaultNamePattern;
}
}

View File

@@ -0,0 +1,93 @@
/*
* 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.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;
import org.alfresco.util.schemacomp.Differences;
import org.alfresco.util.schemacomp.ValidationResult;
import org.alfresco.util.schemacomp.model.DbObject;
import org.alfresco.util.schemacomp.model.Index;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.Oracle10gDialect;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Tests for the NameValidator class.
*
* @author Matt Ward
*/
public class NameValidatorTest
{
private NameValidator validator;
private DiffContext ctx;
private List<ValidationResult> validationResults;
@Before
public void setUp() throws Exception
{
validator = new NameValidator();
validationResults = new ArrayList<ValidationResult>();
ctx = new DiffContext(new Oracle10gDialect(), new Differences(), validationResults);
}
@Test
public void canSpecifyDefaultRequiredPattern()
{
validator.setDefaultNamePattern(Pattern.compile("SYS_[A-Z_]+"));
validator.validate(indexForName("SYS_MYINDEX"), ctx);
validator.validate(indexForName("SYS_"), ctx);
validator.validate(indexForName("SYS_MY_INDEX"), ctx);
validator.validate(indexForName("MY_INDEX"), ctx);
assertEquals(2, validationResults.size());
assertEquals("SYS_", validationResults.get(0).getValue());
assertEquals("MY_INDEX", validationResults.get(1).getValue());
}
@Test
public void canValidateAgainstPatternForDialect()
{
Map<Class<? extends Dialect>, Pattern> patterns = new HashMap<Class<? extends Dialect>, Pattern>();
patterns.put(Oracle10gDialect.class, Pattern.compile("ORA_[A-Z_]+"));
validator.setNamePatterns(patterns);
validator.validate(indexForName("ORA_MYINDEX"), ctx);
validator.validate(indexForName("SYS_MYINDEX"), ctx);
assertEquals(1, validationResults.size());
assertEquals("SYS_MYINDEX", validationResults.get(0).getValue());
}
private DbObject indexForName(String name)
{
return new Index(name, new ArrayList<String>());
}
}

View File

@@ -0,0 +1,35 @@
/*
* 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 org.alfresco.util.schemacomp.DiffContext;
import org.alfresco.util.schemacomp.model.DbObject;
/**
* TODO: comment me!
* @author Matt Ward
*/
public class NullValidator implements DbValidator
{
@Override
public void validate(DbObject dbo, DiffContext ctx)
{
// Do nothing
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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 org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses(
{
NameValidatorTest.class
})
public class ValidatorTestSuite
{
}