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

Revision 5143, 8.0 KB checked in by xeen, 7 weeks ago (diff)

fix #7504 -- Remove superfluous check

  • Property svn:eol-style set to native
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.command;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.util.AbstractMap;
8import java.util.ArrayList;
9import java.util.Arrays;
10import java.util.Collection;
11import java.util.Collections;
12import java.util.HashMap;
13import java.util.LinkedList;
14import java.util.List;
15import java.util.Map;
16
17import javax.swing.Icon;
18
19import org.openstreetmap.josm.Main;
20import org.openstreetmap.josm.data.osm.OsmPrimitive;
21import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
22import org.openstreetmap.josm.gui.DefaultNameFormatter;
23import org.openstreetmap.josm.tools.ImageProvider;
24
25/**
26 * Command that manipulate the key/value structure of several objects. Manages deletion,
27 * adding and modify of values and keys.
28 *
29 * @author imi
30 */
31public class ChangePropertyCommand extends Command {
32    /**
33     * All primitives that are affected with this command.
34     */
35    private final List<OsmPrimitive> objects;
36    /**
37     * Key and value pairs. If value is <code>null</code>, delete all key references with the given
38     * key. Otherwise, change the properties of all objects to the given value or create keys of
39     * those objects that do not have the key yet.
40     */
41    private final AbstractMap<String, String> tags;
42
43    /**
44     * Creates a command to change multiple properties of multiple objects
45     *
46     * @param objects the objects to modify
47     * @param tags the properties to set
48     */
49    public ChangePropertyCommand(Collection<? extends OsmPrimitive> objects, AbstractMap<String, String> tags) {
50        super();
51        this.objects = new LinkedList<OsmPrimitive>();
52        this.tags = tags;
53        init(objects);
54    }
55
56    /**
57     * Creates a command to change one property of multiple objects
58     *
59     * @param objects the objects to modify
60     * @param key the key of the property to set
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    /**
71     * Creates a command to change on property of one object
72     *
73     * @param object the object to modify
74     * @param key the key of the property to set
75     * @param value the value of the key to set
76     */
77    public ChangePropertyCommand(OsmPrimitive object, String key, String value) {
78        this(Arrays.asList(object), key, value);
79    }
80
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
110    @Override public boolean executeCommand() {
111        Main.main.getCurrentDataSet().beginUpdate();
112        try {
113            super.executeCommand(); // save old
114
115            for (OsmPrimitive osm : objects) {
116                // loop over all tags
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()) {
122                        if (oldVal != null)
123                            osm.remove(tag.getKey());
124                    }
125                    else if (oldVal == null || !newVal.equals(oldVal))
126                        osm.put(tag.getKey(), newVal);
127                }
128                // init() only keeps modified primitives. Therefore the modified
129                // bit can be set without further checks.
130                osm.setModified(true);
131            }
132            return true;
133        }
134        finally {
135            Main.main.getCurrentDataSet().endUpdate();
136        }
137    }
138
139    @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
140        modified.addAll(objects);
141    }
142
143    @Override
144    public String getDescriptionText() {
145        String text;
146        if (objects.size() == 1 && tags.size() == 1) {
147            OsmPrimitive primitive = objects.iterator().next();
148            String msg = "";
149            Map.Entry<String, String> entry = tags.entrySet().iterator().next();
150            if (entry.getValue() == null) {
151                switch(OsmPrimitiveType.from(primitive)) {
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;
155                }
156                text = tr(msg, entry.getKey(), primitive.getDisplayName(DefaultNameFormatter.getInstance()));
157            } else {
158                switch(OsmPrimitiveType.from(primitive)) {
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;
162                }
163                text = tr(msg, entry.getKey(), entry.getValue(), primitive.getDisplayName(DefaultNameFormatter.getInstance()));
164            }
165        } else if (objects.size() > 1 && tags.size() == 1) {
166            Map.Entry<String, String> entry = tags.entrySet().iterator().next();
167            if (entry.getValue() == null)
168                text = tr("Remove \"{0}\" for {1} objects", entry.getKey(), objects.size());
169            else
170                text = tr("Set {0}={1} for {2} objects", entry.getKey(), entry.getValue(), objects.size());
171        }
172        else {
173            boolean allnull = true;
174            for (Map.Entry<String, String> tag : this.tags.entrySet()) {
175                if (tag.getValue() != null) {
176                    allnull = false;
177                    break;
178                }
179            }
180
181            if (allnull) {
182                text = tr("Deleted {0} properties for {1} objects", tags.size(), objects.size());
183            } else
184                text = tr("Set {0} properties for {1} objects", tags.size(), objects.size());
185        }
186        return text;
187    }
188
189    @Override
190    public Icon getDescriptionIcon() {
191        return ImageProvider.get("data", "key");
192    }
193
194    @Override public Collection<PseudoCommand> getChildren() {
195        if (objects.size() == 1)
196            return null;
197        List<PseudoCommand> children = new ArrayList<PseudoCommand>();
198        for (final OsmPrimitive osm : objects) {
199            children.add(new PseudoCommand() {
200                @Override public String getDescriptionText() {
201                    return osm.getDisplayName(DefaultNameFormatter.getInstance());
202                }
203
204                @Override public Icon getDescriptionIcon() {
205                    return ImageProvider.get(osm.getDisplayType());
206                }
207
208                @Override public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
209                    return Collections.singleton(osm);
210                }
211
212            });
213        }
214        return children;
215    }
216}
Note: See TracBrowser for help on using the repository browser.