/* Copyright (c) 2013-2014 Boundless and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/edl-v10.html * * Contributors: * Victor Olaya (Boundless) - initial implementation */ package org.locationtech.geogig.api.plumbing.diff; import javax.annotation.Nullable; import org.locationtech.geogig.storage.text.TextValueSerializer; import com.google.common.base.Objects; import com.google.common.base.Optional; import com.google.common.base.Preconditions; /** * Generic implementation of a difference between two values for a given attribute * */ public class GenericAttributeDiffImpl implements AttributeDiff { /** * The new value. Null if it does not exist (the attribute has been removed) */ private Optional<?> newValue; /** * The old value. Null if it did not exist (the attribute has been added) */ private Optional<?> oldValue; public GenericAttributeDiffImpl(@Nullable Optional<?> oldValue, @Nullable Optional<?> newValue) { if (oldValue == null) { this.oldValue = Optional.absent(); } else { this.oldValue = oldValue; } if (newValue == null) { this.newValue = Optional.absent(); } else { this.newValue = newValue; } } @Override public TYPE getType() { TYPE type; if (!oldValue.isPresent() && !newValue.isPresent()) { type = TYPE.NO_CHANGE; } else if (!newValue.isPresent()) { type = TYPE.REMOVED; } else if (!oldValue.isPresent()) { type = TYPE.ADDED; } else if (oldValue.equals(newValue)) { type = TYPE.NO_CHANGE; } else { type = TYPE.MODIFIED; } return type; } @Override public Optional<?> getOldValue() { return oldValue; } @Override public Optional<?> getNewValue() { return newValue; } public String toString() { if (getType().equals(TYPE.MODIFIED)) { return attributeValueAsString(oldValue) + " -> " + attributeValueAsString(newValue); } else if (getType().equals(TYPE.ADDED)) { return "[MISSING] -> " + attributeValueAsString(newValue); } else if (getType().equals(TYPE.REMOVED)) { return attributeValueAsString(oldValue) + " -> [MISSING]"; } else { return "[NO CHANGE] -> " + attributeValueAsString(oldValue); } } private CharSequence attributeValueAsString(Optional<?> value) { if (value.isPresent()) { return TextValueSerializer.asString(Optional.fromNullable((Object) value.get())); } else { return "NULL"; } } @Override public AttributeDiff reversed() { return new GenericAttributeDiffImpl(newValue, oldValue); } @Override public Optional<?> applyOn(Optional<?> obj) { Preconditions.checkState(canBeAppliedOn(obj)); return newValue; } @Override public boolean canBeAppliedOn(Optional<?> obj) { if (obj == null) { obj = Optional.absent(); } return obj.equals(oldValue) || obj.equals(newValue); } @Override public String asText() { if (getType().equals(TYPE.MODIFIED)) { return getType().name().toCharArray()[0] + "\t" + attributeValueAsString(oldValue) + "\t" + attributeValueAsString(newValue); } else if (getType().equals(TYPE.ADDED)) { return getType().name().toCharArray()[0] + "\t" + attributeValueAsString(newValue); } else { return getType().name().toCharArray()[0] + "\t" + attributeValueAsString(oldValue); } } @Override public boolean equals(Object o) { // TODO: this is a temporary simple comparison. Should be more elaborate if (!(o instanceof GenericAttributeDiffImpl)) { return false; } GenericAttributeDiffImpl d = (GenericAttributeDiffImpl) o; return d.oldValue.equals(oldValue) && d.newValue.equals(newValue); } @Override public boolean conflicts(AttributeDiff ad) { if (ad instanceof GenericAttributeDiffImpl) { GenericAttributeDiffImpl gad = (GenericAttributeDiffImpl) ad; return !Objects.equal(gad.newValue, newValue); } else { return true; } } }