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 * 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}