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

Last change on this file since 6524 was 6507, checked in by simon04, 10 years ago

fix #9110 - i18n: fix errors in usage of plural forms

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