package org.javers.core.diff.appenders; import org.javers.common.exception.JaversException; import org.javers.core.diff.NodePair; import org.javers.core.diff.changetype.PropertyChange; import org.javers.core.diff.changetype.ReferenceChange; import org.javers.core.diff.changetype.ValueChange; import org.javers.core.metamodel.object.GlobalId; import org.javers.core.metamodel.object.GlobalIdFactory; import org.javers.core.metamodel.property.Property; import org.javers.core.metamodel.type.*; import java.util.Objects; import java.util.Optional; import static org.javers.common.exception.JaversExceptionCode.UNSUPPORTED_OPTIONAL_CONTENT_TYPE; /** * @author bartosz.walacik */ public class OptionalChangeAppender extends CorePropertyChangeAppender<PropertyChange> { private final GlobalIdFactory globalIdFactory; private final TypeMapper typeMapper; public OptionalChangeAppender(GlobalIdFactory globalIdFactory, TypeMapper typeMapper) { this.globalIdFactory = globalIdFactory; this.typeMapper = typeMapper; } @Override public boolean supports(JaversType propertyType) { return propertyType instanceof OptionalType; } @Override public PropertyChange calculateChanges(NodePair pair, Property property) { OptionalType optionalType = ((JaversProperty) property).getType(); JaversType contentType = typeMapper.getJaversType(optionalType.getItemType()); Optional leftOptional = normalize((Optional) pair.getLeftPropertyValue(property)); Optional rightOptional = normalize((Optional) pair.getRightPropertyValue(property)); if (contentType instanceof ManagedType){ GlobalId leftId = getAndDehydrate(leftOptional, contentType); GlobalId rightId = getAndDehydrate(rightOptional, contentType); if (Objects.equals(leftId, rightId)) { return null; } return new ReferenceChange(pair.getGlobalId(), property.getName(), leftId, rightId, pair.getLeftPropertyValue(property), pair.getRightPropertyValue(property)); } if (contentType instanceof PrimitiveOrValueType) { if (leftOptional.equals(rightOptional)) { return null; } return new ValueChange(pair.getGlobalId(), property.getName(), leftOptional, rightOptional); } throw new JaversException(UNSUPPORTED_OPTIONAL_CONTENT_TYPE, contentType); } private GlobalId getAndDehydrate(Optional optional, final JaversType contentType){ return (GlobalId) optional .map(o -> globalIdFactory.dehydrate(o, contentType, null)) .orElse(null); } private Optional normalize(Optional optional) { if (optional == null) { return Optional.empty(); } return optional; } }