001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.command;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005import static org.openstreetmap.josm.tools.I18n.trn;
006
007import java.util.ArrayList;
008import java.util.Collection;
009import java.util.Collections;
010import java.util.LinkedList;
011import java.util.List;
012import java.util.Objects;
013
014import javax.swing.Icon;
015
016import org.openstreetmap.josm.data.osm.OsmPrimitive;
017import org.openstreetmap.josm.data.validation.util.NameVisitor;
018import org.openstreetmap.josm.tools.ImageProvider;
019
020/**
021 * Command that replaces the key of one or several objects
022 *
023 */
024public class ChangePropertyKeyCommand extends Command {
025    /**
026     * All primitives, that are affected with this command.
027     */
028    private final List<? extends OsmPrimitive> objects;
029    /**
030     * The key that is subject to change.
031     */
032    private final String key;
033    /**
034     * The mew key.
035     */
036    private final String newKey;
037
038    /**
039     * Constructs a new {@code ChangePropertyKeyCommand}.
040     *
041     * @param object the object subject to change replacement
042     * @param key The key to replace
043     * @param newKey the new value of the key
044     * @since 6329
045     */
046    public ChangePropertyKeyCommand(OsmPrimitive object, String key, String newKey) {
047        this(Collections.singleton(object), key, newKey);
048    }
049
050    /**
051     * Constructs a new {@code ChangePropertyKeyCommand}.
052     *
053     * @param objects all objects subject to change replacement
054     * @param key The key to replace
055     * @param newKey the new value of the key
056     */
057    public ChangePropertyKeyCommand(Collection<? extends OsmPrimitive> objects, String key, String newKey) {
058        this.objects = new LinkedList<>(objects);
059        this.key = key;
060        this.newKey = newKey;
061    }
062
063    @Override
064    public boolean executeCommand() {
065        if (!super.executeCommand())
066            return false; // save old
067        for (OsmPrimitive osm : objects) {
068            if (osm.hasKeys()) {
069                osm.setModified(true);
070                String oldValue = osm.get(key);
071                osm.put(newKey, oldValue);
072                osm.remove(key);
073            }
074        }
075        return true;
076    }
077
078    @Override
079    public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
080        modified.addAll(objects);
081    }
082
083    @Override
084    public String getDescriptionText() {
085        String text = tr("Replace \"{0}\" by \"{1}\" for", key, newKey);
086        if (objects.size() == 1) {
087            NameVisitor v = new NameVisitor();
088            objects.get(0).accept(v);
089            text += ' '+tr(v.className)+' '+v.name;
090        } else {
091            text += ' '+objects.size()+' '+trn("object", "objects", objects.size());
092        }
093        return text;
094    }
095
096    @Override
097    public Icon getDescriptionIcon() {
098        return ImageProvider.get("data", "key");
099    }
100
101    @Override
102    public Collection<PseudoCommand> getChildren() {
103        if (objects.size() == 1)
104            return null;
105        List<PseudoCommand> children = new ArrayList<>();
106
107        final NameVisitor v = new NameVisitor();
108        for (final OsmPrimitive osm : objects) {
109            osm.accept(v);
110            children.add(new PseudoCommand() {
111                @Override
112                public String getDescriptionText() {
113                    return v.name;
114                }
115
116                @Override
117                public Icon getDescriptionIcon() {
118                    return v.icon;
119                }
120
121                @Override
122                public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
123                    return Collections.singleton(osm);
124                }
125            });
126        }
127        return children;
128    }
129
130    @Override
131    public int hashCode() {
132        return Objects.hash(super.hashCode(), objects, key, newKey);
133    }
134
135    @Override
136    public boolean equals(Object obj) {
137        if (this == obj) return true;
138        if (obj == null || getClass() != obj.getClass()) return false;
139        if (!super.equals(obj)) return false;
140        ChangePropertyKeyCommand that = (ChangePropertyKeyCommand) obj;
141        return Objects.equals(objects, that.objects) &&
142                Objects.equals(key, that.key) &&
143                Objects.equals(newKey, that.newKey);
144    }
145}