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 
  26 package javafx.css;
  27 
  28 import com.sun.javafx.css.SelectorPartitioning;
  29 
  30 import java.util.Arrays;
  31 import java.util.Collection;
  32 import java.util.List;
  33 import javafx.scene.paint.Color;
  34 import org.junit.Test;
  35 import static org.junit.Assert.*;
  36 
  37 import org.junit.runner.RunWith;
  38 import org.junit.runners.Parameterized;
  39 import org.junit.runners.Parameterized.Parameters;
  40 
  41 @RunWith(Parameterized.class)
  42 public class SelectorPartitioningTest {
  43     
  44     public SelectorPartitioningTest(final Data data) {
  45         this.data = data;
  46         this.instance = new SelectorPartitioning();
  47     }
  48     private final Data data;
  49     private final SelectorPartitioning instance;
  50 
  51     private static class Data {
  52         final Color  color;
  53         final String stylesheetText;
  54         
  55         Data(Color color, String stylesheetText) {
  56             this.color = color;
  57             this.stylesheetText = stylesheetText;
  58         }
  59         
  60     }
  61     
  62     private static class SimpleData extends Data {
  63         
  64         final SimpleSelector selector;
  65         final boolean matches;
  66         
  67         SimpleData(String type, String styleClass, String id, Color color) {
  68             this(type, styleClass, id, color, true);
  69         }
  70         SimpleData(String type, String styleClass, String id, Color color, boolean matches) {
  71             super(color, (new StringBuilder()
  72                     .append((type != null ? type : "*"))
  73                     .append((styleClass != null ? ".".concat(styleClass) : ""))
  74                     .append((id != null ? "#".concat(id) : ""))
  75                     .append("{-fx-fill: rgb(")
  76                     .append(Double.valueOf(color.getRed()*255).intValue()).append(",")
  77                     .append(Double.valueOf(color.getGreen()*255).intValue()).append(",")
  78                     .append(Double.valueOf(color.getBlue()*255).intValue()).append(");}")
  79                 ).toString());
  80             List<String> styleClasses = 
  81                 styleClass != null ? Arrays.asList(styleClass.split("\\.")) : null;
  82             this.selector = 
  83                 new SimpleSelector(type, styleClasses, null, id);            
  84             this.matches = matches;
  85         }
  86     }
  87     
  88     private static class ComplexData extends Data {
  89 
  90         final SimpleData[] data;
  91         final SimpleSelector selector;
  92         final int matches;
  93         
  94         ComplexData(SimpleSelector selector, SimpleData... data) {
  95             super(Color.TRANSPARENT, combineStylesheets(data));
  96             this.data = data;
  97             this.selector = selector;
  98             int n = 0;
  99             for (SimpleData datum : data) {
 100                 if (datum.matches) n += 1;
 101             }
 102             this.matches = n;
 103         }
 104         
 105         static String combineStylesheets(Data... data) {
 106             StringBuilder buf = new StringBuilder();
 107             for (Data datum : data) {
 108                 buf.append(datum.stylesheetText).append('\n');
 109             }
 110             return buf.toString();
 111         }
 112     }
 113     
 114     
 115     @Parameters
 116     public static Collection data() {
 117 
 118         int red = 0;
 119         int green = 0;
 120         int blue = 0;
 121         return Arrays.asList(new Object[] {
 122             /* selector = * */
 123             new Object[] {new SimpleData("*", null, null, Color.rgb(red += 10, 0, 0))},
 124             /* selector = A */
 125             new Object[] {new SimpleData("A", null, null, Color.rgb(red += 10, 0, 0))},
 126             /* selector = * A.b */
 127             new Object[] {new SimpleData("A", "b", null, Color.rgb(red += 10, 0, 0))},
 128             /* selector = A#c */
 129             new Object[] {new SimpleData("A", null, "c", Color.rgb(red += 10, 0, 0))},
 130             /* selector = A.b#c */
 131             new Object[] {new SimpleData("A", "b", "c", Color.rgb(red += 10, 0, 0))},
 132             /* selector = *.b */
 133             new Object[] {new SimpleData("*", "b", null, Color.rgb(red += 10, 0, 0))},
 134             /* selector = *#c */
 135             new Object[] {new SimpleData("*", null, "c", Color.rgb(red += 10, 0, 0))},
 136             /* selector = *.b#c */
 137             new Object[] {new SimpleData("*", "b", "c", Color.rgb(red += 10, 0, 0))},
 138             
 139             new Object[] {
 140                 new ComplexData(
 141                     (SimpleSelector)Selector.createSelector("*.b"),
 142                     new SimpleData("*", "b", null, Color.rgb(0, green += 10, 0), true),
 143                     new SimpleData("*", "c", null, Color.rgb(0, green += 10, 0), false),
 144                     new SimpleData("*", "b.c", null, Color.rgb(0, green += 10, 0), false)
 145                 )},
 146             new Object[] {
 147                 new ComplexData(
 148                     (SimpleSelector)Selector.createSelector("*.b.c"),
 149                     new SimpleData("*", "b", null, Color.rgb(0, green += 10, 0), true),
 150                     new SimpleData("*", "c", null, Color.rgb(0, green += 10, 0), true),
 151                     new SimpleData("*", "b.c", null, Color.rgb(0, green += 10, 0), true)
 152                 )},
 153             new Object[] {
 154                 new ComplexData(
 155                     (SimpleSelector)Selector.createSelector("A.b"),
 156                     new SimpleData("*", "b", null, Color.rgb(0, green += 10, 0), true),
 157                     new SimpleData("A", "b", null, Color.rgb(0, green += 10, 0), true),
 158                     new SimpleData("*", null, null, Color.rgb(0, green += 10, 0), true),
 159                     new SimpleData("*", "c", null, Color.rgb(0, green += 10, 0), false),
 160                     new SimpleData("*", "b.c", null, Color.rgb(0, green += 10, 0), false)
 161                 )},
 162             new Object[] {
 163                 new ComplexData(
 164                     (SimpleSelector)Selector.createSelector("A.c"),
 165                     new SimpleData("*", "b", null, Color.rgb(0, green += 10, 0), false),
 166                     new SimpleData("A", "b", null, Color.rgb(0, green += 10, 0), false),
 167                     new SimpleData("*", null, null, Color.rgb(0, green += 10, 0), true),
 168                     new SimpleData("*", "c", null, Color.rgb(0, green += 10, 0), true),
 169                     new SimpleData("*", "b.c", null, Color.rgb(0, green += 10, 0), false)
 170                 )},
 171             new Object[] {
 172                 new ComplexData(
 173                     (SimpleSelector)Selector.createSelector("A.b.c"),
 174                     new SimpleData("*", "b", null, Color.rgb(0, green += 10, 0), true),
 175                     new SimpleData("A", "b", null, Color.rgb(0, green += 10, 0), true),
 176                     new SimpleData("*", null, null, Color.rgb(0, green += 10, 0), true),
 177                     new SimpleData("*", "c", null, Color.rgb(0, green += 10, 0), true),
 178                     new SimpleData("*", "b.c", null, Color.rgb(0, green += 10, 0), true)
 179                 )}
 180         });
 181     }    
 182 
 183     @Test
 184     public void testSelectorPartitionAndMatch() {
 185 
 186         Stylesheet stylesheet = 
 187                 new CssParser().parse(data.stylesheetText);
 188                 
 189         for (Rule rule : stylesheet.getRules()) {
 190             for (Selector selector : rule.getUnobservedSelectorList()) {
 191                 instance.partition(selector);
 192             }
 193         }
 194         
 195         if (data instanceof SimpleData) {
 196             testWithSimpleData((SimpleData)data, stylesheet);            
 197         } else {
 198             testWithComplexData((ComplexData)data, stylesheet);
 199         }
 200     }
 201     
 202     private void testWithSimpleData(SimpleData simpleData, Stylesheet stylesheet) {
 203                 
 204         SimpleSelector simple = simpleData.selector;
 205         
 206         List<Selector> matched = instance.match(simple.getId(), simple.getName(), simple.getStyleClassSet());
 207         
 208         assertEquals(1,matched.size());
 209         Selector selector = matched.get(0);
 210 
 211         Rule rule = selector.getRule();
 212 
 213         assertEquals(1,rule.getUnobservedDeclarationList().size());
 214         Declaration decl = rule.getUnobservedDeclarationList().get(0);
 215         
 216         assertEquals("-fx-fill", decl.property);
 217         
 218         Color color = (Color)decl.parsedValue.convert(null);
 219         
 220         assertEquals(simpleData.selector.toString(), data.color.getRed(), color.getRed(), 0.00001);
 221         assertEquals(simpleData.selector.toString(), data.color.getGreen(), color.getGreen(), 0.00001);
 222         assertEquals(simpleData.selector.toString(), data.color.getBlue(), color.getBlue(), 0.00001);
 223                 
 224     }
 225     
 226     private void testWithComplexData(ComplexData complexData, Stylesheet stylesheet) {
 227                 
 228         SimpleSelector simple = complexData.selector;
 229         
 230         List<Selector> matched = instance.match(simple.getId(), simple.getName(), simple.getStyleClassSet());
 231         assertEquals(complexData.matches, matched.size());
 232         
 233         for(Selector s1 : matched) {
 234             for (SimpleData datum : complexData.data) {
 235                 Selector s2 = datum.selector;
 236                 if (s1.equals(s2)) {
 237                     assertTrue(s1.toString() + " != " + s2.toString(), datum.matches);
 238                 }
 239             }
 240         }
 241 
 242     }
 243     
 244 }