source: josm/trunk/src/org/openstreetmap/josm/command/ChangePropertyCommand.java@ 6881

Last change on this file since 6881 was 6881, checked in by Don-vip, 11 years ago

javadoc/code style/minor refactorization

  • Property svn:eol-style set to native
File size: 8.8 KB
RevLine 
[6380]1// License: GPL. For details, see LICENSE file.
[626]2package org.openstreetmap.josm.command;
3
[1990]4import static org.openstreetmap.josm.tools.I18n.marktr;
[626]5import static org.openstreetmap.josm.tools.I18n.tr;
[6507]6import static org.openstreetmap.josm.tools.I18n.trn;
[626]7
[4773]8import java.util.AbstractMap;
[3262]9import java.util.ArrayList;
[4302]10import java.util.Arrays;
[626]11import java.util.Collection;
[3262]12import java.util.Collections;
[4773]13import java.util.HashMap;
[626]14import java.util.LinkedList;
15import java.util.List;
[4773]16import java.util.Map;
[5077]17
[4918]18import javax.swing.Icon;
[626]19
[3910]20import org.openstreetmap.josm.Main;
[626]21import org.openstreetmap.josm.data.osm.OsmPrimitive;
[1814]22import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
[1990]23import org.openstreetmap.josm.gui.DefaultNameFormatter;
[626]24import org.openstreetmap.josm.tools.ImageProvider;
25
26/**
27 * Command that manipulate the key/value structure of several objects. Manages deletion,
28 * adding and modify of values and keys.
[1169]29 *
[626]30 * @author imi
31 */
32public class ChangePropertyCommand extends Command {
[1169]33 /**
34 * All primitives that are affected with this command.
35 */
36 private final List<OsmPrimitive> objects;
37 /**
[4773]38 * Key and value pairs. If value is <code>null</code>, delete all key references with the given
[6324]39 * key. Otherwise, change the tags of all objects to the given value or create keys of
[1169]40 * those objects that do not have the key yet.
41 */
[4773]42 private final AbstractMap<String, String> tags;
[628]43
[4773]44 /**
[6324]45 * Creates a command to change multiple tags of multiple objects
[4773]46 *
47 * @param objects the objects to modify
[6324]48 * @param tags the tags to set
[4773]49 */
50 public ChangePropertyCommand(Collection<? extends OsmPrimitive> objects, AbstractMap<String, String> tags) {
[1169]51 this.objects = new LinkedList<OsmPrimitive>();
[4773]52 this.tags = tags;
53 init(objects);
[1169]54 }
[626]55
[4773]56 /**
[6324]57 * Creates a command to change one tag of multiple objects
[4773]58 *
59 * @param objects the objects to modify
[6324]60 * @param key the key of the tag to set
[4773]61 * @param value the value of the key to set
62 */
63 public ChangePropertyCommand(Collection<? extends OsmPrimitive> objects, String key, String value) {
64 this.objects = new LinkedList<OsmPrimitive>();
65 this.tags = new HashMap<String, String>(1);
66 this.tags.put(key, value);
67 init(objects);
68 }
69
70 /**
[6324]71 * Creates a command to change one tag of one object
[4773]72 *
73 * @param object the object to modify
[6324]74 * @param key the key of the tag to set
[4773]75 * @param value the value of the key to set
76 */
[1169]77 public ChangePropertyCommand(OsmPrimitive object, String key, String value) {
[4302]78 this(Arrays.asList(object), key, value);
[1169]79 }
[626]80
[4773]81 /**
82 * Initialize the instance by finding what objects will be modified
83 *
84 * @param objects the objects to (possibly) modify
85 */
86 private void init(Collection<? extends OsmPrimitive> objects) {
87 // determine what objects will be modified
88 for (OsmPrimitive osm : objects) {
89 boolean modified = false;
90
91 // loop over all tags
92 for (Map.Entry<String, String> tag : this.tags.entrySet()) {
93 String oldVal = osm.get(tag.getKey());
94 String newVal = tag.getValue();
95
96 if (newVal == null || newVal.isEmpty()) {
97 if (oldVal != null)
98 // new value is null and tag exists (will delete tag)
99 modified = true;
100 }
101 else if (oldVal == null || !newVal.equals(oldVal))
102 // new value is not null and is different from current value
103 modified = true;
104 }
105 if (modified)
106 this.objects.add(osm);
107 }
108 }
109
[1169]110 @Override public boolean executeCommand() {
[3910]111 Main.main.getCurrentDataSet().beginUpdate();
112 try {
113 super.executeCommand(); // save old
[4773]114
115 for (OsmPrimitive osm : objects) {
[5143]116 // loop over all tags
[4773]117 for (Map.Entry<String, String> tag : this.tags.entrySet()) {
118 String oldVal = osm.get(tag.getKey());
119 String newVal = tag.getValue();
120
121 if (newVal == null || newVal.isEmpty()) {
[5143]122 if (oldVal != null)
[4773]123 osm.remove(tag.getKey());
124 }
125 else if (oldVal == null || !newVal.equals(oldVal))
126 osm.put(tag.getKey(), newVal);
[3910]127 }
[5143]128 // init() only keeps modified primitives. Therefore the modified
129 // bit can be set without further checks.
130 osm.setModified(true);
[1169]131 }
[3910]132 return true;
[1169]133 }
[3910]134 finally {
135 Main.main.getCurrentDataSet().endUpdate();
136 }
[626]137 }
[1169]138
139 @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
140 modified.addAll(objects);
141 }
142
[4918]143 @Override
144 public String getDescriptionText() {
[1182]145 String text;
[4773]146 if (objects.size() == 1 && tags.size() == 1) {
[1814]147 OsmPrimitive primitive = objects.iterator().next();
[1989]148 String msg = "";
[4773]149 Map.Entry<String, String> entry = tags.entrySet().iterator().next();
150 if (entry.getValue() == null) {
[1989]151 switch(OsmPrimitiveType.from(primitive)) {
[2990]152 case NODE: msg = marktr("Remove \"{0}\" for node ''{1}''"); break;
153 case WAY: msg = marktr("Remove \"{0}\" for way ''{1}''"); break;
154 case RELATION: msg = marktr("Remove \"{0}\" for relation ''{1}''"); break;
[1989]155 }
[4773]156 text = tr(msg, entry.getKey(), primitive.getDisplayName(DefaultNameFormatter.getInstance()));
[1989]157 } else {
158 switch(OsmPrimitiveType.from(primitive)) {
[2990]159 case NODE: msg = marktr("Set {0}={1} for node ''{2}''"); break;
160 case WAY: msg = marktr("Set {0}={1} for way ''{2}''"); break;
161 case RELATION: msg = marktr("Set {0}={1} for relation ''{2}''"); break;
[1989]162 }
[4773]163 text = tr(msg, entry.getKey(), entry.getValue(), primitive.getDisplayName(DefaultNameFormatter.getInstance()));
[1989]164 }
[4773]165 } else if (objects.size() > 1 && tags.size() == 1) {
166 Map.Entry<String, String> entry = tags.entrySet().iterator().next();
[6507]167 if (entry.getValue() == null) {
[6679]168 /* I18n: plural form for objects, but value < 2 not possible! */
169 text = trn("Remove \"{0}\" for {1} object", "Remove \"{0}\" for {1} objects", objects.size(), entry.getKey(), objects.size());
[6507]170 } else {
[6679]171 /* I18n: plural form for objects, but value < 2 not possible! */
172 text = trn("Set {0}={1} for {2} object", "Set {0}={1} for {2} objects", objects.size(), entry.getKey(), entry.getValue(), objects.size());
[6507]173 }
[1182]174 }
[4773]175 else {
176 boolean allnull = true;
177 for (Map.Entry<String, String> tag : this.tags.entrySet()) {
178 if (tag.getValue() != null) {
179 allnull = false;
180 break;
181 }
182 }
[5077]183
[4773]184 if (allnull) {
[6881]185 /* I18n: plural form detected for objects only (but value < 2 not possible!), try to do your best for tags */
[6679]186 text = trn("Deleted {0} tags for {1} object", "Deleted {0} tags for {1} objects", objects.size(), tags.size(), objects.size());
[6507]187 } else {
[6679]188 /* I18n: plural form detected for objects only (but value < 2 not possible!), try to do your best for tags */
189 text = trn("Set {0} tags for {1} object", "Set {0} tags for {1} objects", objects.size(), tags.size(), objects.size());
[6507]190 }
[4773]191 }
[4918]192 return text;
[3262]193 }
194
[4918]195 @Override
196 public Icon getDescriptionIcon() {
197 return ImageProvider.get("data", "key");
198 }
199
[3262]200 @Override public Collection<PseudoCommand> getChildren() {
[1169]201 if (objects.size() == 1)
[3262]202 return null;
203 List<PseudoCommand> children = new ArrayList<PseudoCommand>();
204 for (final OsmPrimitive osm : objects) {
205 children.add(new PseudoCommand() {
[4918]206 @Override public String getDescriptionText() {
207 return osm.getDisplayName(DefaultNameFormatter.getInstance());
208 }
[3262]209
[4918]210 @Override public Icon getDescriptionIcon() {
[5077]211 return ImageProvider.get(osm.getDisplayType());
[3262]212 }
[4918]213
[3262]214 @Override public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
215 return Collections.singleton(osm);
216 }
217
218 });
[1169]219 }
[3262]220 return children;
[1169]221 }
[6538]222
[6881]223 /**
224 * Returns the tags to set (key/value pairs).
225 * @return the tags to set (key/value pairs)
226 */
[6538]227 public Map<String, String> getTags() {
228 return Collections.unmodifiableMap(tags);
229 }
[626]230}
Note: See TracBrowser for help on using the repository browser.