source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategy.java@ 8849

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

sonar - squid:S1643 - Strings should not be concatenated using '+' in a loop
sonar - squid:S1640 - Maps with keys that are enum values should be replaced with EnumMap

  • Property svn:eol-style set to native
File size: 10.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint;
3
4import java.util.ArrayList;
5import java.util.Arrays;
6import java.util.Collections;
7import java.util.List;
8
9import org.openstreetmap.josm.Main;
10import org.openstreetmap.josm.data.osm.OsmPrimitive;
11import org.openstreetmap.josm.tools.LanguageInfo;
12
13/**
14 * <p>Provides an abstract parent class and three concrete sub classes for various
15 * strategies on how to compose the text label which can be rendered close to a node
16 * or within an area in an OSM map.</p>
17 *
18 * <p>The three strategies below support three rules for composing a label:
19 * <ul>
20 * <li>{@link StaticLabelCompositionStrategy} - the label is given by a static text
21 * specified in the MapCSS style file</li>
22 *
23 * <li>{@link TagLookupCompositionStrategy} - the label is given by the content of a
24 * tag whose name specified in the MapCSS style file</li>
25 *
26 * <li>{@link DeriveLabelFromNameTagsCompositionStrategy} - the label is given by the value
27 * of one
28 * of the configured "name tags". The list of relevant name tags can be configured
29 * in the JOSM preferences
30 * content of a tag whose name specified in the MapCSS style file, see the preference
31 * options <tt>mappaint.nameOrder</tt> and <tt>mappaint.nameComplementOrder</tt>.</li>
32 * </ul>
33 *
34 */
35public abstract class LabelCompositionStrategy {
36
37 /**
38 * Replies the text value to be rendered as label for the primitive {@code primitive}.
39 *
40 * @param primitive the primitive
41 *
42 * @return the text value to be rendered or null, if primitive is null or
43 * if no suitable value could be composed
44 */
45 public abstract String compose(OsmPrimitive primitive);
46
47 public static class StaticLabelCompositionStrategy extends LabelCompositionStrategy {
48 private String defaultLabel;
49
50 public StaticLabelCompositionStrategy(String defaultLabel) {
51 this.defaultLabel = defaultLabel;
52 }
53
54 @Override
55 public String compose(OsmPrimitive primitive) {
56 return defaultLabel;
57 }
58
59 public String getDefaultLabel() {
60 return defaultLabel;
61 }
62
63 @Override
64 public String toString() {
65 return '{' + getClass().getSimpleName() + " defaultLabel=" + defaultLabel + '}';
66 }
67
68 @Override
69 public int hashCode() {
70 final int prime = 31;
71 int result = 1;
72 result = prime * result + ((defaultLabel == null) ? 0 : defaultLabel.hashCode());
73 return result;
74 }
75
76 @Override
77 public boolean equals(Object obj) {
78 if (this == obj)
79 return true;
80 if (obj == null)
81 return false;
82 if (getClass() != obj.getClass())
83 return false;
84 StaticLabelCompositionStrategy other = (StaticLabelCompositionStrategy) obj;
85 if (defaultLabel == null) {
86 if (other.defaultLabel != null)
87 return false;
88 } else if (!defaultLabel.equals(other.defaultLabel))
89 return false;
90 return true;
91 }
92 }
93
94 public static class TagLookupCompositionStrategy extends LabelCompositionStrategy {
95
96 private String defaultLabelTag;
97
98 public TagLookupCompositionStrategy(String defaultLabelTag) {
99 if (defaultLabelTag != null) {
100 defaultLabelTag = defaultLabelTag.trim();
101 if (defaultLabelTag.isEmpty()) {
102 defaultLabelTag = null;
103 }
104 }
105 this.defaultLabelTag = defaultLabelTag;
106 }
107
108 @Override
109 public String compose(OsmPrimitive primitive) {
110 if (defaultLabelTag == null) return null;
111 if (primitive == null) return null;
112 return primitive.get(defaultLabelTag);
113 }
114
115 public String getDefaultLabelTag() {
116 return defaultLabelTag;
117 }
118
119 @Override
120 public String toString() {
121 return '{' + getClass().getSimpleName() + " defaultLabelTag=" + defaultLabelTag + '}';
122 }
123
124 @Override
125 public int hashCode() {
126 final int prime = 31;
127 int result = 1;
128 result = prime * result + ((defaultLabelTag == null) ? 0 : defaultLabelTag.hashCode());
129 return result;
130 }
131
132 @Override
133 public boolean equals(Object obj) {
134 if (this == obj)
135 return true;
136 if (obj == null)
137 return false;
138 if (getClass() != obj.getClass())
139 return false;
140 TagLookupCompositionStrategy other = (TagLookupCompositionStrategy) obj;
141 if (defaultLabelTag == null) {
142 if (other.defaultLabelTag != null)
143 return false;
144 } else if (!defaultLabelTag.equals(other.defaultLabelTag))
145 return false;
146 return true;
147 }
148 }
149
150 public static class DeriveLabelFromNameTagsCompositionStrategy extends LabelCompositionStrategy {
151
152 /**
153 * The list of default name tags from which a label candidate is derived.
154 */
155 private static final String[] DEFAULT_NAME_TAGS = {
156 "name:" + LanguageInfo.getJOSMLocaleCode(),
157 "name",
158 "int_name",
159 "distance",
160 "ref",
161 "operator",
162 "brand",
163 "addr:housenumber"
164 };
165
166 /**
167 * The list of default name complement tags from which a label candidate is derived.
168 */
169 private static final String[] DEFAULT_NAME_COMPLEMENT_TAGS = {
170 "capacity"
171 };
172
173 private List<String> nameTags = new ArrayList<>();
174 private List<String> nameComplementTags = new ArrayList<>();
175
176 /**
177 * <p>Creates the strategy and initializes its name tags from the preferences.</p>
178 *
179 * <p><strong>Note:</strong> If the list of name tags in the preferences changes, strategy instances
180 * are not notified. It's up to the client to listen to preference changes and
181 * invoke {@link #initNameTagsFromPreferences()} accordingly.</p>
182 *
183 */
184 public DeriveLabelFromNameTagsCompositionStrategy() {
185 initNameTagsFromPreferences();
186 }
187
188 private static List<String> buildNameTags(List<String> nameTags) {
189 if (nameTags == null) {
190 nameTags = Collections.emptyList();
191 }
192 List<String> result = new ArrayList<>();
193 for (String tag: nameTags) {
194 if (tag == null) {
195 continue;
196 }
197 tag = tag.trim();
198 if (tag.isEmpty()) {
199 continue;
200 }
201 result.add(tag);
202 }
203 return result;
204 }
205
206 /**
207 * Sets the name tags to be looked up in order to build up the label.
208 *
209 * @param nameTags the name tags. null values are ignored.
210 */
211 public void setNameTags(List<String> nameTags) {
212 this.nameTags = buildNameTags(nameTags);
213 }
214
215 /**
216 * Sets the name complement tags to be looked up in order to build up the label.
217 *
218 * @param nameComplementTags the name complement tags. null values are ignored.
219 * @since 6541
220 */
221 public void setNameComplementTags(List<String> nameComplementTags) {
222 this.nameComplementTags = buildNameTags(nameComplementTags);
223 }
224
225 /**
226 * Replies an unmodifiable list of the name tags used to compose the label.
227 *
228 * @return the list of name tags
229 */
230 public List<String> getNameTags() {
231 return Collections.unmodifiableList(nameTags);
232 }
233
234 /**
235 * Replies an unmodifiable list of the name complement tags used to compose the label.
236 *
237 * @return the list of name complement tags
238 * @since 6541
239 */
240 public List<String> getNameComplementTags() {
241 return Collections.unmodifiableList(nameComplementTags);
242 }
243
244 /**
245 * Initializes the name tags to use from a list of default name tags (see
246 * {@link #DEFAULT_NAME_TAGS} and {@link #DEFAULT_NAME_COMPLEMENT_TAGS})
247 * and from name tags configured in the preferences using the keys
248 * <tt>mappaint.nameOrder</tt> and <tt>mappaint.nameComplementOrder</tt>.
249 */
250 public final void initNameTagsFromPreferences() {
251 if (Main.pref == null) {
252 this.nameTags = new ArrayList<>(Arrays.asList(DEFAULT_NAME_TAGS));
253 this.nameComplementTags = new ArrayList<>(Arrays.asList(DEFAULT_NAME_COMPLEMENT_TAGS));
254 } else {
255 this.nameTags = new ArrayList<>(
256 Main.pref.getCollection("mappaint.nameOrder", Arrays.asList(DEFAULT_NAME_TAGS))
257 );
258 this.nameComplementTags = new ArrayList<>(
259 Main.pref.getCollection("mappaint.nameComplementOrder", Arrays.asList(DEFAULT_NAME_COMPLEMENT_TAGS))
260 );
261 }
262 }
263
264 private String getPrimitiveName(OsmPrimitive n) {
265 StringBuilder name = new StringBuilder();
266 if (!n.hasKeys()) return null;
267 for (String rn : nameTags) {
268 String val = n.get(rn);
269 if (val != null) {
270 name.append(val);
271 break;
272 }
273 }
274 for (String rn : nameComplementTags) {
275 String comp = n.get(rn);
276 if (comp != null) {
277 if (name.length() == 0) {
278 name.append(comp);
279 } else {
280 name.append(" (").append(comp).append(')');
281 }
282 break;
283 }
284 }
285 return name.toString();
286 }
287
288 @Override
289 public String compose(OsmPrimitive primitive) {
290 if (primitive == null) return null;
291 return getPrimitiveName(primitive);
292 }
293
294 @Override
295 public String toString() {
296 return "{" + getClass().getSimpleName() +'}';
297 }
298 }
299}
Note: See TracBrowser for help on using the repository browser.