ALF-11518 and ALF-11519: unify separate validation/differences lists and move text generation to Result classes.

ALF-11518: Unify differences and validation results lists
ALF-11519: Move validation/diff result text generation from SchemaBootstrap to result classes.



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@32110 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Matt Ward 2011-11-18 18:20:53 +00:00
parent 50ad2d600c
commit 29dadc748a
25 changed files with 554 additions and 167 deletions

View File

@ -74,6 +74,7 @@ import org.alfresco.util.LogUtil;
import org.alfresco.util.TempFileProvider;
import org.alfresco.util.schemacomp.Difference;
import org.alfresco.util.schemacomp.ExportDb;
import org.alfresco.util.schemacomp.Result;
import org.alfresco.util.schemacomp.Results;
import org.alfresco.util.schemacomp.SchemaComparator;
import org.alfresco.util.schemacomp.ValidationResult;
@ -104,8 +105,6 @@ import org.hibernate.engine.ActionQueue;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.core.Conventions;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
@ -1666,8 +1665,7 @@ public class SchemaBootstrap extends AbstractLifecycleBean
schemaComparator.validateAndCompare();
Results differences = schemaComparator.getDifferences();
List<ValidationResult> validationResults = schemaComparator.getValidationResults();
Results results = schemaComparator.getComparisonResults();
String outputFileName = MessageFormat.format(
outputFileNameTemplate,
@ -1675,8 +1673,6 @@ public class SchemaBootstrap extends AbstractLifecycleBean
File outputFile = TempFileProvider.createTempFile(outputFileName, ".txt");
PrintWriter pw = null;
try
{
@ -1687,66 +1683,21 @@ public class SchemaBootstrap extends AbstractLifecycleBean
throw new RuntimeException("Unable to open file for writing: " + outputFile);
}
for (Difference difference : differences)
// Populate the file with details of the comparison's results.
for (Result result : results)
{
StringBuffer sb = new StringBuffer();
sb.append(difference.getStrength())
.append(" (diff): ")
.append(difference.getWhere());
sb.append(" reference path:");
if (difference.getLeft() != null)
{
sb.append(difference.getLeft().getPath());
sb.append(" (value: ")
.append(difference.getLeft().getPropertyValue())
.append(")");
}
else
{
sb.append("null");
}
sb.append(" target path:");
if (difference.getRight() != null)
{
sb.append(difference.getRight().getPath());
sb.append(" (value: ")
.append(difference.getRight().getPropertyValue())
.append(")");
}
else
{
sb.append("null");
}
pw.println(sb);
pw.println(result.describe());
}
for (ValidationResult validationResult : validationResults)
{
StringBuffer sb = new StringBuffer();
sb.append(validationResult.getStrength())
.append(" (validation): ")
.append("target path:")
.append(validationResult.getDbProperty().getPath())
.append(" (value: ")
.append(validationResult.getValue())
.append(")");
pw.println(sb);
}
pw.close();
if (validationResults.size() == 0 && differences.size() == 0)
if (results.size() == 0)
{
logger.info("Compared database schema with reference schema (all OK): " + referenceResource);
}
else
{
int numProblems = validationResults.size() + differences.size();
int numProblems = results.size();
logger.warn("Schema validation found " + numProblems +
" potential problems, results written to: "
+ outputFile);

View File

@ -81,7 +81,7 @@ public class DefaultComparisonUtils implements ComparisonUtils
ArrayList<? extends Object> leftList = new ArrayList<Object>(leftCollection);
ArrayList<? extends Object> rightList = new ArrayList<Object>(rightCollection);
Results differences = ctx.getDifferences();
Results differences = ctx.getComparisonResults();
for (int leftIndex = 0; leftIndex < leftList.size(); leftIndex++)
{
@ -144,7 +144,7 @@ public class DefaultComparisonUtils implements ComparisonUtils
public void compareCollections(Collection<? extends DbObject> leftCollection,
Collection<? extends DbObject> rightCollection, DiffContext ctx, Strength strength)
{
Results differences = ctx.getDifferences();
Results differences = ctx.getComparisonResults();
for (DbObject leftObj : leftCollection)
{
DbObject rightObj = findSameObjectAs(rightCollection, leftObj);
@ -234,7 +234,7 @@ public class DefaultComparisonUtils implements ComparisonUtils
}
}
ctx.getDifferences().add(where, leftProperty, rightProperty, strength);
ctx.getComparisonResults().add(where, leftProperty, rightProperty, strength);
}

View File

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

View File

@ -18,8 +18,6 @@
*/
package org.alfresco.util.schemacomp;
import java.util.List;
import org.alfresco.util.schemacomp.model.Schema;
import org.hibernate.dialect.Dialect;
@ -33,25 +31,39 @@ import org.hibernate.dialect.Dialect;
public class DiffContext
{
private final Dialect dialect;
private final Results differences;
private final List<ValidationResult> validationResults;
private final Results results;
private final Schema referenceSchema;
private final Schema targetSchema;
/**
* Constructor.
*
* @param dialect
* @param differences
* @param results
* @param referenceSchema
* @param targetSchema
*/
public DiffContext(Dialect dialect, Results differences, List<ValidationResult> validationResults,
Schema referenceSchema, Schema targetSchema)
public DiffContext(Dialect dialect, Results results, Schema referenceSchema, Schema targetSchema)
{
this.dialect = dialect;
this.differences = differences;
this.validationResults = validationResults;
this.results = results;
this.referenceSchema = referenceSchema;
this.targetSchema = targetSchema;
}
/**
* Constructor.
*
* @param dialect
* @param referenceSchema
* @param targetSchema
*/
public DiffContext(Dialect dialect, Schema referenceSchema, Schema targetSchema)
{
this(dialect, new Results(), referenceSchema, targetSchema);
}
/**
* @return the dialect
*/
@ -61,19 +73,11 @@ public class DiffContext
}
/**
* @return the differences
* @return the results of schema comparison: validation failures, differences etc.
*/
public Results getDifferences()
public Results getComparisonResults()
{
return this.differences;
}
/**
* @return the validationResults
*/
public List<ValidationResult> getValidationResults()
{
return this.validationResults;
return this.results;
}
/**

View File

@ -71,6 +71,43 @@ public final class Difference extends Result
return this.right;
}
@Override
public String describe()
{
StringBuffer sb = new StringBuffer();
sb.append("Difference: ")
.append(getWhere());
sb.append(" reference path:");
if (getLeft() != null)
{
sb.append(getLeft().getPath());
sb.append(" (value: ")
.append(getLeft().getPropertyValue())
.append(")");
}
else
{
sb.append("null");
}
sb.append(" target path:");
if (getRight() != null)
{
sb.append(getRight().getPath());
sb.append(" (value: ")
.append(getRight().getPropertyValue())
.append(")");
}
else
{
sb.append("null");
}
return sb.toString();
}
@Override
public String toString()
{

View File

@ -0,0 +1,51 @@
/*
* 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 static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.alfresco.util.schemacomp.Difference.Where;
import org.junit.Test;
/**
* Tests for the {@link Difference} class.
*
* @author Matt Ward
*/
public class DifferenceTest
{
@Test
public void describe()
{
DbProperty refDbProp = mock(DbProperty.class);
when(refDbProp.getPath()).thenReturn("alfresco.some_table.some_column.name");
when(refDbProp.getPropertyValue()).thenReturn("node_ref");
DbProperty targetDbProp = mock(DbProperty.class);
when(targetDbProp.getPath()).thenReturn("alfresco.some_table.some_column.name");
when(targetDbProp.getPropertyValue()).thenReturn("nood_ref");
Difference diff = new Difference(Where.ONLY_IN_LEFT, refDbProp, targetDbProp);
assertEquals("Difference: ONLY_IN_LEFT reference path:alfresco.some_table.some_column.name (value: node_ref) " +
"target path:alfresco.some_table.some_column.name (value: nood_ref)", diff.describe());
}
}

View File

@ -0,0 +1,76 @@
/*
* 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.List;
import org.alfresco.util.schemacomp.model.DbObject;
/**
* If more than one DB item in the target schema matches a reference DB item
* then this result will be issued.
*
* @author Matt Ward
*/
public class RedundantDbObject extends Result
{
private final static int SHOW_MAX_MATCHES = 3;
private DbObject dbObject;
private List<DbObject> matches;
public RedundantDbObject(DbObject dbObject, List<DbObject> matches)
{
super(null);
this.dbObject = dbObject;
this.matches = matches;
}
@Override
public String describe()
{
StringBuffer sb = new StringBuffer();
sb.append(matches.size())
.append(" redundant items? reference: ")
.append(dbObject)
.append(", matches: ");
for (int i = 0; i < matches.size() && i < SHOW_MAX_MATCHES; i++)
{
if (i > 0)
{
sb.append(", ");
}
sb.append(matches.get(i));
}
if (matches.size() > SHOW_MAX_MATCHES)
{
sb.append(" and ")
.append(matches.size() - SHOW_MAX_MATCHES).append(" more...");
}
return sb.toString();
}
@Override
public String toString()
{
return "RedundantDbObject [dbObject=" + this.dbObject + ", matches=" + this.matches + "]";
}
}

View File

@ -0,0 +1,91 @@
/*
* 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 static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.util.schemacomp.model.AbstractDbObject;
import org.alfresco.util.schemacomp.model.DbObject;
import org.junit.Test;
/**
* Tests for the {@link RedundantDbObject} class.
*
* @author Matt Ward
*/
public class RedundantDbObjectTest
{
@Test
public void describe()
{
DbObject reference = new MyDbObject("reference");
List<DbObject> matches = makeMatches(3);
RedundantDbObject redundantDBO = new RedundantDbObject(reference, matches);
assertEquals("3 redundant items? reference: MyDbObject[name=reference], " +
"matches: MyDbObject[name=match1], MyDbObject[name=match2], MyDbObject[name=match3]",
redundantDBO.describe());
}
@Test
public void describeTooManyMatches()
{
DbObject reference = new MyDbObject("reference");
List<DbObject> matches = makeMatches(4);
RedundantDbObject redundantDBO = new RedundantDbObject(reference, matches);
assertEquals("4 redundant items? reference: MyDbObject[name=reference], " +
"matches: MyDbObject[name=match1], MyDbObject[name=match2], MyDbObject[name=match3] and 1 more...",
redundantDBO.describe());
}
/**
* @return
*/
private List<DbObject> makeMatches(int numMatches)
{
List<DbObject> matches = new ArrayList<DbObject>();
for (int i = 0; i < numMatches; i++)
{
matches.add(new MyDbObject("match" + (i+1)));
}
return matches;
}
private static class MyDbObject extends AbstractDbObject
{
public MyDbObject(String name)
{
super(null, name);
}
@Override
public void accept(DbObjectVisitor visitor)
{
}
}
}

View File

@ -23,7 +23,7 @@ package org.alfresco.util.schemacomp;
*
* @author Matt Ward
*/
public class Result
public abstract class Result
{
public enum Strength { WARN, ERROR };
protected final Strength strength;
@ -43,4 +43,16 @@ public class Result
{
return this.strength;
}
/**
* A loggable message to describe the comparison result. Default implementation
* delegates to toString() but this should generally be overridden as toString()
* is used in a multitude of contexts.
*
* @return
*/
public String describe()
{
return toString();
}
}

View File

@ -30,9 +30,9 @@ import org.alfresco.util.schemacomp.Result.Strength;
*
* @author Matt Ward
*/
public class Results implements Iterable<Difference>
public class Results implements Iterable<Result>
{
private final List<Difference> items = new ArrayList<Difference>();
private final List<Result> items = new ArrayList<Result>();
/** Temporary step during refactor - Where.IN_BOTH_NO_DIFFERENCE will be going altogether */
private boolean reportNonDifferences = false;
@ -62,16 +62,32 @@ public class Results implements Iterable<Difference>
}
public void add(Result result)
{
items.add(result);
}
/**
* Obtain an iterator for the top-level items held in this schema - since this is a hierarchical model,
* deeper items are obtained by navigating through the top-level items.
*/
@Override
public Iterator<Difference> iterator()
public Iterator<Result> iterator()
{
return items.iterator();
}
/**
* Get the ith result.
*
* @param i
* @return Result
*/
public Result get(int i)
{
return items.get(i);
}
/**
* @return How many top-level items are in the schema.
*/

View File

@ -33,8 +33,11 @@ import org.junit.runners.Suite;
DbPropertyTest.class,
DbToXMLTest.class,
DefaultComparisonUtilsTest.class,
DifferenceTest.class,
ExportDbTest.class,
RedundantDbObjectTest.class,
SchemaComparatorTest.class,
ValidationResultTest.class,
ValidatingVisitorTest.class,
SchemaToXMLTest.class,
XMLToSchemaTest.class

View File

@ -36,23 +36,30 @@ import org.apache.commons.lang.ArrayUtils;
public class SchemaCompTestingUtils
{
public static void dumpValidation(List<ValidationResult> validationResults)
public static void dumpValidation(Results results)
{
System.out.println("Validation Results (" + validationResults.size() + ")");
for (ValidationResult r : validationResults)
System.out.println("Validation Results (" + results.size() + ")");
for (Result r : results)
{
System.out.println(r);
if (r instanceof ValidationResult)
{
System.out.println(r);
}
}
}
public static void dumpDiffs(Results differences, boolean showNonDifferences)
{
System.out.println("Differences (" + differences.size() + ")");
for (Difference d : differences)
for (Result d : differences)
{
if (d.getWhere() != Where.IN_BOTH_NO_DIFFERENCE || showNonDifferences)
if (d instanceof Difference)
{
System.out.println(d);
Difference diff = (Difference) d;
if (diff.getWhere() != Where.IN_BOTH_NO_DIFFERENCE || showNonDifferences)
{
System.out.println(d);
}
}
}
}

View File

@ -18,9 +18,6 @@
*/
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;
@ -48,7 +45,7 @@ public class SchemaComparator
{
this.referenceSchema = referenceSchema;
this.targetSchema = targetSchema;
this.ctx = new DiffContext(dialect, new Results(), new ArrayList<ValidationResult>(), referenceSchema, targetSchema);
this.ctx = new DiffContext(dialect, referenceSchema, targetSchema);
}
@ -79,19 +76,10 @@ public class SchemaComparator
/**
* @return the differences
* @return the schema comparison results.
*/
public Results getDifferences()
public Results getComparisonResults()
{
return ctx.getDifferences();
}
/**
* @return the validation results.
*/
public List<ValidationResult> getValidationResults()
{
return ctx.getValidationResults();
return ctx.getComparisonResults();
}
}

View File

@ -29,7 +29,6 @@ import static org.alfresco.util.schemacomp.SchemaCompTestingUtils.pk;
import static org.alfresco.util.schemacomp.SchemaCompTestingUtils.table;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import java.util.Arrays;
import java.util.Iterator;
@ -57,8 +56,8 @@ public class SchemaComparatorTest
@Before
public void setup()
{
reference = new Schema("reference_schema");
target = new Schema("target_schema");
reference = new Schema("schema");
target = new Schema("schema");
dialect = new MySQL5InnoDBDialect();
}
@ -87,67 +86,55 @@ public class SchemaComparatorTest
comparator.validateAndCompare();
// See stdout for diagnostics dump...
dumpDiffs(comparator.getDifferences(), false);
dumpValidation(comparator.getValidationResults());
dumpDiffs(comparator.getComparisonResults(), false);
dumpValidation(comparator.getComparisonResults());
Results differences = comparator.getDifferences();
Results results = comparator.getComparisonResults();
Iterator<Difference> it = differences.iterator();
// Schema names are different ("reference_schema" vs "target_schema")
Difference diff = it.next();
assertEquals(Where.IN_BOTH_BUT_DIFFERENCE, diff.getWhere());
assertEquals("reference_schema.name", diff.getLeft().getPath());
assertEquals("target_schema.name", diff.getRight().getPath());
assertSame(reference, diff.getLeft().getDbObject());
assertSame(target, diff.getRight().getDbObject());
assertEquals("name", diff.getLeft().getPropertyName());
assertEquals("reference_schema", diff.getLeft().getPropertyValue());
assertEquals("name", diff.getRight().getPropertyName());
assertEquals("target_schema", diff.getRight().getPropertyValue());
Iterator<Result> it = results.iterator();
// Table table_in_reference only appears in the reference schema
diff = it.next();
Difference diff = (Difference) it.next();
assertEquals(Where.ONLY_IN_LEFT, diff.getWhere());
assertEquals("reference_schema.table_in_reference", diff.getLeft().getPath());
assertEquals("schema.table_in_reference", diff.getLeft().getPath());
assertEquals(null, diff.getRight());
assertEquals(null, diff.getLeft().getPropertyName());
assertEquals(null, diff.getLeft().getPropertyValue());
// Table tbl_has_diff_pk has PK of "id" in reference and "nodeRef" in target
diff = it.next();
diff = (Difference) it.next();
assertEquals(Where.ONLY_IN_LEFT, diff.getWhere());
assertEquals("reference_schema.tbl_has_diff_pk.pk_is_diff.columnNames[0]", diff.getLeft().getPath());
assertEquals("target_schema.tbl_has_diff_pk.pk_is_diff.columnNames", diff.getRight().getPath());
assertEquals("schema.tbl_has_diff_pk.pk_is_diff.columnNames[0]", diff.getLeft().getPath());
assertEquals("schema.tbl_has_diff_pk.pk_is_diff.columnNames", diff.getRight().getPath());
assertEquals("columnNames[0]", diff.getLeft().getPropertyName());
assertEquals("id", diff.getLeft().getPropertyValue());
assertEquals("columnNames", diff.getRight().getPropertyName());
assertEquals(Arrays.asList("nodeRef"), diff.getRight().getPropertyValue());
// Table tbl_has_diff_pk has PK of "id" in reference and "nodeRef" in target
diff = it.next();
diff = (Difference) it.next();
assertEquals(Where.ONLY_IN_RIGHT, diff.getWhere());
assertEquals("reference_schema.tbl_has_diff_pk.pk_is_diff.columnNames", diff.getLeft().getPath());
assertEquals("target_schema.tbl_has_diff_pk.pk_is_diff.columnNames[0]", diff.getRight().getPath());
assertEquals("schema.tbl_has_diff_pk.pk_is_diff.columnNames", diff.getLeft().getPath());
assertEquals("schema.tbl_has_diff_pk.pk_is_diff.columnNames[0]", diff.getRight().getPath());
assertEquals("columnNames", diff.getLeft().getPropertyName());
assertEquals(Arrays.asList("id"), diff.getLeft().getPropertyValue());
assertEquals("columnNames[0]", diff.getRight().getPropertyName());
assertEquals("nodeRef", diff.getRight().getPropertyValue());
// idx_two is unique in the righ_schema but not in the reference
diff = it.next();
assertEquals("reference_schema.tbl_has_diff_pk.idx_two.unique", diff.getLeft().getPath());
assertEquals("target_schema.tbl_has_diff_pk.idx_two.unique", diff.getRight().getPath());
diff = (Difference) it.next();
assertEquals("schema.tbl_has_diff_pk.idx_two.unique", diff.getLeft().getPath());
assertEquals("schema.tbl_has_diff_pk.idx_two.unique", diff.getRight().getPath());
assertEquals("unique", diff.getLeft().getPropertyName());
assertEquals(false, diff.getLeft().getPropertyValue());
assertEquals("unique", diff.getRight().getPropertyName());
assertEquals(true, diff.getRight().getPropertyValue());
// Table table_in_target does not exist in the reference schema
diff = it.next();
diff = (Difference) it.next();
assertEquals(Where.ONLY_IN_RIGHT, diff.getWhere());
assertEquals("target_schema.table_in_target", diff.getRight().getPath());
assertEquals("schema.table_in_target", diff.getRight().getPath());
assertEquals(null, diff.getLeft());
assertEquals(null, diff.getRight().getPropertyName());
assertEquals(null, diff.getRight().getPropertyValue());

View File

@ -44,7 +44,10 @@ public class ValidatingVisitor implements DbObjectVisitor
{
List<DbObject> matches = comparisonUtils.findEquivalentObjects(ctx.getTargetSchema(), referenceObj);
// TODO: if matches.size() > 1 then warn of possible redundant database objects
if (matches.size() > 1)
{
ctx.getComparisonResults().add(new RedundantDbObject(referenceObj, matches));
}
// Validate each matching target object against the reference object
// using each of the available validators for that reference object.

View File

@ -31,6 +31,7 @@ import org.alfresco.util.schemacomp.validator.DbValidator;
import org.hibernate.dialect.MySQL5InnoDBDialect;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import org.mockito.Mockito;
/**
@ -59,8 +60,7 @@ public class ValidatingVisitorTest
{
refTable = new Table("reference_table");
refIndex = new Index(refTable, "index_name", Arrays.asList("a", "b", "c"));
ctx = new DiffContext(new MySQL5InnoDBDialect(), new Results(),
new ArrayList<ValidationResult>(), refSchema, targetSchema);
ctx = new DiffContext(new MySQL5InnoDBDialect(), refSchema, targetSchema);
visitor = new ValidatingVisitor(ctx);
validators = new ArrayList<DbValidator>();
@ -97,4 +97,29 @@ public class ValidatingVisitorTest
}
@Test
public void redundantDbObjectsAreNoticed()
{
Mockito.when(comparisonUtils.findEquivalentObjects(refSchema, refIndex)).
thenReturn(Arrays.asList((DbObject) targetIndex1, targetIndex2, targetIndex3));
// Validate all instances of the target schema's indexes that are equivalent to this index
visitor.visit(refIndex);
assertEquals(1, ctx.getComparisonResults().size());
assertEquals(RedundantDbObject.class, ctx.getComparisonResults().get(0).getClass());
}
@Test
public void nonRedundantDbObjectsAreNoticed()
{
Mockito.when(comparisonUtils.findEquivalentObjects(refSchema, refIndex)).
thenReturn(Arrays.asList((DbObject) targetIndex1));
// Validate all instances of the target schema's indexes that are equivalent to this index
visitor.visit(refIndex);
assertEquals(0, ctx.getComparisonResults().size());
}
}

View File

@ -56,6 +56,21 @@ public class ValidationResult extends Result
this.dbProperty = dbProperty;
}
@Override
public String describe()
{
StringBuffer sb = new StringBuffer();
sb.append("Validation ")
.append("target path:")
.append(getDbProperty().getPath())
.append(" (value: ")
.append(getValue())
.append(")");
return sb.toString();
}
/**
* @return the value that was rejected.
*/

View File

@ -0,0 +1,48 @@
/*
* 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 static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
/**
* Tests for the {@link ValidationResult} class.
*
* @author Matt Ward
*/
public class ValidationResultTest
{
@Test
public void describe()
{
DbProperty targetDbProp = mock(DbProperty.class);
when(targetDbProp.getPath()).thenReturn("alfresco.some_table.some_index.name");
when(targetDbProp.getPropertyValue()).thenReturn("ibx_my_index");
ValidationResult validation = new ValidationResult(targetDbProp);
assertEquals("Validation target path:alfresco.some_table.some_index.name (value: ibx_my_index)",
validation.describe());
}
}

View File

@ -96,16 +96,35 @@ public abstract class AbstractDbObject implements DbObject
@Override
public boolean sameAs(DbObject other)
{
if (other == null)
{
return false;
}
if (this == other)
{
return true;
}
if (!this.getClass().equals(other.getClass()))
{
// Objects are not the same type, even if they have the same name and parent
return false;
}
if (getName() != null && other != null && other.getName() != null)
{
return getName().equals(other.getName());
}
else
{
// Only other way we can know if they are the same is if they are
// the exact same object reference.
return this == other;
boolean sameParent = false;
if (getParent() == null && other.getParent() == null)
{
sameParent = true;
}
else if (getParent() != null && getParent().sameAs(other.getParent()))
{
sameParent = true;
}
return sameParent && getName().equals(other.getName());
}
return false;
}
@Override

View File

@ -23,7 +23,6 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.inOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -33,7 +32,6 @@ import org.alfresco.util.schemacomp.DiffContext;
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;
@ -64,7 +62,7 @@ public class AbstractDbObjectTest
public void setUp() throws Exception
{
dbObject = new ConcreteDbObject("the_object");
ctx = new DiffContext(dialect, differences, new ArrayList<ValidationResult>(), null, null);
ctx = new DiffContext(dialect, differences, null, null);
}
@Test
@ -83,7 +81,8 @@ public class AbstractDbObjectTest
dbObject.setName("the_name");
assertFalse("Not the same.", dbObject.sameAs(null));
assertFalse("Not the same.", dbObject.sameAs(new ConcreteDbObject("different_name")));
assertFalse("Not the same.", dbObject.sameAs(new ConcreteDbObject("different_name")));
assertFalse("Not the same type", dbObject.sameAs(new AnotherConcreteDbObject("the_name")));
assertTrue("Logically the same object.", dbObject.sameAs(new ConcreteDbObject("the_name")));
assertTrue("The very same object with non-null name", dbObject.sameAs(dbObject));
}
@ -146,7 +145,7 @@ public class AbstractDbObjectTest
@Override
protected void doDiff(DbObject right, DiffContext ctx, Strength strength)
{
Results differences = ctx.getDifferences();
Results differences = ctx.getComparisonResults();
differences.add(
Where.IN_BOTH_BUT_DIFFERENCE,
new DbProperty(this, "someProp"),
@ -164,6 +163,19 @@ public class AbstractDbObjectTest
}
}
public static class AnotherConcreteDbObject extends AbstractDbObject
{
public AnotherConcreteDbObject(String name)
{
super(null, name);
}
@Override
public void accept(DbObjectVisitor visitor)
{
}
}
private List<DbValidator> validatorList(DbValidator... validators)
{

View File

@ -131,4 +131,28 @@ public class Column extends AbstractDbObject
{
visitor.visit(this);
}
@Override
public boolean sameAs(DbObject other)
{
if (other == null)
{
return false;
}
if (this == other)
{
return true;
}
if (getClass().equals(other.getClass()))
{
if (getName() != null && other.getName() != null)
{
if (getParent() != null && other.getParent() != null && getParent().sameAs(other.getParent()))
{
return getName().equals(other.getName());
}
}
}
return false;
}
}

View File

@ -23,6 +23,7 @@ import org.alfresco.util.schemacomp.DbProperty;
import org.junit.Before;
import org.junit.Test;
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
/**
* Tests for the Column class.
@ -73,5 +74,24 @@ public class ColumnTest extends DbObjectTestBase<Column>
verify(visitor).visit(thisColumn);
}
@Test
public void sameAs()
{
Table thisTable = new Table("the_table");
thisColumn = new Column(thisTable, "this_column", "VARCHAR2(100)", false);
Table thatTable = new Table("the_table");
thatColumn = new Column(thatTable, "this_column", "VARCHAR2(100)", false);
// This column, whilst having the same name as thisColumn, has a different
// parent table - and so is not considered 'the same'.
Table anotherTable = new Table("another_table");
Column anotherColumn = new Column(anotherTable, "this_column", "VARCHAR2(100)", false);
assertTrue("Column should always be the same as itself", thisColumn.sameAs(thisColumn));
assertTrue("Columns should be the same due to same parent table names", thisColumn.sameAs(thatColumn));
assertFalse("Should NOT be the same due to different parent table names", thisColumn.sameAs(anotherColumn));
}
}

View File

@ -18,7 +18,7 @@
*/
package org.alfresco.util.schemacomp.model;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.inOrder;
import java.util.ArrayList;
import java.util.List;
@ -27,9 +27,8 @@ import org.alfresco.util.schemacomp.ComparisonUtils;
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;
import org.alfresco.util.schemacomp.ValidationResult;
import org.alfresco.util.schemacomp.Results;
import org.hibernate.dialect.Dialect;
import org.junit.Before;
import org.junit.Test;
@ -61,7 +60,7 @@ public abstract class DbObjectTestBase<T extends AbstractDbObject>
// Check that the correct calls happened in the correct order.
List<Object> mocks = getMocksUsedInDiff();
inOrder = inOrder(mocks.toArray());
ctx = new DiffContext(dialect, differences, new ArrayList<ValidationResult>(), null, null);
ctx = new DiffContext(dialect, differences, null, null);
}

View File

@ -49,7 +49,7 @@ public class NameValidator implements DbValidator
if (pattern != null && !pattern.matcher(name).matches())
{
ctx.getValidationResults().add(result);
ctx.getComparisonResults().add(result);
}
}

