1 /*
   2  * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   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 package com.sun.javafx.css;
  26 
  27 import java.util.ArrayList;
  28 import java.util.HashMap;
  29 import java.util.Iterator;
  30 import java.util.List;
  31 import java.util.Map;
  32 
  33 /**
  34  * States represents a set of State. A {@code Node} may be in more than
  35  * one pseudo-class state. {@code States} is used to aggregate the active
  36  * pseudo-class state of a {@code Node}.
  37  */
  38 public final class StyleClassSet  extends BitSet<StyleClass> {
  39 
  40     /** Create an empty set of StyleClass */
  41     public StyleClassSet() {
  42         super();
  43     }
  44     
  45     StyleClassSet(List<String> styleClassNames) {
  46 
  47         int nMax = styleClassNames != null ? styleClassNames.size() : 0;
  48         for(int n=0; n<nMax; n++) {
  49             final String styleClass = styleClassNames.get(n);
  50             if (styleClass == null || styleClass.isEmpty()) continue;
  51 
  52             final StyleClass sc = getStyleClass(styleClass);
  53             add(sc);
  54         }
  55 
  56     }    
  57     
  58     /** {@inheritDoc} */
  59     @Override
  60     public Object[] toArray() {
  61         return toArray(new StyleClass[size()]);
  62     }
  63 
  64     /** {@inheritDoc} */
  65     @Override
  66     public <T> T[] toArray(T[] a) {
  67         if (a.length < size()) {
  68             a = (T[]) new StyleClass[size()];
  69         }
  70         int index = 0;
  71         while(index < getBits().length) {
  72             final long state = getBits()[index];
  73             for(int bit=0; bit<Long.SIZE; bit++) {
  74                 long mask = 1l << bit;
  75                 if ((state & mask) == mask) {
  76                     int n = index * Long.SIZE + bit;
  77                     StyleClass impl = getStyleClass(n);
  78                     a[index++] = (T) impl;
  79                 }
  80                     
  81             }
  82         }
  83         return a;
  84     }
  85 
  86 
  87     @Override
  88     public String toString() {
  89         StringBuilder builder = new StringBuilder("style-classes: [");
  90         Iterator<StyleClass> iter = iterator();
  91         while (iter.hasNext()) {
  92             builder.append(iter.next().getStyleClassName());
  93             if (iter.hasNext()) {
  94                 builder.append(", ");
  95             }
  96         }
  97         builder.append(']');        
  98         return builder.toString();
  99     }
 100    
 101     @Override
 102     protected StyleClass cast(Object o) {
 103         if (o == null) {
 104             throw new NullPointerException("null arg");
 105         }
 106         StyleClass styleClass = (StyleClass) o;
 107         return styleClass;
 108     }
 109     
 110     @Override
 111     protected StyleClass getT(int index) {
 112         return getStyleClass(index);
 113     }
 114 
 115     @Override
 116     protected int getIndex(StyleClass t) {
 117         return t.getIndex();
 118     }
 119 
 120    
 121     /**
 122      */
 123     static StyleClass getStyleClass(String styleClass) {
 124 
 125         if (styleClass == null || styleClass.trim().isEmpty()) {
 126             throw new IllegalArgumentException("styleClass cannot be null or empty String");
 127         }
 128 
 129         StyleClass instance = null;
 130         
 131         final Integer value = styleClassMap.get(styleClass);
 132         final int index = value != null ? value.intValue() : -1;
 133         
 134         final int size = styleClasses.size();
 135         assert index < size;
 136         
 137         if (index != -1 && index < size) {
 138             instance = styleClasses.get(index);
 139         }
 140         
 141         if (instance == null) {
 142             instance = new StyleClass(styleClass, size);
 143             styleClasses.add(instance);
 144             styleClassMap.put(styleClass, Integer.valueOf(size));
 145         }
 146         
 147         return instance;
 148     }
 149 
 150    static StyleClass getStyleClass(int index) {
 151        if (0 <= index && index < styleClasses.size()) {
 152            return styleClasses.get(index);
 153        }
 154        return null;
 155    }
 156    
 157     // package private for unit test purposes
 158     static final Map<String,Integer> styleClassMap = 
 159             new HashMap<String,Integer>(64);
 160 
 161     static final List<StyleClass> styleClasses =
 162             new ArrayList<StyleClass>();
 163      
 164 }
 165