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