View File

@ -22,7 +22,6 @@ package org.alfresco.util.schemacomp.validator;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.alfresco.util.schemacomp.DiffContext;
@ -43,14 +42,14 @@ public class NameValidatorTest
{
private NameValidator validator;
private DiffContext ctx;
private List<ValidationResult> validationResults;
private Results validationResults;
@Before
public void setUp() throws Exception
{
validator = new NameValidator();
validationResults = new ArrayList<ValidationResult>();
ctx = new DiffContext(new Oracle10gDialect(), new Results(), validationResults, null, null);
validationResults = new Results();
ctx = new DiffContext(new Oracle10gDialect(), validationResults, null, null);
}
@Test
@ -63,8 +62,8 @@ public class NameValidatorTest
validator.validate(null, indexForName("MY_INDEX"), ctx);
assertEquals(2, validationResults.size());
assertEquals("SYS_", validationResults.get(0).getValue());
assertEquals("MY_INDEX", validationResults.get(1).getValue());
assertEquals("SYS_", ((ValidationResult) validationResults.get(0)).getValue());
assertEquals("MY_INDEX", ((ValidationResult) validationResults.get(1)).getValue());
}
@Test
@ -76,7 +75,7 @@ public class NameValidatorTest
validator.validate(null, indexForName("SYS_MYINDEX"), ctx);
assertEquals(1, validationResults.size());
assertEquals("SYS_MYINDEX", validationResults.get(0).getValue());
assertEquals("SYS_MYINDEX", ((ValidationResult) validationResults.get(0)).getValue());
}