package org.javers.core.diff.appenders;
import org.javers.common.collections.Sets;
import org.javers.core.diff.NodePair;
import org.javers.core.diff.changetype.container.ContainerElementChange;
import org.javers.core.diff.changetype.container.SetChange;
import org.javers.core.diff.changetype.container.ValueAdded;
import org.javers.core.diff.changetype.container.ValueRemoved;
import org.javers.core.metamodel.object.DehydrateContainerFunction;
import org.javers.core.metamodel.object.GlobalIdFactory;
import org.javers.core.metamodel.object.OwnerContext;
import org.javers.core.metamodel.object.PropertyOwnerContext;
import org.javers.core.metamodel.property.Property;
import org.javers.core.metamodel.type.JaversProperty;
import org.javers.core.metamodel.type.JaversType;
import org.javers.core.metamodel.type.SetType;
import org.javers.core.metamodel.type.TypeMapper;
import java.util.*;
/**
* @author pawel szymczyk
*/
class SetChangeAppender extends CorePropertyChangeAppender<SetChange> {
private final TypeMapper typeMapper;
private final GlobalIdFactory globalIdFactory;
SetChangeAppender(TypeMapper typeMapper, GlobalIdFactory globalIdFactory) {
this.typeMapper = typeMapper;
this.globalIdFactory = globalIdFactory;
}
@Override
public boolean supports(JaversType propertyType) {
return propertyType instanceof SetType;
}
private List<ContainerElementChange> calculateEntryChanges(SetType setType, Set leftRawSet, Set rightRawSet, OwnerContext owner) {
JaversType itemType = typeMapper.getJaversType(setType.getItemType());
DehydrateContainerFunction dehydrateFunction = new DehydrateContainerFunction(itemType, globalIdFactory);
if (Objects.equals(leftRawSet, rightRawSet)) {
return Collections.emptyList();
}
Set leftSet = (Set) setType.map(leftRawSet, dehydrateFunction, owner);
Set rightSet = (Set) setType.map(rightRawSet, dehydrateFunction, owner);
List<ContainerElementChange> changes = new ArrayList<>();
Sets.difference(leftSet, rightSet).forEach(valueOrId ->
changes.add(new ValueRemoved(valueOrId)));
Sets.difference(rightSet, leftSet).forEach(valueOrId ->
changes.add(new ValueAdded(valueOrId)));
return changes;
}
@Override
public SetChange calculateChanges(NodePair pair, Property property) {
Set leftValues = (Set) pair.getLeftPropertyValue(property);
Set rightValues = (Set) pair.getRightPropertyValue(property);
SetType setType = ((JaversProperty) property).getType();
OwnerContext owner = new PropertyOwnerContext(pair.getGlobalId(), property.getName());
List<ContainerElementChange> entryChanges =
calculateEntryChanges(setType, leftValues, rightValues, owner);
if (!entryChanges.isEmpty()) {
renderNotParametrizedWarningIfNeeded(setType.getItemType(), "item", "Set", property);
return new SetChange(pair.getGlobalId(), property.getName(), entryChanges);
} else {
return null;
}
}
}