001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.conflict;
003
004import java.util.Map;
005import java.util.Objects;
006
007import org.openstreetmap.josm.data.osm.OsmPrimitive;
008import org.openstreetmap.josm.data.osm.PrimitiveId;
009
010/**
011 * Represents a conflict between two {@link OsmPrimitive}s. It is represented as
012 * a pair of {@link OsmPrimitive}s where one element of the pair has the role <em>my</em>
013 * and the other has the role <em>their</em>.
014 * <ul>
015 *   <li><code>my</code> is the {@link OsmPrimitive} in the local dataset</li>
016 *   <li><code>their</code> is the {@link OsmPrimitive} which caused the conflict when it
017 *   it was tried to merge it onto <code>my</code>. <code>their</code> is usually the
018 *   {@link OsmPrimitive} from the dataset in another layer or the one retrieved from the server.</li>
019 * </ul>
020 * @param <T> primitive type of the conflict
021 * @since 1750
022 */
023public class Conflict<T extends OsmPrimitive> {
024    private final T my;
025    private final T their;
026    private final boolean isMyDeleted;
027
028    // mergedMap is only set if the conflict results from merging two layers
029    private Map<PrimitiveId, PrimitiveId> mergedMap;
030
031    public Conflict(T my, T their) {
032        this(my, their, false);
033    }
034
035    public Conflict(T my, T their, boolean isMyDeleted) {
036        this.my = my;
037        this.their = their;
038        this.isMyDeleted = isMyDeleted;
039    }
040
041    public T getMy() {
042        return my;
043    }
044
045    public T getTheir() {
046        return their;
047    }
048
049    public boolean isMatchingMy(OsmPrimitive my) {
050        return this.my == my;
051    }
052
053    public boolean isMatchingTheir(OsmPrimitive their) {
054        return this.their == their;
055    }
056
057    /**
058     * Replies true if the primitive <code>primitive</code> is participating
059     * in this conflict
060     *
061     * @param primitive the primitive
062     * @return true if the primitive <code>primitive</code> is participating
063     * in this conflict
064     */
065    public boolean isParticipating(OsmPrimitive primitive) {
066        if (primitive == null) return false;
067        return primitive.getPrimitiveId().equals(my.getPrimitiveId())
068        || primitive.getPrimitiveId().equals(their.getPrimitiveId());
069    }
070
071    /**
072     * Replies true if the primitive with id <code>id</code> is participating
073     * in this conflict
074     *
075     * @param id the primitive id
076     * @return true if the primitive <code>primitive</code> is participating
077     * in this conflict
078     */
079    public boolean isParticipating(PrimitiveId id) {
080        if (id == null) return false;
081        return id.equals(my.getPrimitiveId())
082        || id.equals(their.getPrimitiveId());
083    }
084
085    @Override
086    public int hashCode() {
087        return Objects.hash(my, their);
088    }
089
090    @Override
091    public boolean equals(Object obj) {
092        if (this == obj) return true;
093        if (obj == null || getClass() != obj.getClass()) return false;
094        Conflict<?> conflict = (Conflict<?>) obj;
095        return Objects.equals(my, conflict.my) &&
096                Objects.equals(their, conflict.their);
097    }
098
099    /**
100     * Determines if my primitive was deleted but it has set non deleted status.
101     * @return True if my primitive was deleted but it has set non deleted status because it's referred by another
102     * primitive and references to deleted primitives are not allowed.
103     */
104    public boolean isMyDeleted() {
105        return isMyDeleted;
106    }
107
108    public final Map<PrimitiveId, PrimitiveId> getMergedMap() {
109        return mergedMap;
110    }
111
112    public final void setMergedMap(Map<PrimitiveId, PrimitiveId> mergedMap) {
113        this.mergedMap = mergedMap;
114    }
115
116    @Override
117    public String toString() {
118        return "Conflict [my=" + my + ", their=" + their + ']';
119    }
120}