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.equals(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.equals(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}