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

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

see #11390 - sonar - squid:S1610 - Java 8: Abstract classes without fields should be converted to interfaces

  • 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 if (nameTags == null) {
166 nameTags = Collections.emptyList();
167 }
168 List<String> result = new ArrayList<>();
169 for (String tag: nameTags) {
170 if (tag == null) {
171 continue;
172 }
173 tag = tag.trim();
174 if (tag.isEmpty()) {
175 continue;
176 }
177 result.add(tag);
178 }
179 return result;
180 }
181
182 /**
183 * Sets the name tags to be looked up in order to build up the label.
184 *
185 * @param nameTags the name tags. null values are ignored.
186 */
187 public void setNameTags(List<String> nameTags) {
188 this.nameTags = buildNameTags(nameTags);
189 }
190
191 /**
192 * Sets the name complement tags to be looked up in order to build up the label.
193 *
194 * @param nameComplementTags the name complement tags. null values are ignored.
195 * @since 6541
196 */
197 public void setNameComplementTags(List<String> nameComplementTags) {
198 this.nameComplementTags = buildNameTags(nameComplementTags);
199 }
200
201 /**
202 * Replies an unmodifiable list of the name tags used to compose the label.
203 *
204 * @return the list of name tags
205 */
206 public List<String> getNameTags() {
207 return Collections.unmodifiableList(nameTags);
208 }
209
210 /**
211 * Replies an unmodifiable list of the name complement tags used to compose the label.
212 *
213 * @return the list of name complement tags
214 * @since 6541
215 */
216 public List<String> getNameComplementTags() {
217 return Collections.unmodifiableList(nameComplementTags);
218 }
219
220 /**
221 * Initializes the name tags to use from a list of default name tags (see
222 * {@link #DEFAULT_NAME_TAGS} and {@link #DEFAULT_NAME_COMPLEMENT_TAGS})
223 * and from name tags configured in the preferences using the keys
224 * <tt>mappaint.nameOrder</tt> and <tt>mappaint.nameComplementOrder</tt>.
225 */
226 public final void initNameTagsFromPreferences() {
227 if (Main.pref == null) {
228 this.nameTags = new ArrayList<>(Arrays.asList(DEFAULT_NAME_TAGS));
229 this.nameComplementTags = new ArrayList<>(Arrays.asList(DEFAULT_NAME_COMPLEMENT_TAGS));
230 } else {
231 this.nameTags = new ArrayList<>(
232 Main.pref.getCollection("mappaint.nameOrder", Arrays.asList(DEFAULT_NAME_TAGS))
233 );
234 this.nameComplementTags = new ArrayList<>(
235 Main.pref.getCollection("mappaint.nameComplementOrder", Arrays.asList(DEFAULT_NAME_COMPLEMENT_TAGS))
236 );
237 }
238 }
239
240 private String getPrimitiveName(OsmPrimitive n) {
241 StringBuilder name = new StringBuilder();
242 if (!n.hasKeys()) return null;
243 for (String rn : nameTags) {
244 String val = n.get(rn);
245 if (val != null) {
246 name.append(val);
247 break;
248 }
249 }
250 for (String rn : nameComplementTags) {
251 String comp = n.get(rn);
252 if (comp != null) {
253 if (name.length() == 0) {
254 name.append(comp);
255 } else {
256 name.append(" (").append(comp).append(')');
257 }
258 break;
259 }
260 }
261 return name.toString();
262 }
263
264 @Override
265 public String compose(OsmPrimitive primitive) {
266 if (primitive == null) return null;
267 return getPrimitiveName(primitive);
268 }
269
270 @Override
271 public String toString() {
272 return '{' + getClass().getSimpleName() + '}';
273 }
274
275 @Override
276 public void preferenceChanged(PreferenceChangeEvent e) {
277 if (e.getKey() != null && e.getKey().startsWith("mappaint.name")) {
278 initNameTagsFromPreferences();
279 }
280 }
281 }
282}
Note: See TracBrowser for help on using the repository browser.