001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.command.conflict; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.util.Collection; 007import java.util.Objects; 008import java.util.Set; 009 010import javax.swing.Icon; 011 012import org.openstreetmap.josm.data.conflict.Conflict; 013import org.openstreetmap.josm.data.osm.OsmPrimitive; 014import org.openstreetmap.josm.gui.conflict.pair.MergeDecisionType; 015import org.openstreetmap.josm.tools.ImageProvider; 016 017/** 018 * Represents the resolution of a conflict between the deleted flag of two {@link OsmPrimitive}s. 019 * @since 1654 020 */ 021public class DeletedStateConflictResolveCommand extends ConflictResolveCommand { 022 023 /** the conflict to resolve */ 024 private final Conflict<? extends OsmPrimitive> conflict; 025 026 /** the merge decision */ 027 private final MergeDecisionType decision; 028 029 /** 030 * Constructs a new {@code DeletedStateConflictResolveCommand}. 031 * 032 * @param conflict the conflict data set 033 * @param decision the merge decision 034 */ 035 public DeletedStateConflictResolveCommand(Conflict<? extends OsmPrimitive> conflict, MergeDecisionType decision) { 036 super(conflict.getMy().getDataSet()); 037 this.conflict = conflict; 038 this.decision = decision; 039 } 040 041 @Override 042 public String getDescriptionText() { 043 return tr("Resolve conflicts in deleted state in {0}", conflict.getMy().getId()); 044 } 045 046 @Override 047 public Icon getDescriptionIcon() { 048 return ImageProvider.get("data", "object"); 049 } 050 051 @Override 052 public boolean executeCommand() { 053 // remember the current state of modified primitives, i.e. of OSM primitive 'my' 054 super.executeCommand(); 055 056 if (decision == MergeDecisionType.KEEP_MINE) { 057 if (conflict.getMy().isDeleted() || conflict.isMyDeleted()) { 058 // because my was involved in a conflict it my still be referred 059 // to from a way or a relation. Fix this now. 060 deleteMy(); 061 } 062 } else if (decision == MergeDecisionType.KEEP_THEIR) { 063 if (conflict.getTheir().isDeleted()) { 064 deleteMy(); 065 } else { 066 conflict.getMy().setDeleted(false); 067 } 068 } else 069 // should not happen 070 throw new IllegalStateException(tr("Cannot resolve undecided conflict.")); 071 072 rememberConflict(conflict); 073 return true; 074 } 075 076 private void deleteMy() { 077 Set<OsmPrimitive> referrers = getAffectedDataSet().unlinkReferencesToPrimitive(conflict.getMy()); 078 for (OsmPrimitive p : referrers) { 079 if (!p.isNew() && !p.isDeleted()) { 080 p.setModified(true); 081 } 082 } 083 conflict.getMy().setDeleted(true); 084 } 085 086 @Override 087 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, 088 Collection<OsmPrimitive> added) { 089 modified.add(conflict.getMy()); 090 modified.addAll(conflict.getMy().getReferrers()); 091 } 092 093 @Override 094 public int hashCode() { 095 return Objects.hash(super.hashCode(), conflict, decision); 096 } 097 098 @Override 099 public boolean equals(Object obj) { 100 if (this == obj) return true; 101 if (obj == null || getClass() != obj.getClass()) return false; 102 if (!super.equals(obj)) return false; 103 DeletedStateConflictResolveCommand that = (DeletedStateConflictResolveCommand) obj; 104 return decision == that.decision && Objects.equals(conflict, that.conflict); 105 } 106}