Skip to content

Commit

Permalink
javers#605 Add List compare Algorithm SET.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kobyshev Sergey committed Nov 21, 2017
1 parent 793d89c commit 88bf454
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 2 deletions.
@@ -1,14 +1,16 @@
package org.javers.core.diff;

import org.javers.core.diff.appenders.CorePropertyChangeAppender;
import org.javers.core.diff.appenders.SetListChangeAppender;
import org.javers.core.diff.appenders.SimpleListChangeAppender;
import org.javers.core.diff.appenders.levenshtein.LevenshteinListChangeAppender;
import org.javers.core.diff.changetype.container.ListChange;

public enum ListCompareAlgorithm {

SIMPLE(SimpleListChangeAppender.class),
LEVENSHTEIN_DISTANCE(LevenshteinListChangeAppender.class);
LEVENSHTEIN_DISTANCE(LevenshteinListChangeAppender.class),
SET(SetListChangeAppender.class);

private final Class<? extends CorePropertyChangeAppender<ListChange>> listChangeAppender;

Expand Down
Expand Up @@ -36,7 +36,7 @@ public boolean supports(JaversType propertyType) {
return propertyType instanceof SetType;
}

private List<ContainerElementChange> calculateEntryChanges(SetType setType, Set leftRawSet, Set rightRawSet, OwnerContext owner) {
List<ContainerElementChange> calculateEntryChanges(SetType setType, Set leftRawSet, Set rightRawSet, OwnerContext owner) {

JaversType itemType = typeMapper.getJaversType(setType.getItemType());
DehydrateContainerFunction dehydrateFunction = new DehydrateContainerFunction(itemType, globalIdFactory);
Expand Down
@@ -0,0 +1,51 @@
package org.javers.core.diff.appenders;

import org.javers.core.diff.NodePair;
import org.javers.core.diff.changetype.container.ContainerElementChange;
import org.javers.core.diff.changetype.container.ListChange;
import org.javers.core.metamodel.object.OwnerContext;
import org.javers.core.metamodel.object.PropertyOwnerContext;
import org.javers.core.metamodel.type.*;

import java.util.List;

import static org.javers.common.collections.Sets.asSet;

/**
* @author Sergey Kobyshev
*/
public class SetListChangeAppender extends CorePropertyChangeAppender<ListChange> {

private final SetChangeAppender setChangeAppender;
private final TypeMapper typeMapper;

SetListChangeAppender(SetChangeAppender setChangeAppender, TypeMapper typeMapper) {
this.setChangeAppender = setChangeAppender;
this.typeMapper = typeMapper;
}

@Override
public boolean supports(JaversType propertyType) {
return propertyType instanceof ListType;
}

@Override
public ListChange calculateChanges(final NodePair pair, final JaversProperty property) {
List leftList = (List) pair.getLeftPropertyValue(property);
List rightList = (List) pair.getRightPropertyValue(property);

ListType listType = ((JaversProperty) property).getType();
OwnerContext owner = new PropertyOwnerContext(pair.getGlobalId(), property.getName());
SetType setType = typeMapper.getSetType(listType);

List<ContainerElementChange> entryChanges =
setChangeAppender.calculateEntryChanges(setType, leftList == null ? null : asSet(leftList), rightList == null ? null : asSet(rightList), owner);

if (!entryChanges.isEmpty()) {
renderNotParametrizedWarningIfNeeded(setType.getItemType(), "item", "Set", property);
return new ListChange(pair.getGlobalId(), property.getName(), entryChanges);
} else {
return null;
}
}
}
Expand Up @@ -88,6 +88,13 @@ public MapContentType getMapContentType(ContainerType containerType){
return new MapContentType(keyType, valueType);
}

/**
* only for change appenders
*/
public SetType getSetType(ContainerType containerType){
return new SetType(containerType.getItemType());
}

/**
* is Set, List or Array of ManagedClasses
*/
Expand Down
Expand Up @@ -31,4 +31,8 @@ abstract class AbstractDiffAppendersTest extends AbstractDiffTest {
SetChangeAppender setChangeAppender() {
new SetChangeAppender(javers.typeMapper, javers.globalIdFactory)
}

SetListChangeAppender setListChangeAppender() {
new SetListChangeAppender(setChangeAppender(), javers.typeMapper)
}
}
@@ -0,0 +1,96 @@
package org.javers.core.diff.appenders

import org.javers.core.model.DummyUser
import org.javers.core.model.SnapshotEntity
import spock.lang.Unroll

import java.time.LocalDate

import static org.javers.core.diff.appenders.ContainerChangeAssert.getAssertThat
import static org.javers.core.model.DummyUser.dummyUser

/**
* @author Sergey Kobyshev
*/
class SetListChangeAppenderTest extends AbstractDiffAppendersTest {

@Unroll
def "should append #changesCount changes when left list is #leftList and right list is #rightList"() {

when:
def leftNode = dummyUser().withIntegerList(leftList)
def rightNode = dummyUser().withIntegerList(rightList)

def change = setListChangeAppender().calculateChanges(
realNodePair(leftNode, rightNode), getProperty(DummyUser, "integerList"))

then:
change.changes.size() == changesCount
change.changes.each {
assert it.index == null
}

where:
leftList | rightList || changesCount
null | [1, 2] || 2
[] | [1, 2] || 2
[1, 2] | [1, 2, 3, 4] || 2
[1, 2] | [2, 1, 3] || 1
[1, 2] | [] || 2
[1, 2, 3, 4] | [1] || 3
[2, 1, 3] | [1, 2] || 1
}

@Unroll
def "should not append changes when left list #leftList and right list #rightList are equal"() {

when:
def leftNode = dummyUser().withIntegerList(leftList)
def rightNode = dummyUser().withIntegerList(rightList)

def change = setListChangeAppender().calculateChanges(
realNodePair(leftNode, rightNode), getProperty(DummyUser, "integerList"))

then:
change == null

where:
leftList | rightList
[] | []
[1, 2] | [1, 2]
[1, 2] | [2, 1]
}

def "should append ValueAdded in List of Values"() {
given:
def leftCdo = new SnapshotEntity(listOfDates: [new LocalDate(2001,1,1)])
def rightCdo = new SnapshotEntity(listOfDates: [new LocalDate(2001,5,5), new LocalDate(2001,1,1)])

when:
def change = setListChangeAppender()
.calculateChanges(realNodePair(leftCdo, rightCdo), getProperty(SnapshotEntity, "listOfDates"))

then:
assertThat(change)
.hasSize(1)
.hasValueAdded(new LocalDate(2001,5,5))

}

def "should append ValueRemoved in List of Values"() {
given:
def leftCdo = new SnapshotEntity(listOfDates: [new LocalDate(2001,5,5), new LocalDate(2001,1,1)])
def rightCdo = new SnapshotEntity(listOfDates: [new LocalDate(2001,1,1)])

when:
def change = setListChangeAppender()
.calculateChanges(realNodePair(leftCdo, rightCdo), getProperty(SnapshotEntity, "listOfDates"))

then:
assertThat(change)
.hasSize(1)
.hasValueRemoved(new LocalDate(2001,5,5))

}

}

0 comments on commit 88bf454

Please sign in to comment.