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