source: josm/trunk/src/org/openstreetmap/josm/gui/conflict/tags/MultiValueResolutionDecision.java@ 9078

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

sonar - Immutable Field

  • Property svn:eol-style set to native
File size: 9.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.conflict.tags;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.text.MessageFormat;
7import java.util.ArrayList;
8import java.util.Collection;
9import java.util.Collections;
10import java.util.List;
11
12import org.openstreetmap.josm.command.ChangePropertyCommand;
13import org.openstreetmap.josm.command.Command;
14import org.openstreetmap.josm.data.osm.OsmPrimitive;
15import org.openstreetmap.josm.data.osm.Tag;
16import org.openstreetmap.josm.data.osm.TagCollection;
17import org.openstreetmap.josm.tools.CheckParameterUtil;
18
19/**
20 * Represents a decision for a conflict due to multiple possible value for a tag.
21 * @since 2008
22 */
23public class MultiValueResolutionDecision {
24
25 /** the type of decision */
26 private MultiValueDecisionType type;
27 /** the collection of tags for which a decision is needed */
28 private final TagCollection tags;
29 /** the selected value if {@link #type} is {@link MultiValueDecisionType#KEEP_ONE} */
30 private String value;
31
32 private static final String[] SUMMABLE_KEYS = new String[] {
33 "capacity(:.+)?", "step_count"
34 };
35
36 /**
37 * constructor
38 */
39 public MultiValueResolutionDecision() {
40 type = MultiValueDecisionType.UNDECIDED;
41 tags = new TagCollection();
42 autoDecide();
43 }
44
45 /**
46 * Creates a new decision for the tag collection <code>tags</code>.
47 * All tags must have the same key.
48 *
49 * @param tags the tags. Must not be null.
50 * @throws IllegalArgumentException if tags is null
51 * @throws IllegalArgumentException if there are more than one keys
52 * @throws IllegalArgumentException if tags is empty
53 */
54 public MultiValueResolutionDecision(TagCollection tags) {
55 CheckParameterUtil.ensureParameterNotNull(tags, "tags");
56 if (tags.isEmpty())
57 throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' must not be empty.", "tags"));
58 if (tags.getKeys().size() != 1)
59 throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' with tags for exactly one key expected. Got {1}.",
60 "tags", tags.getKeys().size()));
61 this.tags = tags;
62 autoDecide();
63 }
64
65 /**
66 * Tries to find the best decision based on the current values.
67 */
68 protected final void autoDecide() {
69 this.type = MultiValueDecisionType.UNDECIDED;
70 // exactly one empty value ? -> delete the tag
71 if (tags.size() == 1 && tags.getValues().contains("")) {
72 this.type = MultiValueDecisionType.KEEP_NONE;
73
74 // exactly one non empty value? -> keep this value
75 } else if (tags.size() == 1) {
76 this.type = MultiValueDecisionType.KEEP_ONE;
77 this.value = tags.getValues().iterator().next();
78 }
79 }
80
81 /**
82 * Apply the decision to keep no value
83 */
84 public void keepNone() {
85 this.type = MultiValueDecisionType.KEEP_NONE;
86 }
87
88 /**
89 * Apply the decision to keep all values
90 */
91 public void keepAll() {
92 this.type = MultiValueDecisionType.KEEP_ALL;
93 }
94
95 /**
96 * Apply the decision to sum all numeric values
97 * @since 7743
98 */
99 public void sumAllNumeric() {
100 this.type = MultiValueDecisionType.SUM_ALL_NUMERIC;
101 }
102
103 /**
104 * Apply the decision to keep exactly one value
105 *
106 * @param value the value to keep
107 * @throws IllegalArgumentException if value is null
108 * @throws IllegalStateException if value is not in the list of known values for this tag
109 */
110 public void keepOne(String value) {
111 CheckParameterUtil.ensureParameterNotNull(value, "value");
112 if (!tags.getValues().contains(value))
113 throw new IllegalStateException(tr("Tag collection does not include the selected value ''{0}''.", value));
114 this.value = value;
115 this.type = MultiValueDecisionType.KEEP_ONE;
116 }
117
118 /**
119 * sets a new value for this
120 *
121 * @param value the new vlaue
122 */
123 public void setNew(String value) {
124 if (value == null) {
125 value = "";
126 }
127 this.value = value;
128 this.type = MultiValueDecisionType.KEEP_ONE;
129
130 }
131
132 /**
133 * marks this as undecided
134 *
135 */
136 public void undecide() {
137 this.type = MultiValueDecisionType.UNDECIDED;
138 }
139
140 /**
141 * Replies the chosen value
142 *
143 * @return the chosen value
144 * @throws IllegalStateException if this resolution is not yet decided
145 */
146 public String getChosenValue() {
147 switch(type) {
148 case UNDECIDED: throw new IllegalStateException(tr("Not decided yet."));
149 case KEEP_ONE: return value;
150 case SUM_ALL_NUMERIC: return tags.getSummedValues(getKey());
151 case KEEP_ALL: return tags.getJoinedValues(getKey());
152 case KEEP_NONE:
153 default: return null;
154 }
155 }
156
157 /**
158 * Replies the list of possible, non empty values
159 *
160 * @return the list of possible, non empty values
161 */
162 public List<String> getValues() {
163 List<String> ret = new ArrayList<>(tags.getValues());
164 ret.remove("");
165 ret.remove(null);
166 Collections.sort(ret);
167 return ret;
168 }
169
170 /**
171 * Replies the key of the tag to be resolved by this resolution
172 *
173 * @return the key of the tag to be resolved by this resolution
174 */
175 public String getKey() {
176 return tags.getKeys().iterator().next();
177 }
178
179 /**
180 * Replies true if the empty value is a possible value in this resolution
181 *
182 * @return true if the empty value is a possible value in this resolution
183 */
184 public boolean canKeepNone() {
185 return tags.getValues().contains("");
186 }
187
188 /**
189 * Replies true, if this resolution has more than 1 possible non-empty values
190 *
191 * @return true, if this resolution has more than 1 possible non-empty values
192 */
193 public boolean canKeepAll() {
194 return getValues().size() > 1;
195 }
196
197 /**
198 * Replies true, if summing all numeric values is a possible value in this resolution
199 *
200 * @return true, if summing all numeric values is a possible value in this resolution
201 * @since 7743
202 */
203 public boolean canSumAllNumeric() {
204 if (!canKeepAll()) {
205 return false;
206 }
207 for (String key : SUMMABLE_KEYS) {
208 if (getKey().matches(key)) {
209 return true;
210 }
211 }
212 return false;
213 }
214
215 /**
216 * Replies true if this resolution is decided
217 *
218 * @return true if this resolution is decided
219 */
220 public boolean isDecided() {
221 return !type.equals(MultiValueDecisionType.UNDECIDED);
222 }
223
224 /**
225 * Replies the type of the resolution
226 *
227 * @return the type of the resolution
228 */
229 public MultiValueDecisionType getDecisionType() {
230 return type;
231 }
232
233 /**
234 * Applies the resolution to an {@link OsmPrimitive}
235 *
236 * @param primitive the primitive
237 * @throws IllegalStateException if this resolution is not resolved yet
238 *
239 */
240 public void applyTo(OsmPrimitive primitive) {
241 if (primitive == null) return;
242 if (!isDecided())
243 throw new IllegalStateException(tr("Not decided yet."));
244 String key = tags.getKeys().iterator().next();
245 if (type.equals(MultiValueDecisionType.KEEP_NONE)) {
246 primitive.remove(key);
247 } else {
248 primitive.put(key, getChosenValue());
249 }
250 }
251
252 /**
253 * Applies this resolution to a collection of primitives
254 *
255 * @param primitives the collection of primitives
256 * @throws IllegalStateException if this resolution is not resolved yet
257 */
258 public void applyTo(Collection<? extends OsmPrimitive> primitives) {
259 if (primitives == null) return;
260 for (OsmPrimitive primitive: primitives) {
261 if (primitive == null) {
262 continue;
263 }
264 applyTo(primitive);
265 }
266 }
267
268 /**
269 * Builds a change command for applying this resolution to a primitive
270 *
271 * @param primitive the primitive
272 * @return the change command
273 * @throws IllegalArgumentException if primitive is null
274 * @throws IllegalStateException if this resolution is not resolved yet
275 */
276 public Command buildChangeCommand(OsmPrimitive primitive) {
277 CheckParameterUtil.ensureParameterNotNull(primitive, "primitive");
278 if (!isDecided())
279 throw new IllegalStateException(tr("Not decided yet."));
280 String key = tags.getKeys().iterator().next();
281 return new ChangePropertyCommand(primitive, key, getChosenValue());
282 }
283
284 /**
285 * Builds a change command for applying this resolution to a collection of primitives
286 *
287 * @param primitives the collection of primitives
288 * @return the change command
289 * @throws IllegalArgumentException if primitives is null
290 * @throws IllegalStateException if this resolution is not resolved yet
291 */
292 public Command buildChangeCommand(Collection<? extends OsmPrimitive> primitives) {
293 CheckParameterUtil.ensureParameterNotNull(primitives, "primitives");
294 if (!isDecided())
295 throw new IllegalStateException(tr("Not decided yet."));
296 String key = tags.getKeys().iterator().next();
297 return new ChangePropertyCommand(primitives, key, getChosenValue());
298 }
299
300 /**
301 * Replies a tag representing the current resolution. Null, if this resolution is not resolved yet.
302 *
303 * @return a tag representing the current resolution. Null, if this resolution is not resolved yet
304 */
305 public Tag getResolution() {
306 switch(type) {
307 case SUM_ALL_NUMERIC: return new Tag(getKey(), tags.getSummedValues(getKey()));
308 case KEEP_ALL: return new Tag(getKey(), tags.getJoinedValues(getKey()));
309 case KEEP_ONE: return new Tag(getKey(), value);
310 case KEEP_NONE: return new Tag(getKey(), "");
311 case UNDECIDED:
312 default: return null;
313 }
314 }
315}
Note: See TracBrowser for help on using the repository browser.