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 this.conflict = conflict; 037 this.decision = decision; 038 } 039 040 @Override 041 public String getDescriptionText() { 042 return tr("Resolve conflicts in deleted state in {0}", conflict.getMy().getId()); 043 } 044 045 @Override 046 public Icon getDescriptionIcon() { 047 return ImageProvider.get("data", "object"); 048 } 049 050 @Override 051 public boolean executeCommand() { 052 // remember the current state of modified primitives, i.e. of OSM primitive 'my' 053 super.executeCommand(); 054 055 if (decision.equals(MergeDecisionType.KEEP_MINE)) { 056 if (conflict.getMy().isDeleted() || conflict.isMyDeleted()) { 057 // because my was involved in a conflict it my still be referred 058 // to from a way or a relation. Fix this now. 059 deleteMy(); 060 } 061 } else if (decision.equals(MergeDecisionType.KEEP_THEIR)) { 062 if (conflict.getTheir().isDeleted()) { 063 deleteMy(); 064 } else { 065 conflict.getMy().setDeleted(false); 066 } 067 } else 068 // should not happen 069 throw new IllegalStateException(tr("Cannot resolve undecided conflict.")); 070 071 rememberConflict(conflict); 072 return true; 073 } 074 075 private void deleteMy() { 076 Set<OsmPrimitive> referrers = getLayer().data.unlinkReferencesToPrimitive(conflict.getMy()); 077 for (OsmPrimitive p : referrers) { 078 if (!p.isNew() && !p.isDeleted()) { 079 p.setModified(true); 080 } 081 } 082 conflict.getMy().setDeleted(true); 083 } 084 085 @Override 086 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, 087 Collection<OsmPrimitive> added) { 088 modified.add(conflict.getMy()); 089 modified.addAll(conflict.getMy().getReferrers()); 090 } 091 092 @Override 093 public int hashCode() { 094 return Objects.hash(super.hashCode(), conflict, decision); 095 } 096 097 @Override 098 public boolean equals(Object obj) { 099 if (this == obj) return true; 100 if (obj == null || getClass() != obj.getClass()) return false; 101 if (!super.equals(obj)) return false; 102 DeletedStateConflictResolveCommand that = (DeletedStateConflictResolveCommand) obj; 103 return Objects.equals(conflict, that.conflict) && 104 decision == that.decision; 105 } 106}