001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.command;
003
004import static org.openstreetmap.josm.tools.I18n.marktr;
005import static org.openstreetmap.josm.tools.I18n.tr;
006
007import java.util.Collection;
008
009import javax.swing.Icon;
010
011import org.openstreetmap.josm.data.osm.OsmPrimitive;
012import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
013import org.openstreetmap.josm.data.osm.Way;
014import org.openstreetmap.josm.gui.DefaultNameFormatter;
015import org.openstreetmap.josm.gui.layer.OsmDataLayer;
016import org.openstreetmap.josm.tools.CheckParameterUtil;
017import org.openstreetmap.josm.tools.ImageProvider;
018
019/**
020 * Command that basically replaces one OSM primitive by another of the same type.
021 *
022 * @since 93
023 */
024public class ChangeCommand extends Command {
025
026    private final OsmPrimitive osm;
027    private final OsmPrimitive newOsm;
028
029    /**
030     * Constructs a new {@code ChangeCommand} in the context of the current edit layer, if any.
031     * @param osm The existing primitive to modify
032     * @param newOsm The new primitive
033     */
034    public ChangeCommand(OsmPrimitive osm, OsmPrimitive newOsm) {
035        this.osm = osm;
036        this.newOsm = newOsm;
037        sanityChecks();
038    }
039
040    /**
041     * Constructs a new {@code ChangeCommand} in the context of a given data layer.
042     * @param layer The data layer
043     * @param osm The existing primitive to modify
044     * @param newOsm The new primitive
045     */
046    public ChangeCommand(OsmDataLayer layer, OsmPrimitive osm, OsmPrimitive newOsm) {
047        super(layer);
048        this.osm = osm;
049        this.newOsm = newOsm;
050        sanityChecks();
051    }
052
053    private void sanityChecks() {
054        CheckParameterUtil.ensureParameterNotNull(osm, "osm");
055        CheckParameterUtil.ensureParameterNotNull(newOsm, "newOsm");
056        if (newOsm instanceof Way && ((Way)newOsm).getNodesCount() == 0) {
057            // Do not allow to create empty ways (see #7465)
058            throw new IllegalArgumentException(tr("New way {0} has 0 nodes", newOsm));
059        }
060    }
061
062    @Override
063    public boolean executeCommand() {
064        super.executeCommand();
065        osm.cloneFrom(newOsm);
066        osm.setModified(true);
067        return true;
068    }
069
070    @Override
071    public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
072        modified.add(osm);
073    }
074
075    @Override
076    public String getDescriptionText() {
077        String msg = "";
078        switch(OsmPrimitiveType.from(osm)) {
079        case NODE: msg = marktr("Change node {0}"); break;
080        case WAY: msg = marktr("Change way {0}"); break;
081        case RELATION: msg = marktr("Change relation {0}"); break;
082        }
083        return tr(msg, osm.getDisplayName(DefaultNameFormatter.getInstance()));
084    }
085
086    @Override
087    public Icon getDescriptionIcon() {
088        return ImageProvider.get(osm.getDisplayType());
089    }
090}