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 org.openstreetmap.josm.Main;
007import org.openstreetmap.josm.command.Command;
008import org.openstreetmap.josm.data.conflict.Conflict;
009import org.openstreetmap.josm.data.conflict.ConflictCollection;
010import org.openstreetmap.josm.gui.layer.OsmDataLayer;
011
012/**
013 * This is the common base class for {@link Command}s which manipulate {@link Conflict}s in
014 * addition to {@link org.openstreetmap.josm.data.osm.OsmPrimitive}s.
015 *
016 * A ConflictResolverCommand can remember a collection of conflicts it resolves. Upon undoing
017 * it reconstitutes them.
018 *
019 */
020public abstract class ConflictResolveCommand extends Command {
021    /** the list of resolved conflicts */
022    private final ConflictCollection resolvedConflicts;
023
024    /**
025     * Constructs a new {@code ConflictResolveCommand} in the context of the current edit layer, if any.
026     */
027    public ConflictResolveCommand() {
028        super();
029        resolvedConflicts = new ConflictCollection();
030    }
031
032    /**
033     * Constructs a new {@code ConflictResolveCommand} in the context of a given data layer.
034     * @param layer the data layer. Must not be null.
035     */
036    public ConflictResolveCommand(OsmDataLayer layer) {
037        super(layer);
038        resolvedConflicts = new ConflictCollection();
039    }
040
041    /**
042     * remembers a conflict in the internal list of remembered conflicts
043     *
044     * @param c the remembered conflict
045     */
046    protected void rememberConflict(Conflict<?> c) {
047        if (!resolvedConflicts.hasConflictForMy(c.getMy())) {
048            resolvedConflicts.add(c);
049        }
050    }
051
052    /**
053     * reconstitutes all remembered conflicts. Add the remembered conflicts to the
054     * set of conflicts of the {@link OsmDataLayer} this command was applied to.
055     *
056     */
057    protected void reconstituteConflicts() {
058        OsmDataLayer editLayer = getLayer();
059        for (Conflict<?> c : resolvedConflicts) {
060            if (!editLayer.getConflicts().hasConflictForMy(c.getMy())) {
061                editLayer.getConflicts().add(c);
062            }
063        }
064    }
065
066    @Override
067    public void undoCommand() {
068        super.undoCommand();
069
070        if (Main.isDisplayingMapView()) {
071            if (!Main.map.mapView.hasLayer(getLayer())) {
072                Main.warn(tr("Cannot undo command ''{0}'' because layer ''{1}'' is not present any more",
073                        this.toString(),
074                        getLayer().toString()
075                ));
076                return;
077            }
078
079            Main.map.mapView.setActiveLayer(getLayer());
080        }
081        reconstituteConflicts();
082    }
083
084    @Override
085    public int hashCode() {
086        final int prime = 31;
087        int result = super.hashCode();
088        result = prime * result + ((resolvedConflicts == null) ? 0 : resolvedConflicts.hashCode());
089        return result;
090    }
091
092    @Override
093    public boolean equals(Object obj) {
094        if (this == obj)
095            return true;
096        if (!super.equals(obj))
097            return false;
098        if (getClass() != obj.getClass())
099            return false;
100        ConflictResolveCommand other = (ConflictResolveCommand) obj;
101        if (resolvedConflicts == null) {
102            if (other.resolvedConflicts != null)
103                return false;
104        } else if (!resolvedConflicts.equals(other.resolvedConflicts))
105            return false;
106        return true;
107    }
108}