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

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

refactor handling of null values - use Java 8 Optional where possible

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