mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
ALF-7260: fixed diffs to work against multiple matching db objects
It is possible that multiple database objects, e.g. indexes, match a given object as described in the schema reference file. This fix means that diffs will be provided against all the matching items, where previously only the first matching item was reported against. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@32864 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -33,14 +33,7 @@ import org.alfresco.util.schemacomp.model.Schema;
|
|||||||
*/
|
*/
|
||||||
public interface ComparisonUtils
|
public interface ComparisonUtils
|
||||||
{
|
{
|
||||||
/**
|
List<DbObject> findEquivalentObjects(DbObject rootObject, DbObject objToMatch);
|
||||||
* @deprecated This method ignores the fact that multiple objects may match.
|
|
||||||
* @param objToFind
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
DbObject findSameObjectAs(Collection<? extends DbObject> objects, final DbObject objToFind);
|
|
||||||
|
|
||||||
List<DbObject> findEquivalentObjects(Schema schema, DbObject objToMatch);
|
|
||||||
|
|
||||||
void compareSimpleCollections(DbProperty leftProperty, DbProperty rightProperty,
|
void compareSimpleCollections(DbProperty leftProperty, DbProperty rightProperty,
|
||||||
DiffContext ctx, Strength strength);
|
DiffContext ctx, Strength strength);
|
||||||
|
@@ -37,31 +37,11 @@ import org.apache.commons.collections.Predicate;
|
|||||||
*/
|
*/
|
||||||
public class DefaultComparisonUtils implements ComparisonUtils
|
public class DefaultComparisonUtils implements ComparisonUtils
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @param objToFind
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public DbObject findSameObjectAs(Collection<? extends DbObject> objects, final DbObject objToFind)
|
public List<DbObject> findEquivalentObjects(DbObject rootObject, DbObject objToMatch)
|
||||||
{
|
|
||||||
return (DbObject) CollectionUtils.find(objects, new Predicate()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public boolean evaluate(Object o)
|
|
||||||
{
|
|
||||||
DbObject object = (DbObject) o;
|
|
||||||
return object.sameAs(objToFind);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DbObject> findEquivalentObjects(Schema schema, DbObject objToMatch)
|
|
||||||
{
|
{
|
||||||
EquivalentObjectSeeker objectSeeker = new EquivalentObjectSeeker(objToMatch);
|
EquivalentObjectSeeker objectSeeker = new EquivalentObjectSeeker(objToMatch);
|
||||||
schema.accept(objectSeeker);
|
rootObject.accept(objectSeeker);
|
||||||
|
|
||||||
return objectSeeker.getMatches();
|
return objectSeeker.getMatches();
|
||||||
}
|
}
|
||||||
@@ -147,17 +127,27 @@ public class DefaultComparisonUtils implements ComparisonUtils
|
|||||||
Results differences = ctx.getComparisonResults();
|
Results differences = ctx.getComparisonResults();
|
||||||
for (DbObject leftObj : leftCollection)
|
for (DbObject leftObj : leftCollection)
|
||||||
{
|
{
|
||||||
DbObject rightObj = findSameObjectAs(rightCollection, leftObj);
|
boolean foundMatch = false;
|
||||||
|
|
||||||
if (rightObj != null)
|
for (DbObject rootObject : rightCollection)
|
||||||
{
|
{
|
||||||
// There is an equivalent object in the right hand collection as
|
List<DbObject> matches = findEquivalentObjects(rootObject, leftObj);
|
||||||
// in the left.
|
|
||||||
leftObj.diff(rightObj, ctx, strength);
|
for (DbObject match : matches)
|
||||||
|
{
|
||||||
|
// There is an equivalent object in the right hand collection as in the left.
|
||||||
|
leftObj.diff(match, ctx, strength);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (matches.size() > 0)
|
||||||
{
|
{
|
||||||
// No equivalent object in the right hand collection.
|
foundMatch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundMatch)
|
||||||
|
{
|
||||||
|
// No equivalent object in the target collection.
|
||||||
differences.add(Where.ONLY_IN_REFERENCE, new DbProperty(leftObj, null), null, strength);
|
differences.add(Where.ONLY_IN_REFERENCE, new DbProperty(leftObj, null), null, strength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,9 +155,19 @@ public class DefaultComparisonUtils implements ComparisonUtils
|
|||||||
// Identify objects in the right collection but not the left
|
// Identify objects in the right collection but not the left
|
||||||
for (DbObject rightObj : rightCollection)
|
for (DbObject rightObj : rightCollection)
|
||||||
{
|
{
|
||||||
DbObject leftObj = findSameObjectAs(leftCollection, rightObj);
|
boolean foundMatch = false;
|
||||||
|
|
||||||
if (leftObj == null)
|
for (DbObject rootObject : leftCollection)
|
||||||
|
{
|
||||||
|
List<DbObject> matches = findEquivalentObjects(rootObject, rightObj);
|
||||||
|
if (matches.size() > 0)
|
||||||
|
{
|
||||||
|
foundMatch = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundMatch)
|
||||||
{
|
{
|
||||||
// No equivalent object in the left hand collection.
|
// No equivalent object in the left hand collection.
|
||||||
differences.add(Where.ONLY_IN_TARGET, null, new DbProperty(rightObj, null), strength);
|
differences.add(Where.ONLY_IN_TARGET, null, new DbProperty(rightObj, null), strength);
|
||||||
@@ -251,7 +251,7 @@ public class DefaultComparisonUtils implements ComparisonUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class EquivalentObjectSeeker implements DbObjectVisitor
|
public static class EquivalentObjectSeeker implements DbObjectVisitor
|
||||||
{
|
{
|
||||||
private final List<DbObject> matches = new ArrayList<DbObject>();
|
private final List<DbObject> matches = new ArrayList<DbObject>();
|
||||||
private final DbObject objToMatch;
|
private final DbObject objToMatch;
|
||||||
|
@@ -35,9 +35,11 @@ import org.alfresco.util.schemacomp.Result.Strength;
|
|||||||
import org.alfresco.util.schemacomp.model.AbstractDbObject;
|
import org.alfresco.util.schemacomp.model.AbstractDbObject;
|
||||||
import org.alfresco.util.schemacomp.model.DbObject;
|
import org.alfresco.util.schemacomp.model.DbObject;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
@@ -89,14 +91,11 @@ public class DefaultComparisonUtilsTest
|
|||||||
@Test
|
@Test
|
||||||
public void compareCollections()
|
public void compareCollections()
|
||||||
{
|
{
|
||||||
DbObject db1 = mock(DbObject.class);
|
DbObject db1 = new DatabaseObject("db1");
|
||||||
when(db1.sameAs(db1)).thenReturn(true);
|
DbObject db2 = new DatabaseObject("db2"); // only in left
|
||||||
DbObject db2 = mock(DbObject.class); // only in left
|
DbObject db3 = new DatabaseObject("db3"); // only in right
|
||||||
when(db2.sameAs(db2)).thenReturn(true);
|
DbObject db4 = new DatabaseObject("db4");
|
||||||
DbObject db3 = mock(DbObject.class); // only in right
|
|
||||||
when(db3.sameAs(db3)).thenReturn(true);
|
|
||||||
DbObject db4 = mock(DbObject.class);
|
|
||||||
when(db4.sameAs(db4)).thenReturn(true);
|
|
||||||
|
|
||||||
Collection<DbObject> left = new ArrayList<DbObject>();
|
Collection<DbObject> left = new ArrayList<DbObject>();
|
||||||
Collections.addAll(left, db1, db2, db4);
|
Collections.addAll(left, db1, db2, db4);
|
||||||
@@ -106,13 +105,34 @@ public class DefaultComparisonUtilsTest
|
|||||||
|
|
||||||
comparisonUtils.compareCollections(left, right, ctx, Strength.ERROR);
|
comparisonUtils.compareCollections(left, right, ctx, Strength.ERROR);
|
||||||
|
|
||||||
// Objects in both are asked for their differences
|
// Differences and ommissions are noticed...
|
||||||
verify(db1).diff(db1, ctx, Strength.ERROR);
|
verify(differences).add(Where.IN_BOTH_BUT_DIFFERENCE, new DbProperty(db1), new DbProperty(db1));
|
||||||
verify(db4).diff(db4, ctx, Strength.ERROR);
|
|
||||||
|
|
||||||
// Objects in only one collections are marked as such
|
|
||||||
verify(differences).add(Where.ONLY_IN_REFERENCE, new DbProperty(db2), null, Strength.ERROR);
|
verify(differences).add(Where.ONLY_IN_REFERENCE, new DbProperty(db2), null, Strength.ERROR);
|
||||||
verify(differences).add(Where.ONLY_IN_TARGET, null, new DbProperty(db3), Strength.ERROR);
|
verify(differences).add(Where.ONLY_IN_TARGET, null, new DbProperty(db3), Strength.ERROR);
|
||||||
|
verify(differences).add(Where.IN_BOTH_BUT_DIFFERENCE, new DbProperty(db4), new DbProperty(db4));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void compareCollectionsWithMultipleMatches()
|
||||||
|
{
|
||||||
|
DbObject db2 = new DatabaseObject("db2");
|
||||||
|
DbObject db3 = new DatabaseObject("db3");
|
||||||
|
DbObject db4 = new DatabaseObject("db4");
|
||||||
|
DbObject db1 = new DatabaseObject("db1", db2, db3);
|
||||||
|
|
||||||
|
Collection<DbObject> left = new ArrayList<DbObject>();
|
||||||
|
Collections.addAll(left, db1, db4);
|
||||||
|
|
||||||
|
Collection<DbObject> right = new ArrayList<DbObject>();
|
||||||
|
Collections.addAll(right, db1, db2, db3);
|
||||||
|
|
||||||
|
comparisonUtils.compareCollections(left, right, ctx, Strength.ERROR);
|
||||||
|
|
||||||
|
// Differences and ommissions are noticed...
|
||||||
|
verify(differences).add(Where.ONLY_IN_REFERENCE, new DbProperty(db4), null, Strength.ERROR);
|
||||||
|
verify(differences).add(Where.IN_BOTH_BUT_DIFFERENCE, new DbProperty(db1), new DbProperty(db1));
|
||||||
|
verify(differences).add(Where.IN_BOTH_BUT_DIFFERENCE, new DbProperty(db1), new DbProperty(db2));
|
||||||
|
verify(differences).add(Where.IN_BOTH_BUT_DIFFERENCE, new DbProperty(db1), new DbProperty(db3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -195,40 +215,6 @@ public class DefaultComparisonUtilsTest
|
|||||||
return new DbProperty(obj, propName, -1, true, propValue);
|
return new DbProperty(obj, propName, -1, true, propValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void findSameObjectAsSuccessfulFind()
|
|
||||||
{
|
|
||||||
// Make a list of mock DbOjbect objects to test against
|
|
||||||
int numObjects = 20;
|
|
||||||
List<DbObject> dbObjects = createMockDbObjects(numObjects);
|
|
||||||
|
|
||||||
// The reference that will be used to look for one 'the same' in the collection.
|
|
||||||
DbObject toFind = mock(DbObject.class);
|
|
||||||
|
|
||||||
// For all other objects sameAs() will return false
|
|
||||||
DbObject objShouldBeFound = dbObjects.get(12);
|
|
||||||
when(objShouldBeFound.sameAs(toFind)).thenReturn(true);
|
|
||||||
|
|
||||||
DbObject found = comparisonUtils.findSameObjectAs(dbObjects, toFind);
|
|
||||||
|
|
||||||
assertSame("Found the wrong DbObject", objShouldBeFound, found);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void findSameObjectAsNotFound()
|
|
||||||
{
|
|
||||||
// Make a list of mock DbOjbect objects to test against
|
|
||||||
int numObjects = 20;
|
|
||||||
List<DbObject> dbObjects = createMockDbObjects(numObjects);
|
|
||||||
|
|
||||||
// The reference that will be used to look for one 'the same' in the collection.
|
|
||||||
DbObject toFind = mock(DbObject.class);
|
|
||||||
|
|
||||||
DbObject found = comparisonUtils.findSameObjectAs(dbObjects, toFind);
|
|
||||||
|
|
||||||
assertNull("Should not have found a matching DbObject", found);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<DbObject> createMockDbObjects(int size)
|
private List<DbObject> createMockDbObjects(int size)
|
||||||
{
|
{
|
||||||
@@ -263,4 +249,52 @@ public class DefaultComparisonUtilsTest
|
|||||||
return this.collection;
|
return this.collection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class DatabaseObject extends AbstractDbObject
|
||||||
|
{
|
||||||
|
private DbObject[] equivalentObjects = new DbObject[] {};
|
||||||
|
|
||||||
|
public DatabaseObject(String name)
|
||||||
|
{
|
||||||
|
super(null, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DatabaseObject(String name, DbObject... equivalentObjects)
|
||||||
|
{
|
||||||
|
this(name);
|
||||||
|
this.equivalentObjects = equivalentObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(DbObjectVisitor visitor)
|
||||||
|
{
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doDiff(DbObject right, DiffContext ctx, Strength strength)
|
||||||
|
{
|
||||||
|
DbProperty leftProp = new DbProperty(this);
|
||||||
|
DbProperty rightProp = new DbProperty(right);
|
||||||
|
ctx.getComparisonResults().add(Where.IN_BOTH_BUT_DIFFERENCE, leftProp, rightProp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean sameAs(DbObject other)
|
||||||
|
{
|
||||||
|
// We can tell this stub to treat certain other objects as 'the same' as this object
|
||||||
|
// by supplying them in the constructor. If this object is invoked with t.sameAs(o)
|
||||||
|
// and o is in the list of equivalent objects supplied in the constructor, then
|
||||||
|
// sameAs() will return true. Otherwise the default sameAs() implementation is used.
|
||||||
|
for (DbObject o : equivalentObjects)
|
||||||
|
{
|
||||||
|
if (other.equals(o))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.sameAs(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user