modules/graphics/src/main/java/com/sun/javafx/css/SelectorPartitioning.java

Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization


   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 =