source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleIndex.java@ 15991

Last change on this file since 15991 was 15991, checked in by simon04, 4 years ago

see #18802 - MapCSSStyleIndex: reuse rule if base is the same

File size: 6.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint.mapcss;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.text.MessageFormat;
7import java.util.Collections;
8import java.util.Iterator;
9import java.util.Map;
10import java.util.Set;
11import java.util.stream.Collectors;
12import java.util.stream.Stream;
13
14import org.openstreetmap.josm.data.osm.INode;
15import org.openstreetmap.josm.data.osm.IPrimitive;
16import org.openstreetmap.josm.data.osm.IRelation;
17import org.openstreetmap.josm.data.osm.IWay;
18import org.openstreetmap.josm.data.osm.OsmUtils;
19import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource.MapCSSRuleIndex;
20import org.openstreetmap.josm.tools.JosmRuntimeException;
21import org.openstreetmap.josm.tools.Logging;
22
23/**
24 * Store indexes of {@link MapCSSRule}s using {@link MapCSSRuleIndex} differentiated by {@linkplain Selector#getBase() base}
25 */
26public final class MapCSSStyleIndex {
27
28 /**
29 * Rules for nodes
30 */
31 final MapCSSRuleIndex nodeRules = new MapCSSRuleIndex();
32 /**
33 * Rules for ways without tag area=no
34 */
35 final MapCSSRuleIndex wayRules = new MapCSSRuleIndex();
36 /**
37 * Rules for ways with tag area=no
38 */
39 final MapCSSRuleIndex wayNoAreaRules = new MapCSSRuleIndex();
40 /**
41 * Rules for relations that are not multipolygon relations
42 */
43 final MapCSSRuleIndex relationRules = new MapCSSRuleIndex();
44 /**
45 * Rules for multipolygon relations
46 */
47 final MapCSSRuleIndex multipolygonRules = new MapCSSRuleIndex();
48 /**
49 * rules to apply canvas properties
50 */
51 final MapCSSRuleIndex canvasRules = new MapCSSRuleIndex();
52
53 /**
54 * Clear the index.
55 * <p>
56 * You must own the write lock STYLE_SOURCE_LOCK when calling this method.
57 */
58 public void clear() {
59 nodeRules.clear();
60 wayRules.clear();
61 wayNoAreaRules.clear();
62 relationRules.clear();
63 multipolygonRules.clear();
64 canvasRules.clear();
65 }
66
67 /**
68 * Builds and initializes the index.
69 * <p>
70 * You must own the write lock of STYLE_SOURCE_LOCK when calling this method.
71 */
72 public void buildIndex(Stream<MapCSSRule> ruleStream) {
73 clear();
74 // optimization: filter rules for different primitive types
75 ruleStream.forEach(rule -> {
76 final Map<String, MapCSSRule> selectorsByBase;
77 final Set<String> bases = rule.selectors.stream().map(Selector::getBase).collect(Collectors.toSet());
78 if (bases.size() == 1) {
79 // reuse rule
80 selectorsByBase = Collections.singletonMap(bases.iterator().next(), rule);
81 } else {
82 selectorsByBase = rule.selectors.stream()
83 .collect(Collectors.groupingBy(Selector::getBase,
84 Collectors.collectingAndThen(Collectors.toList(), selectors -> new MapCSSRule(selectors, rule.declaration))));
85 }
86 selectorsByBase.forEach((base, optRule) -> {
87 switch (base) {
88 case Selector.BASE_NODE:
89 nodeRules.add(optRule);
90 break;
91 case Selector.BASE_WAY:
92 wayNoAreaRules.add(optRule);
93 wayRules.add(optRule);
94 break;
95 case Selector.BASE_AREA:
96 wayRules.add(optRule);
97 multipolygonRules.add(optRule);
98 break;
99 case Selector.BASE_RELATION:
100 relationRules.add(optRule);
101 multipolygonRules.add(optRule);
102 break;
103 case Selector.BASE_ANY:
104 nodeRules.add(optRule);
105 wayRules.add(optRule);
106 wayNoAreaRules.add(optRule);
107 relationRules.add(optRule);
108 multipolygonRules.add(optRule);
109 break;
110 case Selector.BASE_CANVAS:
111 canvasRules.add(optRule);
112 break;
113 case Selector.BASE_META:
114 case Selector.BASE_SETTING:
115 case Selector.BASE_SETTINGS:
116 break;
117 default:
118 final RuntimeException e = new JosmRuntimeException(MessageFormat.format("Unknown MapCSS base selector {0}", base));
119 Logging.warn(tr("Failed to index validator rules. Error was: {0}", e.getMessage()));
120 Logging.error(e);
121 }
122 });
123 });
124 initIndex();
125 }
126
127 private void initIndex() {
128 nodeRules.initIndex();
129 wayRules.initIndex();
130 wayNoAreaRules.initIndex();
131 relationRules.initIndex();
132 multipolygonRules.initIndex();
133 canvasRules.initIndex();
134 }
135
136 /**
137 * Get the index of rules for the given primitive.
138 * @param p the primitive
139 * @return index of rules for the given primitive
140 */
141 public MapCSSRuleIndex get(IPrimitive p) {
142 if (p instanceof INode) {
143 return nodeRules;
144 } else if (p instanceof IWay) {
145 if (OsmUtils.isFalse(p.get("area"))) {
146 return wayNoAreaRules;
147 } else {
148 return wayRules;
149 }
150 } else if (p instanceof IRelation) {
151 if (((IRelation<?>) p).isMultipolygon()) {
152 return multipolygonRules;
153 } else if (p.hasKey("#canvas")) {
154 return canvasRules;
155 } else {
156 return relationRules;
157 }
158 } else {
159 throw new IllegalArgumentException("Unsupported type: " + p);
160 }
161 }
162
163 /**
164 * Get a subset of all rules that might match the primitive. Rules not included in the result are guaranteed to
165 * not match this primitive.
166 * <p>
167 * You must have a read lock of STYLE_SOURCE_LOCK when calling this method.
168 *
169 * @param osm the primitive to match
170 * @return An iterator over possible rules in the right order.
171 */
172 public Iterator<MapCSSRule> getRuleCandidates(IPrimitive osm) {
173 return get(osm).getRuleCandidates(osm);
174 }
175}
Note: See TracBrowser for help on using the repository browser.