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 * @since 3669 023 */ 024public class ChangePropertyKeyCommand extends Command { 025 static final class SinglePrimitivePseudoCommand implements PseudoCommand { 026 private final String name; 027 private final OsmPrimitive osm; 028 private final Icon icon; 029 030 SinglePrimitivePseudoCommand(String name, OsmPrimitive osm, Icon icon) { 031 this.name = name; 032 this.osm = osm; 033 this.icon = icon; 034 } 035 036 @Override 037 public String getDescriptionText() { 038 return name; 039 } 040 041 @Override 042 public Icon getDescriptionIcon() { 043 return icon; 044 } 045 046 @Override 047 public Collection<? extends OsmPrimitive> getParticipatingPrimitives() { 048 return Collections.singleton(osm); 049 } 050 } 051 052 /** 053 * All primitives, that are affected with this command. 054 */ 055 private final List<? extends OsmPrimitive> objects; 056 /** 057 * The key that is subject to change. 058 */ 059 private final String key; 060 /** 061 * The mew key. 062 */ 063 private final String newKey; 064 065 /** 066 * Constructs a new {@code ChangePropertyKeyCommand}. 067 * 068 * @param object the object subject to change replacement 069 * @param key The key to replace 070 * @param newKey the new value of the key 071 * @since 6329 072 */ 073 public ChangePropertyKeyCommand(OsmPrimitive object, String key, String newKey) { 074 this(Collections.singleton(object), key, newKey); 075 } 076 077 /** 078 * Constructs a new {@code ChangePropertyKeyCommand}. 079 * 080 * @param objects all objects subject to change replacement 081 * @param key The key to replace 082 * @param newKey the new value of the key 083 */ 084 public ChangePropertyKeyCommand(Collection<? extends OsmPrimitive> objects, String key, String newKey) { 085 this.objects = new LinkedList<>(objects); 086 this.key = key; 087 this.newKey = newKey; 088 } 089 090 @Override 091 public boolean executeCommand() { 092 if (!super.executeCommand()) 093 return false; // save old 094 for (OsmPrimitive osm : objects) { 095 if (osm.hasKey(key) || osm.hasKey(newKey)) { 096 osm.setModified(true); 097 String oldValue = osm.get(key); 098 osm.put(newKey, oldValue); 099 osm.remove(key); 100 } 101 } 102 return true; 103 } 104 105 @Override 106 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) { 107 modified.addAll(objects); 108 } 109 110 @Override 111 public String getDescriptionText() { 112 String text = tr("Replace \"{0}\" by \"{1}\" for", key, newKey); 113 if (objects.size() == 1) { 114 NameVisitor v = new NameVisitor(); 115 objects.get(0).accept(v); 116 text += " "+tr(v.className)+" "+v.name; 117 } else { 118 text += " "+objects.size()+" "+trn("object", "objects", objects.size()); 119 } 120 return text; 121 } 122 123 @Override 124 public Icon getDescriptionIcon() { 125 return ImageProvider.get("data", "key"); 126 } 127 128 @Override 129 public Collection<PseudoCommand> getChildren() { 130 if (objects.size() == 1) 131 return null; 132 List<PseudoCommand> children = new ArrayList<>(); 133 134 final NameVisitor v = new NameVisitor(); 135 for (final OsmPrimitive osm : objects) { 136 osm.accept(v); 137 children.add(new SinglePrimitivePseudoCommand(v.name, osm, v.icon)); 138 } 139 return children; 140 } 141 142 @Override 143 public int hashCode() { 144 return Objects.hash(super.hashCode(), objects, key, newKey); 145 } 146 147 @Override 148 public boolean equals(Object obj) { 149 if (this == obj) return true; 150 if (obj == null || getClass() != obj.getClass()) return false; 151 if (!super.equals(obj)) return false; 152 ChangePropertyKeyCommand that = (ChangePropertyKeyCommand) obj; 153 return Objects.equals(objects, that.objects) && 154 Objects.equals(key, that.key) && 155 Objects.equals(newKey, that.newKey); 156 } 157}