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