8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.javafx.css;
27
28
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.Comparator;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36
37 /**
38 * Code to partition selectors into a tree-like structure for faster matching.
39 */
40 public final class SelectorPartitioning {
41
42 /** package accessible */
43 SelectorPartitioning() {}
44
45 /*
46 * Wrapper so that we can have Map<ParitionKey, Partition> even though
47 * the innards of the key might be a String or long[]
48 */
49 private final static class PartitionKey<K> {
50
51 private final K key;
52
53 private PartitionKey(K key) {
54 this.key = key;
55 }
56
57 @Override
58 public boolean equals(Object obj) {
59 if (obj == null) {
60 return false;
61 }
62 if (getClass() != obj.getClass()) {
63 return false;
176 }
177
178 }
179
180 /* A Map for selectors that have an id */
181 private final Map<PartitionKey, Partition> idMap = new HashMap<PartitionKey,Partition>();
182
183 /* A Map for selectors that have an element type */
184 private final Map<PartitionKey, Partition> typeMap = new HashMap<PartitionKey,Partition>();
185
186 /* A Map for selectors that have style classes */
187 private final Map<PartitionKey, Partition> styleClassMap = new HashMap<PartitionKey,Partition>();
188
189 /**
190 * Keep track of the order in which a selector is added to the mapping so
191 * the original order can be restored for the cascade.
192 */
193 private int ordinal;
194
195 /** clear current partitioning */
196 void reset() {
197 idMap.clear();
198 typeMap.clear();
199 styleClassMap.clear();
200 ordinal = 0;
201 }
202
203
204 /**
205 * Helper to lookup an id in the given map, creating and adding a Partition
206 *
207 */
208 private static Partition getPartition(PartitionKey id, Map<PartitionKey,Partition> map) {
209
210 Partition treeNode = map.get(id);
211 if (treeNode == null) {
212 treeNode = new Partition(id);
213 map.put(id, treeNode);
214 }
215 return treeNode;
216 }
217
218 /* Mask that indicates the selector has an id part, e.g. #title */
219 private static final int ID_BIT = 4;
220 /* Mask that indicates the selector has a type part, e.g. Label */
221 private static final int TYPE_BIT = 2;
222 /* Mask that indicates the selector has a styleclass part, e.g. .label */
223 private static final int STYLECLASS_BIT = 1;
224 /* If there is no type part, then * is the default. */
225 private static final PartitionKey WILDCARD = new PartitionKey<String>("*");
226
227 /* Place this selector into the partitioning map. Package accessible */
228 void partition(Selector selector) {
229
230 SimpleSelector simpleSelector = null;
231 if (selector instanceof CompoundSelector) {
232 final List<SimpleSelector> selectors = ((CompoundSelector)selector).getSelectors();
233 final int last = selectors.size()-1;
234 simpleSelector = selectors.get(last);
235 } else {
236 simpleSelector = (SimpleSelector)selector;
237 }
238
239 final String selectorId = simpleSelector.getId();
240 final boolean hasId =
241 (selectorId != null && selectorId.isEmpty() == false);
242 final PartitionKey idKey = hasId
243 ? new PartitionKey(selectorId)
244 : null;
245
246 final String selectorType = simpleSelector.getName();
247 final boolean hasType =
248 (selectorType != null && selectorType.isEmpty() == false);
283 partition = getPartition(typeKey, typeMap);
284 if ((c & STYLECLASS_BIT) == STYLECLASS_BIT) {
285 slot = partition.partition(styleClassKey, styleClassMap);
286 slot.addSelector(selector);
287 } else {
288 partition.addSelector(selector);
289 }
290 break;
291
292 // SimpleSelector always has a type which defaults to '*'
293 case ID_BIT | STYLECLASS_BIT:
294 case ID_BIT:
295 case STYLECLASS_BIT:
296 default:
297 assert(false);
298 }
299
300 }
301
302 /** Get the list of selectors that match this selector. Package accessible */
303 List<Selector> match(String selectorId, String selectorType, Set<StyleClass> selectorStyleClass) {
304
305 final boolean hasId =
306 (selectorId != null && selectorId.isEmpty() == false);
307 final PartitionKey idKey = hasId
308 ? new PartitionKey(selectorId)
309 : null;
310
311 final boolean hasType =
312 (selectorType != null && selectorType.isEmpty() == false);
313 final PartitionKey typeKey = hasType
314 ? new PartitionKey(selectorType)
315 : null;
316
317 final boolean hasStyleClass =
318 (selectorStyleClass != null && selectorStyleClass.size() > 0);
319 final PartitionKey styleClassKey = hasStyleClass
320 ? new PartitionKey<Set<StyleClass>>(selectorStyleClass)
321 : null;
322
323 int c =
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.javafx.css;
27
28 import javafx.css.CompoundSelector;
29 import javafx.css.Selector;
30 import javafx.css.SimpleSelector;
31 import javafx.css.StyleClass;
32
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.Comparator;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40
41 /**
42 * Code to partition selectors into a tree-like structure for faster matching.
43 */
44 public final class SelectorPartitioning {
45
46 /** package accessible */
47 public SelectorPartitioning() {}
48
49 /*
50 * Wrapper so that we can have Map<ParitionKey, Partition> even though
51 * the innards of the key might be a String or long[]
52 */
53 private final static class PartitionKey<K> {
54
55 private final K key;
56
57 private PartitionKey(K key) {
58 this.key = key;
59 }
60
61 @Override
62 public boolean equals(Object obj) {
63 if (obj == null) {
64 return false;
65 }
66 if (getClass() != obj.getClass()) {
67 return false;
180 }
181
182 }
183
184 /* A Map for selectors that have an id */
185 private final Map<PartitionKey, Partition> idMap = new HashMap<PartitionKey,Partition>();
186
187 /* A Map for selectors that have an element type */
188 private final Map<PartitionKey, Partition> typeMap = new HashMap<PartitionKey,Partition>();
189
190 /* A Map for selectors that have style classes */
191 private final Map<PartitionKey, Partition> styleClassMap = new HashMap<PartitionKey,Partition>();
192
193 /**
194 * Keep track of the order in which a selector is added to the mapping so
195 * the original order can be restored for the cascade.
196 */
197 private int ordinal;
198
199 /** clear current partitioning */
200 public void reset() {
201 idMap.clear();
202 typeMap.clear();
203 styleClassMap.clear();
204 ordinal = 0;
205 }
206
207
208 /**
209 * Helper to lookup an id in the given map, creating and adding a Partition
210 *
211 */
212 private static Partition getPartition(PartitionKey id, Map<PartitionKey,Partition> map) {
213
214 Partition treeNode = map.get(id);
215 if (treeNode == null) {
216 treeNode = new Partition(id);
217 map.put(id, treeNode);
218 }
219 return treeNode;
220 }
221
222 /* Mask that indicates the selector has an id part, e.g. #title */
223 private static final int ID_BIT = 4;
224 /* Mask that indicates the selector has a type part, e.g. Label */
225 private static final int TYPE_BIT = 2;
226 /* Mask that indicates the selector has a styleclass part, e.g. .label */
227 private static final int STYLECLASS_BIT = 1;
228 /* If there is no type part, then * is the default. */
229 private static final PartitionKey WILDCARD = new PartitionKey<String>("*");
230
231 /* Place this selector into the partitioning map. Package accessible */
232 public void partition(Selector selector) {
233
234 SimpleSelector simpleSelector = null;
235 if (selector instanceof CompoundSelector) {
236 final List<SimpleSelector> selectors = ((CompoundSelector)selector).getSelectors();
237 final int last = selectors.size()-1;
238 simpleSelector = selectors.get(last);
239 } else {
240 simpleSelector = (SimpleSelector)selector;
241 }
242
243 final String selectorId = simpleSelector.getId();
244 final boolean hasId =
245 (selectorId != null && selectorId.isEmpty() == false);
246 final PartitionKey idKey = hasId
247 ? new PartitionKey(selectorId)
248 : null;
249
250 final String selectorType = simpleSelector.getName();
251 final boolean hasType =
252 (selectorType != null && selectorType.isEmpty() == false);
287 partition = getPartition(typeKey, typeMap);
288 if ((c & STYLECLASS_BIT) == STYLECLASS_BIT) {
289 slot = partition.partition(styleClassKey, styleClassMap);
290 slot.addSelector(selector);
291 } else {
292 partition.addSelector(selector);
293 }
294 break;
295
296 // SimpleSelector always has a type which defaults to '*'
297 case ID_BIT | STYLECLASS_BIT:
298 case ID_BIT:
299 case STYLECLASS_BIT:
300 default:
301 assert(false);
302 }
303
304 }
305
306 /** Get the list of selectors that match this selector. Package accessible */
307 public List<Selector> match(String selectorId, String selectorType, Set<StyleClass> selectorStyleClass) {
308
309 final boolean hasId =
310 (selectorId != null && selectorId.isEmpty() == false);
311 final PartitionKey idKey = hasId
312 ? new PartitionKey(selectorId)
313 : null;
314
315 final boolean hasType =
316 (selectorType != null && selectorType.isEmpty() == false);
317 final PartitionKey typeKey = hasType
318 ? new PartitionKey(selectorType)
319 : null;
320
321 final boolean hasStyleClass =
322 (selectorStyleClass != null && selectorStyleClass.size() > 0);
323 final PartitionKey styleClassKey = hasStyleClass
324 ? new PartitionKey<Set<StyleClass>>(selectorStyleClass)
325 : null;
326
327 int c =
|