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

Last change on this file since 12854 was 12854, checked in by bastiK, 7 years ago

see #15229 - fix checkstyle warnings

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