1 /*
   2  * Copyright (c) 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 javafx.css.converter.EnumConverter;
  29 import javafx.beans.property.Property;
  30 import javafx.geometry.Insets;
  31 import javafx.scene.effect.Effect;
  32 import javafx.scene.paint.Color;
  33 import javafx.scene.paint.Paint;
  34 import javafx.scene.text.Font;
  35 import javafx.util.Duration;
  36 import javafx.util.Pair;
  37 
  38 import java.util.ArrayList;
  39 import java.util.Collections;
  40 import java.util.HashMap;
  41 import java.util.List;
  42 import java.util.Map;
  43 import java.util.NoSuchElementException;
  44 import java.util.function.Function;
  45 
  46 /**
  47  * Methods for creating instances of StyleableProperty with corresponding CssMetaData created behind the scenes.
  48  * These methods greatly reduce the amount of boiler-plate code needed to implement the StyleableProperty
  49  * and CssMetaData.
  50  * These methods take a Function<? extends Styleable, StyleableProperty<?>> which returns a
  51  * reference to the property itself. See the example below. Note that for efficient use of memory and for better
  52  * CSS performance, creating the <code>StyleablePropertyFactory</code> as a static member, as shown below, is recommended.
  53  * <code><pre>
  54  public final class MyButton extends Button {
  55 
  56      private static final{@literal StyleablePropertyFactory<MyButton>} FACTORY = new{@literal StyleablePropertyFactory<>}(Button.getClassCssMetaData());
  57 
  58      MyButton(String labelText) {
  59          super(labelText);
  60          getStyleClass().add("my-button");
  61      }
  62 
  63      // Typical JavaFX property implementation
  64      public{@literal ObservableValue<Boolean>} selectedProperty() { return ({@literal ObservableValue<Boolean>})selected; }
  65      public final boolean isSelected() { return selected.getValue(); }
  66      public final void setSelected(boolean isSelected) { selected.setValue(isSelected); }
  67 
  68      // StyleableProperty implementation reduced to one line
  69      private final{@literal StyleableProperty<Boolean>} selected =
  70          FACTORY.createStyleableBooleanProperty(this, "selected", "-my-selected", s{@literal ->} s.selected);
  71 
  72     {@literal @}Override
  73      public{@literal List<CssMetaData<? extends Styleable, ?>>} getControlCssMetaData() {
  74          return FACTORY.getCssMetaData();
  75      }
  76 
  77  }
  78  * </pre></code>
  79  * <p>The example above is the simplest use of <code>StyleablePropertyFactory</code>. But, this use does not provide the
  80  * static CssMetaData that is useful for {@code getClassCssMetaData()}, which is described in the javadoc for
  81  * {@link CssMetaData)}. Static CssMetaData can, however, be created via <code>StyleablePropertyFactory</code> methods
  82  * and will be returned by the methods which create StyleableProperty instances, as the example below illustrates.
  83  * Note that the static method <code>getClassCssMetaData()</code> is a convention used throughout the JavaFX code base
  84  * but the <code>getClassCssMetaData()</code> method itself is not used at runtime.</p>
  85  * <code><pre>
  86  public final class MyButton extends Button {
  87 
  88      private static final{@literal StyleablePropertyFactory<MyButton>} FACTORY =
  89          new{@literal StyleablePropertyFactory<>}(Button.getClassCssMetaData());
  90 
  91      private static final{@literal CssMetaData<MyButton, Boolean>} SELECTED =
  92          FACTORY.createBooleanCssMetaData("-my-selected", s{@literal ->} s.selected, false, false);
  93 
  94      MyButton(String labelText) {
  95          super(labelText);
  96          getStyleClass().add("my-button");
  97      }
  98 
  99      // Typical JavaFX property implementation
 100      public{@literal ObservableValue<Boolean>} selectedProperty() { return ({@literal ObservableValue<Boolean>})selected; }
 101      public final boolean isSelected() { return selected.getValue(); }
 102      public final void setSelected(boolean isSelected) { selected.setValue(isSelected); }
 103 
 104      // StyleableProperty implementation reduced to one line
 105      private final{@literal StyleableProperty<Boolean>} selected =
 106          new SimpleStyleableBooleanProperty(SELECTED, this, "selected");
 107 
 108      public static {@literal List<CssMetaData<? extends Styleable, ?>>} getClassCssMetaData() {
 109          return FACTORY.getCssMetaData();
 110      }
 111 
 112      {@literal @}Override
 113      public{@literal List<CssMetaData<? extends Styleable, ?>>} getControlCssMetaData() {
 114          return FACTORY.getCssMetaData();
 115      }
 116 
 117  }
 118  * </pre></code>
 119  * <p>The same can be accomplished with an inner-class. The previous example called {@code new SimpleStyleableBooleanProperty}
 120  * to create the <code>selected</code> property. This example uses the factory to access the <code>CssMetaData</code>
 121  * that was created along with the anonymous inner-class. For all intents and purposes, the two examples are the same.</p>
 122  * <code><pre>
 123  public final class MyButton extends Button {
 124 
 125      private static final{@literal StyleablePropertyFactory<MyButton>} FACTORY =
 126          new{@literal StyleablePropertyFactory<>}(Button.getClassCssMetaData()) {
 127          {
 128              createBooleanCssMetaData("-my-selected", s{@literal ->} s.selected, false, false);
 129          }
 130      }
 131 
 132 
 133      MyButton(String labelText) {
 134          super(labelText);
 135          getStyleClass().add("my-button");
 136      }
 137 
 138      // Typical JavaFX property implementation
 139      public{@literal ObservableValue<Boolean>} selectedProperty() { return ({@literal ObservableValue<Boolean>})selected; }
 140      public final boolean isSelected() { return selected.getValue(); }
 141      public final void setSelected(boolean isSelected) { selected.setValue(isSelected); }
 142 
 143      // StyleableProperty implementation reduced to one line
 144      private final{@literal StyleableProperty<Boolean>} selected =
 145          new SimpleStyleableBooleanProperty(this, "selected", "my-selected");
 146 
 147      public static {@literal List<CssMetaData<? extends Styleable, ?>>} getClassCssMetaData() {
 148          return FACTORY.getCssMetaData();
 149      }
 150 
 151      {@literal @}Override
 152      public{@literal List<CssMetaData<? extends Styleable, ?>>} getControlCssMetaData() {
 153          return FACTORY.getCssMetaData();
 154      }
 155 
 156  }
 157  * </pre></code>
 158  * <p><span class="simpleTagLabel">Caveats:</span></p>
 159  * The only option for creating a StyleableProperty with a number value is to create a StyleableProperty&lt;Number&gt;</Number>.
 160  * The return value from the <code>getValue()</code> method of the StyleableProperty is a Number. Therefore,
 161  * the <code>get</code> method of the JavaFX property needs to call the correct <code>value</code> method for the return type.
 162  * For example,
 163  * <code><pre>
 164      public ObservableValue<Double> offsetProperty() { return (ObservableValue<Double>)offset; }
 165      public Double getOffset() { return offset.getValue().doubleValue(); }
 166      public void setOffset(Double value) { offset.setValue(value); }
 167      private final StyleableProperty<Number> offset = FACTORY.createStyleableNumberProperty(this, "offset", "-my-offset", s -> ((MyButton)s).offset);
 168  * <br>
 169  * </pre></code>
 170  * @param <S> The type of Styleable
 171  * @since JavaFX 8u40
 172  */
 173 public class StyleablePropertyFactory<S extends Styleable> {
 174 
 175     /**
 176      * The constructor is passed the CssMetaData of the parent class of &lt;S&gt;, typically by calling the
 177      * static <code>getClassCssMetaData()</code> method of the parent.
 178      * @param parentCssMetaData The CssMetaData of the parent class of &lt;S&gt;, or null.
 179      */
 180     public StyleablePropertyFactory(List<CssMetaData<? extends Styleable, ?>> parentCssMetaData) {
 181         this.metaDataList = new ArrayList<>();
 182         this.unmodifiableMetaDataList = Collections.unmodifiableList(this.metaDataList);
 183         if (parentCssMetaData != null) this.metaDataList.addAll(parentCssMetaData);
 184         this.metaDataMap = new HashMap<>();
 185     }
 186 
 187 
 188     /**
 189      * Get the CssMetaData for the given Styleable. For a Node other than a Control, this method should be
 190      * called from the {@link javafx.css.Styleable#getCssMetaData()} method. For a Control, this method should be called
 191      * from the {@link javafx.scene.control.Control#getControlCssMetaData()} method.
 192      */
 193     public final List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 194         return unmodifiableMetaDataList;
 195     }
 196 
 197     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 198     //
 199     // StyleableProperty<Boolean>
 200     //
 201     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 202 
 203     /**
 204      * Create a StyleableProperty&lt;Boolean&gt; with initial value and inherit flag.
 205      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 206      * @param propertyName The field name of the StyleableProperty&lt;Boolean&gt;
 207      * @param cssProperty The CSS property name
 208      * @param function A function that returns the StyleableProperty&lt;Boolean&gt; that was created by this method call.
 209      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 210      * @param inherits Whether or not the CSS style can be inherited by child nodes                     
 211      */
 212     public final StyleableProperty<Boolean> createStyleableBooleanProperty(
 213             S styleable,
 214             String propertyName,
 215             String cssProperty,
 216             Function<S, StyleableProperty<Boolean>> function,
 217             boolean initialValue,
 218             boolean inherits) {
 219 
 220         CssMetaData<S,Boolean> cssMetaData = createBooleanCssMetaData(cssProperty, function, initialValue, inherits);
 221         return new SimpleStyleableBooleanProperty(cssMetaData, styleable, propertyName, initialValue);
 222     }
 223 
 224     /**
 225      * Create a StyleableProperty&lt;Boolean&gt; with initial value. The inherit flag defaults to false.
 226      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 227      * @param propertyName The field name of the StyleableProperty&lt;Boolean&gt;
 228      * @param cssProperty The CSS property name
 229      * @param function A function that returns the StyleableProperty&lt;Boolean&gt; that was created by this method call.
 230      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 231      */
 232     public final StyleableProperty<Boolean> createStyleableBooleanProperty(
 233             S styleable,
 234             String propertyName,
 235             String cssProperty,
 236             Function<S, StyleableProperty<Boolean>> function,
 237             boolean initialValue) {
 238         return createStyleableBooleanProperty(styleable, propertyName, cssProperty, function, initialValue, false);
 239     }
 240 
 241     /**
 242      * Create a StyleableProperty&lt;Boolean&gt;. The initialValue and inherit flag default to false.
 243      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 244      * @param propertyName The field name of the StyleableProperty&lt;Boolean&gt;
 245      * @param cssProperty The CSS property name
 246      * @param function A function that returns the StyleableProperty&lt;Boolean&gt; that was created by this method call.
 247      */
 248     public final StyleableProperty<Boolean> createStyleableBooleanProperty(
 249             S styleable,
 250             String propertyName,
 251             String cssProperty,
 252             Function<S, StyleableProperty<Boolean>> function) {
 253         return createStyleableBooleanProperty(styleable, propertyName, cssProperty, function, false, false);
 254     }
 255 
 256     /**
 257      * Create a StyleableProperty&lt;Boolean&gt; using previously created CssMetaData for the given <code>cssProperty</code>.
 258      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 259      * @param propertyName The field name of the StyleableProperty&lt;Boolean&gt;
 260      * @param cssProperty The CSS property name
 261      * @throws java.lang.IllegalArgumentException if <code>cssProperty</code> is null or empty
 262      * @throws java.util.NoSuchElementException if the CssMetaData for <code>cssProperty</code> was not created prior to this method invocation
 263      */
 264     public final StyleableProperty<Boolean> createStyleableBooleanProperty(
 265             S styleable,
 266             String propertyName,
 267             String cssProperty) {
 268 
 269         if (cssProperty == null || cssProperty.isEmpty()) {
 270             throw new IllegalArgumentException("cssProperty cannot be null or empty string");
 271         }
 272 
 273         @SuppressWarnings("unchecked")
 274         CssMetaData<S,Boolean> cssMetaData = (CssMetaData<S,Boolean>)getCssMetaData(Boolean.class, cssProperty);
 275         return new SimpleStyleableBooleanProperty(cssMetaData, styleable, propertyName, cssMetaData.getInitialValue(styleable));
 276     }
 277 
 278     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 279     //
 280     // create StyleableProperty<Color>
 281     //
 282     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 283 
 284     /**
 285      * Create a StyleableProperty&lt;Color&gt; with initial value and inherit flag.
 286      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 287      * @param propertyName The field name of the StyleableProperty&lt;Color&gt;
 288      * @param cssProperty The CSS property name
 289      * @param function A function that returns the StyleableProperty&lt;Color&gt; that was created by this method call.
 290      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 291      * @param inherits Whether or not the CSS style can be inherited by child nodes                     
 292      */    
 293     public final StyleableProperty<Color> createStyleableColorProperty(
 294             S styleable,
 295             String propertyName,
 296             String cssProperty,
 297             Function<S, StyleableProperty<Color>> function,
 298             Color initialValue,
 299             boolean inherits) {
 300 
 301         CssMetaData<S,Color> cssMetaData = createColorCssMetaData(cssProperty, function, initialValue, inherits);
 302         return new SimpleStyleableObjectProperty<Color>(cssMetaData, styleable, propertyName, initialValue);
 303     }
 304 
 305     /**
 306      * Create a StyleableProperty&lt;Color&gt; with initial value. The inherit flag defaults to false.
 307      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 308      * @param propertyName The field name of the StyleableProperty&lt;Color&gt;
 309      * @param cssProperty The CSS property name
 310      * @param function A function that returns the StyleableProperty&lt;Color&gt; that was created by this method call.
 311      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 312      */
 313     public final StyleableProperty<Color> createStyleableColorProperty(
 314             S styleable,
 315             String propertyName,
 316             String cssProperty,
 317             Function<S, StyleableProperty<Color>> function,
 318             Color initialValue) {
 319         return createStyleableColorProperty(styleable, propertyName, cssProperty, function, initialValue, false);
 320     }
 321 
 322     /**
 323      * Create a StyleableProperty&lt;Color&gt;. The initial value defaults to Color.BLACK and the 
 324      * inherit flag defaults to false.
 325      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 326      * @param propertyName The field name of the StyleableProperty&lt;Color&gt;
 327      * @param cssProperty The CSS property name
 328      * @param function A function that returns the StyleableProperty&lt;Color&gt; that was created by this method call.
 329      */
 330     public final StyleableProperty<Color> createStyleableColorProperty(
 331             S styleable,
 332             String propertyName,
 333             String cssProperty,
 334             Function<S, StyleableProperty<Color>> function) {
 335         return createStyleableColorProperty(styleable, propertyName, cssProperty, function, Color.BLACK, false);
 336     }
 337 
 338     /**
 339      * Create a StyleableProperty&lt;Color&gt; using previously created CssMetaData for the given <code>cssProperty</code>.
 340      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 341      * @param propertyName The field name of the StyleableProperty&lt;Color&gt;
 342      * @param cssProperty The CSS property name
 343      * @throws java.lang.IllegalArgumentException if <code>cssProperty</code> is null or empty
 344      * @throws java.util.NoSuchElementException if the CssMetaData for <code>cssProperty</code> was not created prior to this method invocation
 345      */
 346     public final StyleableProperty<Color> createStyleableColorProperty(
 347             S styleable,
 348             String propertyName,
 349             String cssProperty) {
 350 
 351         if (cssProperty == null || cssProperty.isEmpty()) {
 352             throw new IllegalArgumentException("cssProperty cannot be null or empty string");
 353         }
 354 
 355         @SuppressWarnings("unchecked")
 356         CssMetaData<S,Color> cssMetaData = (CssMetaData<S,Color>)getCssMetaData(Color.class, cssProperty);
 357         return new SimpleStyleableObjectProperty<Color>(cssMetaData, styleable, propertyName, cssMetaData.getInitialValue(styleable));
 358     }
 359 
 360     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 361     //
 362     // create StyleableProperty<Duration>
 363     //
 364     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 365 
 366     /**
 367      * Create a StyleableProperty&lt;Duration&gt; with initial value and inherit flag.
 368      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 369      * @param propertyName The field name of the StyleableProperty&lt;Duration&gt;
 370      * @param cssProperty The CSS property name
 371      * @param function A function that returns the StyleableProperty&lt;Duration&gt; that was created by this method call.
 372      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 373      * @param inherits Whether or not the CSS style can be inherited by child nodes                     
 374      */
 375     public final StyleableProperty<Duration> createStyleableDurationProperty(
 376             S styleable,
 377             String propertyName,
 378             String cssProperty,
 379             Function<S, StyleableProperty<Duration>> function,
 380             Duration initialValue,
 381             boolean inherits) {
 382 
 383         CssMetaData<S,Duration> cssMetaData = createDurationCssMetaData(cssProperty, function, initialValue, inherits);
 384         return new SimpleStyleableObjectProperty<Duration>(cssMetaData, styleable, propertyName, initialValue);
 385     }
 386 
 387     /**
 388      * Create a StyleableProperty&lt;Duration&gt; with initial value. The inherit flag defaults to false.
 389      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 390      * @param propertyName The field name of the StyleableProperty&lt;Duration&gt;
 391      * @param cssProperty The CSS property name
 392      * @param function A function that returns the StyleableProperty&lt;Duration&gt; that was created by this method call.
 393      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 394      */
 395     public final StyleableProperty<Duration> createStyleableDurationProperty(
 396             S styleable,
 397             String propertyName,
 398             String cssProperty,
 399             Function<S, StyleableProperty<Duration>> function,
 400             Duration initialValue) {
 401         return createStyleableDurationProperty(styleable, propertyName, cssProperty, function, initialValue, false);
 402     }
 403 
 404     /**
 405      * Create a StyleableProperty&lt;Duration&gt;. The initial value defaults to Duration.BLACK and the 
 406      * inherit flag defaults to false.
 407      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 408      * @param propertyName The field name of the StyleableProperty&lt;Duration&gt;
 409      * @param cssProperty The CSS property name
 410      * @param function A function that returns the StyleableProperty&lt;Duration&gt; that was created by this method call.
 411      */
 412     public final StyleableProperty<Duration> createStyleableDurationProperty(
 413             S styleable,
 414             String propertyName,
 415             String cssProperty,
 416             Function<S, StyleableProperty<Duration>> function) {
 417         return createStyleableDurationProperty(styleable, propertyName, cssProperty, function, Duration.UNKNOWN, false);
 418     }
 419 
 420     /**
 421      * Create a StyleableProperty&lt;Duration&gt; using previously created CssMetaData for the given <code>cssProperty</code>.
 422      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 423      * @param propertyName The field name of the StyleableProperty&lt;Duration&gt;
 424      * @param cssProperty The CSS property name
 425      * @throws java.lang.IllegalArgumentException if <code>cssProperty</code> is null or empty
 426      * @throws java.util.NoSuchElementException if the CssMetaData for <code>cssProperty</code> was not created prior to this method invocation
 427      */
 428     public final StyleableProperty<Duration> createStyleableDurationProperty(
 429             S styleable,
 430             String propertyName,
 431             String cssProperty) {
 432 
 433         if (cssProperty == null || cssProperty.isEmpty()) {
 434             throw new IllegalArgumentException("cssProperty cannot be null or empty string");
 435         }
 436 
 437         @SuppressWarnings("unchecked")
 438         CssMetaData<S,Duration> cssMetaData = (CssMetaData<S,Duration>)getCssMetaData(Duration.class, cssProperty);
 439         return new SimpleStyleableObjectProperty<Duration>(cssMetaData, styleable, propertyName, cssMetaData.getInitialValue(styleable));
 440     }
 441 
 442     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 443     //
 444     // create StyleableProperty<Effect>
 445     //
 446     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 447 
 448     /**
 449      * Create a StyleableProperty&lt;Effect&gt; with initial value and inherit flag.
 450      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 451      * @param propertyName The field name of the StyleableProperty&lt;Effect&gt;
 452      * @param cssProperty The CSS property name
 453      * @param function A function that returns the StyleableProperty&lt;Effect&gt; that was created by this method call.
 454      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 455      * @param inherits Whether or not the CSS style can be inherited by child nodes                     
 456      */
 457     public final <E extends Effect> StyleableProperty<E> createStyleableEffectProperty(
 458             S styleable,
 459             String propertyName,
 460             String cssProperty,
 461             Function<S, StyleableProperty<E>> function,
 462             E initialValue,
 463             boolean inherits) {
 464 
 465         CssMetaData<S,E> cssMetaData = createEffectCssMetaData(cssProperty, function, initialValue, inherits);
 466         return new SimpleStyleableObjectProperty<E>(cssMetaData, styleable, propertyName, initialValue);
 467     }
 468 
 469     /**
 470      * Create a StyleableProperty&lt;Effect&gt; with initial value. The inherit flag defaults to false.
 471      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 472      * @param propertyName The field name of the StyleableProperty&lt;Effect&gt;
 473      * @param cssProperty The CSS property name
 474      * @param function A function that returns the StyleableProperty&lt;Effect&gt; that was created by this method call.
 475      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 476      */
 477     public final <E extends Effect> StyleableProperty<E> createStyleableEffectProperty(
 478             S styleable,
 479             String propertyName,
 480             String cssProperty,
 481             Function<S, StyleableProperty<E>> function,
 482             E initialValue) {
 483         return createStyleableEffectProperty(styleable, propertyName, cssProperty, function, initialValue, false);
 484     }
 485 
 486     /**
 487      * Create a StyleableProperty&lt;Effect&gt;. The initial value is null and the inherit flag defaults to false.
 488      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 489      * @param propertyName The field name of the StyleableProperty&lt;Effect&gt;
 490      * @param cssProperty The CSS property name
 491      * @param function A function that returns the StyleableProperty&lt;Effect&gt; that was created by this method call.
 492      */
 493     public final <E extends Effect> StyleableProperty<E> createStyleableEffectProperty(
 494             S styleable,
 495             String propertyName,
 496             String cssProperty,
 497             Function<S, StyleableProperty<E>> function) {
 498         return createStyleableEffectProperty(styleable, propertyName, cssProperty, function, null, false);
 499     }
 500 
 501     /**
 502      * Create a StyleableProperty&lt;Effect&gt; using previously created CssMetaData for the given <code>cssProperty</code>.
 503      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 504      * @param propertyName The field name of the StyleableProperty&lt;Effect&gt;
 505      * @param cssProperty The CSS property name
 506      * @throws java.lang.IllegalArgumentException if <code>cssProperty</code> is null or empty
 507      * @throws java.util.NoSuchElementException if the CssMetaData for <code>cssProperty</code> was not created prior to this method invocation
 508      */
 509     public final StyleableProperty<Effect> createStyleableEffectProperty(
 510             S styleable,
 511             String propertyName,
 512             String cssProperty) {
 513 
 514         if (cssProperty == null || cssProperty.isEmpty()) {
 515             throw new IllegalArgumentException("cssProperty cannot be null or empty string");
 516         }
 517 
 518         @SuppressWarnings("unchecked")
 519         CssMetaData<S,Effect> cssMetaData = (CssMetaData<S,Effect>)getCssMetaData(Effect.class, cssProperty);
 520         return new SimpleStyleableObjectProperty<Effect>(cssMetaData, styleable, propertyName, cssMetaData.getInitialValue(styleable));
 521     }
 522     
 523     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 524     //
 525     // create StyleableProperty<? extends Enum<?>>
 526     //
 527     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 528 
 529     /**
 530      * Create a StyleableProperty&lt;E extends Enum&lt;E&gt;&gt; with initial value and inherit flag. 
 531      * The <code>enumClass</code> parameter is the Class of the Enum that is the value of the property. For example, 
 532      * <code><pre>
 533      *     private static final StyleablePropertyFactory&lt;MyControl&gt; FACTORY = new StyleablePropertyFactory&lt;&gt;();
 534      *     StyleableProperty&lt;Orientation&gt; orientation =
 535      *         FACTORY.createStyleableEnumProperty(
 536      *             this, 
 537      *             "orientation", 
 538      *             "-my-orientation", 
 539      *             s -> ((MyControl)s).orientation,
 540      *             Orientation.class,
 541      *             Orientation.HORIZONTAL,
 542      *             false);
 543      * </pre></code>
 544      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 545      * @param propertyName The field name of the StyleableProperty&lt;E extends Enum&lt;E&gt;&gt;
 546      * @param cssProperty The CSS property name
 547      * @param function A function that returns the StyleableProperty&lt;E extends Enum&lt;E&gt;&gt; that was created by this method call.
 548      * @param enumClass The Enum class that is the type of the StyleableProperty&lt;E extends Enum&lt;E&gt;&gt;.
 549      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 550      * @param inherits Whether or not the CSS style can be inherited by child nodes                     
 551      */
 552     public final <E extends Enum<E>> StyleableProperty<E> createStyleableEnumProperty(
 553             S styleable,
 554             String propertyName,
 555             String cssProperty,
 556             Function<S, StyleableProperty<E>> function,
 557             Class<E> enumClass,
 558             E initialValue,
 559             boolean inherits) {
 560 
 561         CssMetaData<S,E> cssMetaData = createEnumCssMetaData(enumClass, cssProperty, function, initialValue, inherits);
 562         return new SimpleStyleableObjectProperty<E>(cssMetaData, styleable, propertyName, initialValue);
 563     }
 564 
 565     /**
 566      * Create a StyleableProperty&lt;E extends Enum&lt;E&gt;&gt; with initial value. The inherit flag defaults to false. 
 567      * The <code>enumClass</code> parameter is the Class of the Enum that is the value of the property. For example, 
 568      * <code><pre>
 569      *     private static final StyleablePropertyFactory&lt;MyControl&gt; FACTORY = new StyleablePropertyFactory&lt;&gt;();
 570      *     StyleableProperty&lt;Orientation&gt; orientation =
 571      *         FACTORY.createStyleableEnumProperty(
 572      *             this, 
 573      *             "orientation", 
 574      *             "-my-orientation", 
 575      *             s -> ((MyControl)s).orientation,
 576      *             Orientation.class,
 577      *             Orientation.HORIZONTAL);
 578      * </pre></code>
 579      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 580      * @param propertyName The field name of the StyleableProperty&lt;E extends Enum&lt;E&gt;&gt;
 581      * @param cssProperty The CSS property name
 582      * @param function A function that returns the StyleableProperty&lt;E extends Enum&lt;E&gt;&gt; that was created by this method call.
 583      * @param enumClass The Enum class that is the type of the StyleableProperty&lt;E extends Enum&lt;E&gt;&gt;.
 584      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 585      */
 586     public final <E extends Enum<E>> StyleableProperty<E> createStyleableEnumProperty(
 587             S styleable,
 588             String propertyName,
 589             String cssProperty,
 590             Function<S, StyleableProperty<E>> function,
 591             Class<E> enumClass,
 592             E initialValue) {
 593         return createStyleableEnumProperty(styleable, propertyName, cssProperty, function, enumClass, initialValue, false);
 594     }
 595 
 596     /**
 597      * Create a StyleableProperty&lt;E extends Enum&lt;E&gt;&gt;. The initial value is null and inherit flag defaults to false. 
 598      * The <code>enumClass</code> parameter is the Class of the Enum that is the value of the property. For example, 
 599      * <code><pre>
 600      *     private static final StyleablePropertyFactory&lt;MyControl&gt; FACTORY = new StyleablePropertyFactory&lt;&gt;();
 601      *     StyleableProperty&lt;Orientation&gt; orientation =
 602      *         FACTORY.createStyleableEnumProperty(
 603      *             this, 
 604      *             "orientation", 
 605      *             "-my-orientation", 
 606      *             s -> ((MyControl)s).orientation,
 607      *             Orientation.class);
 608      * </pre></code>
 609      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 610      * @param propertyName The field name of the StyleableProperty&lt;E extends Enum&lt;E&gt;&gt;
 611      * @param cssProperty The CSS property name
 612      * @param function A function that returns the StyleableProperty&lt;E extends Enum&lt;E&gt;&gt; that was created by this method call.
 613      * @param enumClass The Enum class that is the type of the StyleableProperty&lt;E extends Enum&lt;E&gt;&gt;.
 614      */
 615     public final <E extends Enum<E>> StyleableProperty<E> createStyleableEnumProperty(
 616             S styleable,
 617             String propertyName,
 618             String cssProperty,
 619             Function<S, StyleableProperty<E>> function,
 620             Class<E> enumClass) {
 621         return createStyleableEnumProperty(styleable, propertyName, cssProperty, function, enumClass, null, false);
 622     }
 623 
 624     /**
 625      * Create a StyleableProperty&lt;E extends Enum&lt;E&gt;&gt; using previously created CssMetaData for the given <code>cssProperty</code>.
 626      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 627      * @param propertyName The field name of the StyleableProperty&lt;E extends Enum&lt;E&gt;&gt;
 628      * @param cssProperty The CSS property name
 629      * @throws java.lang.IllegalArgumentException if <code>cssProperty</code> is null or empty
 630      * @throws java.util.NoSuchElementException if the CssMetaData for <code>cssProperty</code> was not created prior to this method invocation
 631      */
 632     public final <E extends Enum<E>> StyleableProperty<E> createStyleableEffectProperty(
 633             S styleable,
 634             String propertyName,
 635             String cssProperty,
 636             Class<E> enumClass) {
 637 
 638         if (cssProperty == null || cssProperty.isEmpty()) {
 639             throw new IllegalArgumentException("cssProperty cannot be null or empty string");
 640         }
 641 
 642         @SuppressWarnings("unchecked")
 643         CssMetaData<S,E> cssMetaData = (CssMetaData<S,E>)getCssMetaData(enumClass, cssProperty);
 644         return new SimpleStyleableObjectProperty<E>(cssMetaData, styleable, propertyName, cssMetaData.getInitialValue(styleable));
 645     }
 646 
 647     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 648     //
 649     // create StyleableProperty<Font>
 650     //
 651     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 652 
 653     /**
 654      * Create a StyleableProperty&lt;Font&gt; with initial value and inherit flag.
 655      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 656      * @param propertyName The field name of the StyleableProperty&lt;Font&gt;
 657      * @param cssProperty The CSS property name
 658      * @param function A function that returns the StyleableProperty&lt;Font&gt; that was created by this method call.
 659      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 660      * @param inherits Whether or not the CSS style can be inherited by child nodes                     
 661      */
 662     public final StyleableProperty<Font> createStyleableFontProperty(
 663             S styleable,
 664             String propertyName,
 665             String cssProperty,
 666             Function<S, StyleableProperty<Font>> function,
 667             Font initialValue,
 668             boolean inherits) {
 669 
 670         CssMetaData<S,Font> cssMetaData = createFontCssMetaData(cssProperty, function, initialValue, inherits);
 671         return new SimpleStyleableObjectProperty<Font>(cssMetaData, styleable, propertyName, initialValue);
 672     }
 673 
 674     /**
 675      * Create a StyleableProperty&lt;Font&gt; with initial value. The inherit flag defaults to true.
 676      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 677      * @param propertyName The field name of the StyleableProperty&lt;Font&gt;
 678      * @param cssProperty The CSS property name
 679      * @param function A function that returns the StyleableProperty&lt;Font&gt; that was created by this method call.
 680      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 681      */
 682     public final StyleableProperty<Font> createStyleableFontProperty(
 683             S styleable,
 684             String propertyName,
 685             String cssProperty,
 686             Function<S, StyleableProperty<Font>> function,
 687             Font initialValue) {
 688         return createStyleableFontProperty(styleable, propertyName, cssProperty, function, initialValue, true);
 689     }
 690 
 691     /**
 692      * Create a StyleableProperty&lt;Font&gt;. The initial value defaults to {@link javafx.scene.text.Font#getDefault()}
 693      * and the inherit flag defaults to true.
 694      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 695      * @param propertyName The field name of the StyleableProperty&lt;Font&gt;
 696      * @param cssProperty The CSS property name
 697      * @param function A function that returns the StyleableProperty&lt;Font&gt; that was created by this method call.
 698      */
 699     public final StyleableProperty<Font> createStyleableFontProperty(
 700             S styleable,
 701             String propertyName,
 702             String cssProperty,
 703             Function<S, StyleableProperty<Font>> function) {
 704         return createStyleableFontProperty(styleable, propertyName, cssProperty, function, Font.getDefault(), true);
 705     }
 706 
 707     /**
 708      * Create a StyleableProperty&lt;Font&gt; using previously created CssMetaData for the given <code>cssProperty</code>.
 709      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 710      * @param propertyName The field name of the StyleableProperty&lt;Font&gt;
 711      * @param cssProperty The CSS property name
 712      * @throws java.lang.IllegalArgumentException if <code>cssProperty</code> is null or empty
 713      * @throws java.util.NoSuchElementException if the CssMetaData for <code>cssProperty</code> was not created prior to this method invocation
 714      */
 715     public final StyleableProperty<Font> createStyleableFontProperty(
 716             S styleable,
 717             String propertyName,
 718             String cssProperty) {
 719 
 720         if (cssProperty == null || cssProperty.isEmpty()) {
 721             throw new IllegalArgumentException("cssProperty cannot be null or empty string");
 722         }
 723 
 724         @SuppressWarnings("unchecked")
 725         CssMetaData<S,Font> cssMetaData = (CssMetaData<S,Font>)getCssMetaData(Font.class, cssProperty);
 726         return new SimpleStyleableObjectProperty<Font>(cssMetaData, styleable, propertyName, cssMetaData.getInitialValue(styleable));
 727     }
 728 
 729     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 730     //
 731     // create StyleableProperty<Insets>
 732     //
 733     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 734 
 735     /**
 736      * Create a StyleableProperty&lt;Inset&gt; with initial value and inherit flag.
 737      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 738      * @param propertyName The field name of the StyleableProperty&lt;Inset&gt;
 739      * @param cssProperty The CSS property name
 740      * @param function A function that returns the StyleableProperty&lt;Inset&gt; that was created by this method call.
 741      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 742      * @param inherits Whether or not the CSS style can be inherited by child nodes                     
 743      */
 744     public final StyleableProperty<Insets> createStyleableInsetsProperty(
 745             S styleable,
 746             String propertyName,
 747             String cssProperty,
 748             Function<S, StyleableProperty<Insets>> function,
 749             Insets initialValue,
 750             boolean inherits) {
 751 
 752         CssMetaData<S,Insets> cssMetaData = createInsetsCssMetaData(cssProperty, function, initialValue, inherits);
 753         return new SimpleStyleableObjectProperty<Insets>(cssMetaData, styleable, propertyName, initialValue);
 754     }
 755 
 756     /**
 757      * Create a StyleableProperty&lt;Inset&gt; with initial value. The inherit flag defaults to false.
 758      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 759      * @param propertyName The field name of the StyleableProperty&lt;Inset&gt;
 760      * @param cssProperty The CSS property name
 761      * @param function A function that returns the StyleableProperty&lt;Inset&gt; that was created by this method call.
 762      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 763      */
 764     public final StyleableProperty<Insets> createStyleableInsetsProperty(
 765             S styleable,
 766             String propertyName,
 767             String cssProperty,
 768             Function<S, StyleableProperty<Insets>> function,
 769             Insets initialValue) {
 770         return createStyleableInsetsProperty(styleable, propertyName, cssProperty, function, initialValue, false);
 771     }
 772 
 773     /**
 774      * Create a StyleableProperty&lt;Inset&gt;. The initial value is {@link Insets#EMPTY} and the inherit flag defaults to false.
 775      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 776      * @param propertyName The field name of the StyleableProperty&lt;Inset&gt;
 777      * @param cssProperty The CSS property name
 778      * @param function A function that returns the StyleableProperty&lt;Inset&gt; that was created by this method call.
 779      */
 780     public final StyleableProperty<Insets> createStyleableInsetsProperty(
 781             S styleable,
 782             String propertyName,
 783             String cssProperty,
 784             Function<S, StyleableProperty<Insets>> function) {
 785         return createStyleableInsetsProperty(styleable, propertyName, cssProperty, function, Insets.EMPTY, false);
 786     }
 787 
 788     /**
 789      * Create a StyleableProperty&lt;Insets&gt; using previously created CssMetaData for the given <code>cssProperty</code>.
 790      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 791      * @param propertyName The field name of the StyleableProperty&lt;Insets&gt;
 792      * @param cssProperty The CSS property name
 793      * @throws java.lang.IllegalArgumentException if <code>cssProperty</code> is null or empty
 794      * @throws java.util.NoSuchElementException if the CssMetaData for <code>cssProperty</code> was not created prior to this method invocation
 795      */
 796     public final StyleableProperty<Insets> createStyleableInsetsProperty(
 797             S styleable,
 798             String propertyName,
 799             String cssProperty) {
 800 
 801         if (cssProperty == null || cssProperty.isEmpty()) {
 802             throw new IllegalArgumentException("cssProperty cannot be null or empty string");
 803         }
 804 
 805         @SuppressWarnings("unchecked")
 806         CssMetaData<S,Insets> cssMetaData = (CssMetaData<S,Insets>)getCssMetaData(Insets.class, cssProperty);
 807         return new SimpleStyleableObjectProperty<Insets>(cssMetaData, styleable, propertyName, cssMetaData.getInitialValue(styleable));
 808     }
 809 
 810     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 811     //
 812     // create StyleableProperty<Paint>
 813     //
 814     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 815 
 816     /**
 817      * Create a StyleableProperty&lt;Paint&gt; with initial value and inherit flag.
 818      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 819      * @param propertyName The field name of the StyleableProperty&lt;Paint&gt;
 820      * @param cssProperty The CSS property name
 821      * @param function A function that returns the StyleableProperty&lt;Paint&gt; that was created by this method call.
 822      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 823      * @param inherits Whether or not the CSS style can be inherited by child nodes                     
 824      */
 825     public final StyleableProperty<Paint> createStyleablePaintProperty(
 826             S styleable,
 827             String propertyName,
 828             String cssProperty,
 829             Function<S, StyleableProperty<Paint>> function,
 830             Paint initialValue,
 831             boolean inherits) {
 832 
 833         CssMetaData<S,Paint> cssMetaData = createPaintCssMetaData(cssProperty, function, initialValue, inherits);
 834         return new SimpleStyleableObjectProperty<Paint>(cssMetaData, styleable, propertyName, initialValue);
 835     }
 836 
 837     /**
 838      * Create a StyleableProperty&lt;Paint&gt; with initial value. The inherit flag defaults to false.
 839      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 840      * @param propertyName The field name of the StyleableProperty&lt;Paint&gt;
 841      * @param cssProperty The CSS property name
 842      * @param function A function that returns the StyleableProperty&lt;Paint&gt; that was created by this method call.
 843      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 844      */
 845     public final StyleableProperty<Paint> createStyleablePaintProperty(
 846             S styleable,
 847             String propertyName,
 848             String cssProperty,
 849             Function<S, StyleableProperty<Paint>> function,
 850             Paint initialValue) {
 851         return createStyleablePaintProperty(styleable, propertyName, cssProperty, function, initialValue, false);
 852     }
 853 
 854     /**
 855      * Create a StyleableProperty&lt;Paint&gt;. The initial value defautls to Color.BLACK and the inherit flag defaults to false.
 856      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 857      * @param propertyName The field name of the StyleableProperty&lt;Paint&gt;
 858      * @param cssProperty The CSS property name
 859      * @param function A function that returns the StyleableProperty&lt;Paint&gt; that was created by this method call.
 860      */
 861     public final StyleableProperty<Paint> createStyleablePaintProperty(
 862             S styleable,
 863             String propertyName,
 864             String cssProperty,
 865             Function<S, StyleableProperty<Paint>> function) {
 866         return createStyleablePaintProperty(styleable, propertyName, cssProperty, function, Color.BLACK, false);
 867     }
 868 
 869     /**
 870      * Create a StyleableProperty&lt;Paint&gt; using previously created CssMetaData for the given <code>cssProperty</code>.
 871      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 872      * @param propertyName The field name of the StyleableProperty&lt;Paint&gt;
 873      * @param cssProperty The CSS property name
 874      * @throws java.lang.IllegalArgumentException if <code>cssProperty</code> is null or empty
 875      * @throws java.util.NoSuchElementException if the CssMetaData for <code>cssProperty</code> was not created prior to this method invocation
 876      */
 877     public final StyleableProperty<Paint> createStyleablePaintProperty(
 878             S styleable,
 879             String propertyName,
 880             String cssProperty) {
 881 
 882         if (cssProperty == null || cssProperty.isEmpty()) {
 883             throw new IllegalArgumentException("cssProperty cannot be null or empty string");
 884         }
 885 
 886         @SuppressWarnings("unchecked")
 887         CssMetaData<S,Paint> cssMetaData = (CssMetaData<S,Paint>)getCssMetaData(Paint.class, cssProperty);
 888         return new SimpleStyleableObjectProperty<Paint>(cssMetaData, styleable, propertyName, cssMetaData.getInitialValue(styleable));
 889     }
 890     
 891     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 892     //
 893     // create StyleableProperty<Number>
 894     //
 895     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 896 
 897     /**
 898      * Create a StyleableProperty&lt;Number&gt; with initial value and inherit flag.
 899      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 900      * @param propertyName The field name of the StyleableProperty&lt;Number&gt;
 901      * @param cssProperty The CSS property name
 902      * @param function A function that returns the StyleableProperty&lt;Number&gt; that was created by this method call.
 903      * @param initialValue The initial value of the property. CSS may reset the property to this value.
 904      * @param inherits Whether or not the CSS style can be inherited by child nodes
 905      */
 906     public final StyleableProperty<Number> createStyleableNumberProperty(
 907             S styleable,
 908             String propertyName,
 909             String cssProperty,
 910             Function<S, StyleableProperty<Number>> function,
 911             Number initialValue,
 912             boolean inherits) {
 913 
 914         CssMetaData<S,Number> cssMetaData = createSizeCssMetaData(cssProperty, function, initialValue, inherits);
 915         return new SimpleStyleableObjectProperty<>(cssMetaData, styleable, propertyName, initialValue);
 916     }
 917 
 918     /**
 919      * Create a StyleableProperty&lt;Number&gt; with initial value. The inherit flag defaults to false.
 920      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 921      * @param propertyName The field name of the StyleableProperty&lt;Number&gt;
 922      * @param cssProperty The CSS property name
 923      * @param function A function that returns the StyleableProperty&lt;Number&gt; that was created by this method call.
 924      * @param initialValue The initial value of the property. CSS may reset the property to this value.
 925      */
 926     public final StyleableProperty<Number> createStyleableNumberProperty(
 927             S styleable,
 928             String propertyName,
 929             String cssProperty,
 930             Function<S, StyleableProperty<Number>> function,
 931             Number initialValue) {
 932         return createStyleableNumberProperty(styleable, propertyName, cssProperty, function, initialValue, false);
 933     }
 934 
 935     /**
 936      * Create a StyleableProperty&lt;Number&gt;. The initial value defaults to zero. The inherit flag defaults to false.
 937      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 938      * @param propertyName The field name of the StyleableProperty&lt;Number&gt;
 939      * @param cssProperty The CSS property name
 940      * @param function A function that returns the StyleableProperty&lt;Number&gt; that was created by this method call.
 941      */
 942     public final StyleableProperty<Number> createStyleableNumberProperty(
 943             S styleable,
 944             String propertyName,
 945             String cssProperty,
 946             Function<S, StyleableProperty<Number>> function) {
 947         return createStyleableNumberProperty(styleable, propertyName, cssProperty, function, 0d, false);
 948     }
 949 
 950     /**
 951      * Create a StyleableProperty&lt;Number&gt; using previously created CssMetaData for the given <code>cssProperty</code>.
 952      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 953      * @param propertyName The field name of the StyleableProperty&lt;Number&gt;
 954      * @param cssProperty The CSS property name
 955      * @throws java.lang.IllegalArgumentException if <code>cssProperty</code> is null or empty
 956      * @throws java.util.NoSuchElementException if the CssMetaData for <code>cssProperty</code> was not created prior to this method invocation
 957      */
 958     public final StyleableProperty<Number> createStyleableNumberProperty(
 959             S styleable,
 960             String propertyName,
 961             String cssProperty) {
 962 
 963         if (cssProperty == null || cssProperty.isEmpty()) {
 964             throw new IllegalArgumentException("cssProperty cannot be null or empty string");
 965         }
 966 
 967         @SuppressWarnings("unchecked")
 968         CssMetaData<S,Number> cssMetaData = (CssMetaData<S,Number>)getCssMetaData(Number.class, cssProperty);
 969         return new SimpleStyleableObjectProperty<Number>(cssMetaData, styleable, propertyName, cssMetaData.getInitialValue(styleable));
 970     }
 971     
 972     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 973     //
 974     // create StyleableProperty<String>
 975     //
 976     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 977 
 978     /**
 979      * Create a StyleableProperty&lt;String&gt; with initial value and inherit flag.
 980      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
 981      * @param propertyName The field name of the StyleableProperty&lt;String&gt;
 982      * @param cssProperty The CSS property name
 983      * @param function A function that returns the StyleableProperty&lt;String&gt; that was created by this method call.
 984      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
 985      * @param inherits Whether or not the CSS style can be inherited by child nodes                     
 986      */
 987     public final StyleableProperty<String> createStyleableStringProperty(
 988             S styleable,
 989             String propertyName,
 990             String cssProperty,
 991             Function<S, StyleableProperty<String>> function,
 992             String initialValue,
 993             boolean inherits) {
 994 
 995         CssMetaData<S,String> cssMetaData = createStringCssMetaData(cssProperty, function, initialValue, inherits);
 996         return new SimpleStyleableStringProperty(cssMetaData, styleable, propertyName, initialValue);
 997     }
 998 
 999     /**
1000      * Create a StyleableProperty&lt;String&gt; with initial value. The inherit flag defaults to false.
1001      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
1002      * @param propertyName The field name of the StyleableProperty&lt;String&gt;
1003      * @param cssProperty The CSS property name
1004      * @param function A function that returns the StyleableProperty&lt;String&gt; that was created by this method call.
1005      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1006      */
1007     public final StyleableProperty<String> createStyleableStringProperty(
1008             S styleable,
1009             String propertyName,
1010             String cssProperty,
1011             Function<S, StyleableProperty<String>> function,
1012             String initialValue) {
1013         return createStyleableStringProperty(styleable, propertyName, cssProperty, function, initialValue, false);
1014     }
1015 
1016     /**
1017      * Create a StyleableProperty&lt;String&gt;. The initial value defaults to null and the inherit flag defaults to false.
1018      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
1019      * @param propertyName The field name of the StyleableProperty&lt;String&gt;
1020      * @param cssProperty The CSS property name
1021      * @param function A function that returns the StyleableProperty&lt;String&gt; that was created by this method call.
1022      */
1023     public final StyleableProperty<String> createStyleableStringProperty(
1024             S styleable,
1025             String propertyName,
1026             String cssProperty,
1027             Function<S, StyleableProperty<String>> function) {
1028         return createStyleableStringProperty(styleable, propertyName, cssProperty, function, null, false);
1029     }
1030 
1031     /**
1032      * Create a StyleableProperty&lt;String&gt; using previously created CssMetaData for the given <code>cssProperty</code>.
1033      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
1034      * @param propertyName The field name of the StyleableProperty&lt;String&gt;
1035      * @param cssProperty The CSS property name
1036      * @throws java.lang.IllegalArgumentException if <code>cssProperty</code> is null or empty
1037      * @throws java.util.NoSuchElementException if the CssMetaData for <code>cssProperty</code> was not created prior to this method invocation
1038      */
1039     public final StyleableProperty<String> createStyleableStringProperty(
1040             S styleable,
1041             String propertyName,
1042             String cssProperty) {
1043 
1044         if (cssProperty == null || cssProperty.isEmpty()) {
1045             throw new IllegalArgumentException("cssProperty cannot be null or empty string");
1046         }
1047 
1048         @SuppressWarnings("unchecked")
1049         CssMetaData<S,String> cssMetaData = (CssMetaData<S,String>)getCssMetaData(String.class, cssProperty);
1050         return new SimpleStyleableStringProperty(cssMetaData, styleable, propertyName, cssMetaData.getInitialValue(styleable));
1051     }
1052     
1053     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1054     //
1055     // create StyleableProperty<String> where String is a URL
1056     //
1057     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1058 
1059     /**
1060      * Create a StyleableProperty&lt;String&gt; with initial value and inherit flag. Here, the String value represents
1061      * a URL converted from a <a href="http://www.w3.org/TR/CSS21/syndata.html#uri">CSS</a> url("<path>").
1062      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
1063      * @param propertyName The field name of the StyleableProperty&lt;String&gt;
1064      * @param cssProperty The CSS property name
1065      * @param function A function that returns the StyleableProperty&lt;String&gt; that was created by this method call.
1066      * @param initialValue The initial value of the property. CSS may reset the property to this value. 
1067      * @param inherits Whether or not the CSS style can be inherited by child nodes                     
1068      */
1069     public final StyleableProperty<String> createStyleableUrlProperty(
1070             S styleable,
1071             String propertyName,
1072             String cssProperty,
1073             Function<S, StyleableProperty<String>> function,
1074             String initialValue,
1075             boolean inherits) {
1076 
1077         CssMetaData<S,String> cssMetaData = createUrlCssMetaData(cssProperty, function, initialValue, inherits);
1078         return new SimpleStyleableStringProperty(cssMetaData, styleable, propertyName, initialValue);
1079     }
1080 
1081     /**
1082      * Create a StyleableProperty&lt;String&gt; with initial value. The inherit flag defaults to false.
1083      * Here, the String value represents a URL converted from a
1084      * <a href="http://www.w3.org/TR/CSS21/syndata.html#uri">CSS</a> url("<path>").
1085      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
1086      * @param propertyName The field name of the StyleableProperty&lt;String&gt;
1087      * @param cssProperty The CSS property name
1088      * @param function A function that returns the StyleableProperty&lt;String&gt; that was created by this method call.
1089      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1090      */
1091     public final StyleableProperty<String> createStyleableUrlProperty(
1092             S styleable,
1093             String propertyName,
1094             String cssProperty,
1095             Function<S, StyleableProperty<String>> function,
1096             String initialValue) {
1097         return createStyleableUrlProperty(styleable, propertyName, cssProperty, function, initialValue, false);
1098     }
1099 
1100     /**
1101      * Create a StyleableProperty&lt;String&gt; with initial value. The inherit flag defaults to false.
1102      * Here, the String value represents a URL converted from a
1103      * <a href="http://www.w3.org/TR/CSS21/syndata.html#uri">CSS</a> url("<path>").
1104      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
1105      * @param propertyName The field name of the StyleableProperty&lt;String&gt;
1106      * @param cssProperty The CSS property name
1107      * @param function A function that returns the StyleableProperty&lt;String&gt; that was created by this method call.
1108      */
1109     public final StyleableProperty<String> createStyleableUrlProperty(
1110             S styleable,
1111             String propertyName,
1112             String cssProperty,
1113             Function<S, StyleableProperty<String>> function) {
1114         return createStyleableUrlProperty(styleable, propertyName, cssProperty, function, null, false);
1115     }
1116 
1117     /**
1118      * Create a StyleableProperty&lt;String&gt; using previously created CssMetaData for the given <code>cssProperty</code>.
1119      * @param styleable The <code>this</code> reference of the returned property. This is also the property bean.
1120      * @param propertyName The field name of the StyleableProperty&lt;String&gt;
1121      * @param cssProperty The CSS property name
1122      * @throws java.lang.IllegalArgumentException if <code>cssProperty</code> is null or empty
1123      * @throws java.util.NoSuchElementException if the CssMetaData for <code>cssProperty</code> was not created prior to this method invocation
1124      */
1125     public final StyleableProperty<String> createStyleableUrlProperty(
1126             S styleable,
1127             String propertyName,
1128             String cssProperty) {
1129 
1130         if (cssProperty == null || cssProperty.isEmpty()) {
1131             throw new IllegalArgumentException("cssProperty cannot be null or empty string");
1132         }
1133 
1134         @SuppressWarnings("unchecked")
1135         CssMetaData<S,String> cssMetaData = (CssMetaData<S,String>)getCssMetaData(String.class, cssProperty);
1136         return new SimpleStyleableStringProperty(cssMetaData, styleable, propertyName, cssMetaData.getInitialValue(styleable));
1137     }
1138 
1139     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1140     //                                                                                                              //
1141     // create CssMetaData<S, Boolean>                                                                               //
1142     //                                                                                                              //
1143     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1144 
1145     /**
1146      * Create a CssMetaData&lt;S, Boolean&gt; with initial value, and inherit flag.
1147      * @param property The CSS property name.
1148      * @param function A function that returns the StyleableProperty&lt;Boolean&gt; that corresponds to this CssMetaData.
1149      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1150      * @param inherits Whether or not the CSS style can be inherited by child nodes
1151      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1152      */
1153     public final CssMetaData<S, Boolean>
1154     createBooleanCssMetaData(final String property, final Function<S,StyleableProperty<Boolean>> function, final boolean initialValue, final boolean inherits)
1155     {
1156         if (property == null || property.isEmpty()) {
1157             throw new IllegalArgumentException("property cannot be null or empty string");
1158         }
1159 
1160         if (function == null) {
1161             throw new IllegalArgumentException("function cannot be null");
1162         }
1163 
1164         @SuppressWarnings("unchecked") // getCssMetaData checks and will throw a ClassCastException
1165         CssMetaData<S, Boolean> cssMetaData =
1166                 (CssMetaData<S, Boolean>)getCssMetaData(Boolean.class, property, key -> {
1167                     final StyleConverter<String, Boolean> converter = StyleConverter.getBooleanConverter();
1168                     return new SimpleCssMetaData<S, Boolean>(key, function, converter, initialValue, inherits);
1169                 });
1170         return cssMetaData;
1171     }
1172 
1173     /**
1174      * Create a CssMetaData&lt;S, Boolean&gt; with initial value, and inherit flag defaulting to false.
1175      * @param property The CSS property name.
1176      * @param function A function that returns the StyleableProperty&lt;Boolean&gt; that corresponds to this CssMetaData.
1177      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1178      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1179      */
1180     public final CssMetaData<S, Boolean>
1181     createBooleanCssMetaData(final String property, final Function<S,StyleableProperty<Boolean>> function, final boolean initialValue)
1182     {
1183         return createBooleanCssMetaData(property, function, initialValue, false);
1184     }
1185 
1186     /**
1187      * Create a CssMetaData&lt;S, Boolean&gt; with initial value and inherit flag both defaulting to false.
1188      * @param property The CSS property name.
1189      * @param function A function that returns the StyleableProperty&lt;Boolean&gt; that corresponds to this CssMetaData.
1190      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1191      */
1192     public final CssMetaData<S, Boolean>
1193     createBooleanCssMetaData(final String property, final Function<S,StyleableProperty<Boolean>> function)
1194     {
1195         return createBooleanCssMetaData(property, function, false, false);
1196     }
1197 
1198     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1199     //                                                                                                              //
1200     // create CssMetaData<S, Color>                                                                                 //
1201     //                                                                                                              //
1202     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1203 
1204     /**
1205      * Create a CssMetaData&lt;S, Color&gt; with initial value, and inherit flag.
1206      * @param property The CSS property name.
1207      * @param function A function that returns the StyleableProperty&lt;Color&gt; that corresponds to this CssMetaData.
1208      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1209      * @param inherits Whether or not the CSS style can be inherited by child nodes
1210      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1211      */
1212     public final CssMetaData<S, Color>
1213     createColorCssMetaData(final String property, final Function<S,StyleableProperty<Color>> function, final Color initialValue, final boolean inherits)
1214     {
1215         if (property == null || property.isEmpty()) {
1216             throw new IllegalArgumentException("property cannot be null or empty string");
1217         }
1218 
1219         if (function == null) {
1220             throw new IllegalArgumentException("function cannot be null");
1221         }
1222 
1223         @SuppressWarnings("unchecked") // getCssMetaData checks and will throw a ClassCastException
1224         CssMetaData<S, Color> cssMetaData =
1225                 (CssMetaData<S, Color>)getCssMetaData(Color.class, property, key -> {
1226                     final StyleConverter<String,Color> converter = StyleConverter.getColorConverter();
1227                     return new SimpleCssMetaData<S, Color>(property, function, converter, initialValue, inherits);
1228                 });
1229         return cssMetaData;
1230     }
1231 
1232     /**
1233      * Create a CssMetaData&lt;S, Color&gt; with initial value, and inherit flag defaulting to false.
1234      * @param property The CSS property name.
1235      * @param function A function that returns the StyleableProperty&lt;Color&gt; that corresponds to this CssMetaData.
1236      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1237      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1238      */
1239     public final CssMetaData<S, Color>
1240     createColorCssMetaData(final String property, final Function<S,StyleableProperty<Color>> function, final Color initialValue)
1241     {
1242         return createColorCssMetaData(property, function, initialValue, false);
1243     }
1244 
1245     /**
1246      * Create a CssMetaData&lt;S, Color&gt; with initial value of Color.BLACK, and inherit flag defaulting to false.
1247      * @param property The CSS property name.
1248      * @param function A function that returns the StyleableProperty&lt;Color&gt; that corresponds to this CssMetaData.
1249      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1250      */
1251     public final CssMetaData<S, Color>
1252     createColorCssMetaData(final String property, final Function<S,StyleableProperty<Color>> function)
1253     {
1254         return createColorCssMetaData(property, function, Color.BLACK, false);
1255     }
1256 
1257     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1258     //                                                                                                              //
1259     // create CssMetaData<S, Duration>                                                                                 //
1260     //                                                                                                              //
1261     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1262 
1263     /**
1264      * Create a CssMetaData&lt;S, Duration&gt; with initial value, and inherit flag.
1265      * @param property The CSS property name.
1266      * @param function A function that returns the StyleableProperty&lt;Duration&gt; that corresponds to this CssMetaData.
1267      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1268      * @param inherits Whether or not the CSS style can be inherited by child nodes
1269      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1270      */
1271     public final CssMetaData<S, Duration>
1272     createDurationCssMetaData(final String property, final Function<S,StyleableProperty<Duration>> function, final Duration initialValue, final boolean inherits)
1273     {
1274         if (property == null || property.isEmpty()) {
1275             throw new IllegalArgumentException("property cannot be null or empty string");
1276         }
1277 
1278         if (function == null) {
1279             throw new IllegalArgumentException("function cannot be null");
1280         }
1281 
1282         @SuppressWarnings("unchecked") // getCssMetaData checks and will throw a ClassCastException
1283                 CssMetaData<S, Duration> cssMetaData =
1284                 (CssMetaData<S, Duration>)getCssMetaData(Duration.class, property, key -> {
1285                     final StyleConverter<?,Duration> converter = StyleConverter.getDurationConverter();
1286                     return new SimpleCssMetaData<S, Duration>(property, function, converter, initialValue, inherits);
1287                 });
1288         return cssMetaData;
1289     }
1290 
1291     /**
1292      * Create a CssMetaData&lt;S, Duration&gt; with initial value, and inherit flag defaulting to false.
1293      * @param property The CSS property name.
1294      * @param function A function that returns the StyleableProperty&lt;Duration&gt; that corresponds to this CssMetaData.
1295      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1296      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1297      */
1298     public final CssMetaData<S, Duration>
1299     createDurationCssMetaData(final String property, final Function<S,StyleableProperty<Duration>> function, final Duration initialValue)
1300     {
1301         return createDurationCssMetaData(property, function, initialValue, false);
1302     }
1303 
1304     /**
1305      * Create a CssMetaData&lt;S, Duration&gt; with initial value of Duration.BLACK, and inherit flag defaulting to false.
1306      * @param property The CSS property name.
1307      * @param function A function that returns the StyleableProperty&lt;Duration&gt; that corresponds to this CssMetaData.
1308      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1309      */
1310     public final CssMetaData<S, Duration>
1311     createDurationCssMetaData(final String property, final Function<S,StyleableProperty<Duration>> function)
1312     {
1313         return createDurationCssMetaData(property, function, Duration.UNKNOWN, false);
1314     }
1315 
1316     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1317     //                                                                                                              //
1318     // create CssMetaData<S, Effect>                                                                                 //
1319     //                                                                                                              //
1320     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1321 
1322     /**
1323      * Create a CssMetaData&lt;S, Effect&gt; with initial value, and inherit flag.
1324      * @param property The CSS property name.
1325      * @param function A function that returns the StyleableProperty&lt;Effect&gt; that corresponds to this CssMetaData.
1326      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1327      * @param inherits Whether or not the CSS style can be inherited by child nodes
1328      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1329      */
1330     public final <E extends Effect> CssMetaData<S, E>
1331     createEffectCssMetaData(final String property, final Function<S,StyleableProperty<E>> function, final E initialValue, final boolean inherits)
1332     {
1333         if (property == null || property.isEmpty()) {
1334             throw new IllegalArgumentException("property cannot be null or empty string");
1335         }
1336 
1337         if (function == null) {
1338             throw new IllegalArgumentException("function cannot be null");
1339         }
1340 
1341         @SuppressWarnings("unchecked") // getCssMetaData checks and will throw a ClassCastException
1342         CssMetaData<S, E> cssMetaData =
1343                 (CssMetaData<S, E>)getCssMetaData(Effect.class, property, key -> {
1344                     final StyleConverter<ParsedValue[], Effect> converter = StyleConverter.getEffectConverter();
1345                     return new SimpleCssMetaData(property, function, converter, initialValue, inherits);
1346                 });
1347         return cssMetaData;
1348     }
1349 
1350     /**
1351      * Create a CssMetaData&lt;S, Effect&gt; with initial value, and inherit flag defaulting to false.
1352      * @param property The CSS property name.
1353      * @param function A function that returns the StyleableProperty&lt;Effect&gt; that corresponds to this CssMetaData.
1354      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1355      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1356      */
1357     public final <E extends Effect> CssMetaData<S, E>
1358     createEffectCssMetaData(final String property, final Function<S,StyleableProperty<E>> function, final E initialValue) {
1359         return createEffectCssMetaData(property, function, initialValue, false);
1360     }
1361 
1362     /**
1363      * Create a CssMetaData&lt;S, Effect&gt; with initial value of null, and inherit flag defaulting to false.
1364      * @param property The CSS property name.
1365      * @param function A function that returns the StyleableProperty&lt;Effect&gt; that corresponds to this CssMetaData.
1366      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1367      */
1368     public final <E extends Effect> CssMetaData<S, E>
1369     createEffectCssMetaData(final String property, final Function<S,StyleableProperty<E>> function) {
1370         return createEffectCssMetaData(property, function, null, false);
1371     }
1372 
1373     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1374     //                                                                                                              //
1375     // create CssMetaData<S, Enum>                                                                                 //
1376     //                                                                                                              //
1377     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1378 
1379     /**
1380      * Create a CssMetaData&lt;S, Enum&gt; with initial value, and inherit flag.
1381      * @param property The CSS property name.
1382      * @param function A function that returns the StyleableProperty&lt;Enum&gt; that corresponds to this CssMetaData.
1383      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1384      * @param inherits Whether or not the CSS style can be inherited by child nodes
1385      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1386      */
1387     public final <E extends Enum<E>> CssMetaData<S, E>
1388     createEnumCssMetaData(Class<? extends Enum> enumClass, final String property, final Function<S,StyleableProperty<E>> function, final E initialValue, final boolean inherits)
1389     {
1390         if (property == null || property.isEmpty()) {
1391             throw new IllegalArgumentException("property cannot be null or empty string");
1392         }
1393 
1394         if (function == null) {
1395             throw new IllegalArgumentException("function cannot be null");
1396         }
1397 
1398         @SuppressWarnings("unchecked") // getCssMetaData checks and will throw a ClassCastException
1399         CssMetaData<S, E> cssMetaData =
1400                 (CssMetaData<S, E>)getCssMetaData(enumClass, property, key -> {
1401                     final EnumConverter<E> converter = new EnumConverter(enumClass);
1402                     return new SimpleCssMetaData<S, E>(property, function, converter, initialValue, inherits);
1403                 });
1404         return cssMetaData;
1405     }
1406 
1407     /**
1408      * Create a CssMetaData&lt;S, Enum&gt; with initial value, and inherit flag defaulting to false.
1409      * @param property The CSS property name.
1410      * @param function A function that returns the StyleableProperty&lt;Enum&gt; that corresponds to this CssMetaData.
1411      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1412      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1413      */
1414     public final <E extends Enum<E>> CssMetaData<S, E>
1415     createEnumCssMetaData(Class<? extends Enum> enumClass, final String property, final Function<S,StyleableProperty<E>> function, final E initialValue) {
1416         return createEnumCssMetaData(enumClass, property, function, initialValue, false);
1417     }
1418 
1419     /**
1420      * Create a CssMetaData&lt;S, Enum&gt; with initial value of null, and inherit flag defaulting to false.
1421      * @param property The CSS property name.
1422      * @param function A function that returns the StyleableProperty&lt;Enum&gt; that corresponds to this CssMetaData.
1423      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1424      */
1425     public final <E extends Enum<E>> CssMetaData<S, E>
1426     createEnumCssMetaData(Class<? extends Enum> enumClass, final String property, final Function<S,StyleableProperty<E>> function) {
1427         return createEnumCssMetaData(enumClass, property, function, null, false);
1428     }
1429 
1430     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1431     //                                                                                                              //
1432     // create CssMetaData<S, Font>                                                                                 //
1433     //                                                                                                              //
1434     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1435 
1436     /**
1437      * Create a CssMetaData&lt;S, Font&gt; with initial value, and inherit flag.
1438      * @param property The CSS property name.
1439      * @param function A function that returns the StyleableProperty&lt;Font&gt; that corresponds to this CssMetaData.
1440      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1441      * @param inherits Whether or not the CSS style can be inherited by child nodes
1442      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1443      */
1444     public final CssMetaData<S, Font>
1445     createFontCssMetaData(final String property, final Function<S,StyleableProperty<Font>> function, final Font initialValue, final boolean inherits)
1446     {
1447         if (property == null || property.isEmpty()) {
1448             throw new IllegalArgumentException("property cannot be null or empty string");
1449         }
1450 
1451         if (function == null) {
1452             throw new IllegalArgumentException("function cannot be null");
1453         }
1454 
1455         @SuppressWarnings("unchecked") // getCssMetaData checks and will throw a ClassCastException
1456         CssMetaData<S,Font> cssMetaData =
1457                 (CssMetaData<S,Font>)getCssMetaData(Font.class, property, key -> {
1458                     final StyleConverter<ParsedValue[],Font> converter = StyleConverter.getFontConverter();
1459                     return new SimpleCssMetaData<S, Font>(property, function, converter, initialValue, inherits);
1460                 });
1461         return cssMetaData;
1462     }
1463 
1464     /**
1465      * Create a CssMetaData&lt;S, Font&gt; with initial value, and inherit flag defaulting to true.
1466      * @param property The CSS property name.
1467      * @param function A function that returns the StyleableProperty&lt;Font&gt; that corresponds to this CssMetaData.
1468      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1469      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1470      */
1471     public final CssMetaData<S, Font>
1472     createFontCssMetaData(final String property, final Function<S,StyleableProperty<Font>> function, final Font initialValue) {
1473         return createFontCssMetaData(property, function, initialValue, true);
1474     }
1475 
1476     /**
1477      * Create a CssMetaData&lt;S, Font&gt; with initial value of {@link javafx.scene.text.Font#getDefault()}, and inherit flag defaulting to true.
1478      * @param property The CSS property name.
1479      * @param function A function that returns the StyleableProperty&lt;Font&gt; that corresponds to this CssMetaData.
1480      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1481      */
1482     public final CssMetaData<S, Font>
1483     createFontCssMetaData(final String property, final Function<S,StyleableProperty<Font>> function) {
1484         return createFontCssMetaData(property, function, Font.getDefault(), true);
1485     }
1486 
1487     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1488     //                                                                                                              //
1489     // create CssMetaData<S, Insets>                                                                                 //
1490     //                                                                                                              //
1491     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1492 
1493     /**
1494      * Create a CssMetaData&lt;S, Insets&gt; with initial value, and inherit flag.
1495      * @param property The CSS property name.
1496      * @param function A function that returns the StyleableProperty&lt;Insets&gt; that corresponds to this CssMetaData.
1497      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1498      * @param inherits Whether or not the CSS style can be inherited by child nodes
1499      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1500      */
1501     public final CssMetaData<S, Insets>
1502     createInsetsCssMetaData(final String property, final Function<S,StyleableProperty<Insets>> function, final Insets initialValue, final boolean inherits)
1503     {
1504         if (property == null || property.isEmpty()) {
1505             throw new IllegalArgumentException("property cannot be null or empty string");
1506         }
1507 
1508         if (function == null) {
1509             throw new IllegalArgumentException("function cannot be null");
1510         }
1511 
1512         @SuppressWarnings("unchecked") // getCssMetaData checks and will throw a ClassCastException
1513         CssMetaData<S,Insets> cssMetaData =
1514                 (CssMetaData<S,Insets>)getCssMetaData(Insets.class, property, key -> {
1515                     final StyleConverter<ParsedValue[],Insets> converter = StyleConverter.getInsetsConverter();
1516                     return new SimpleCssMetaData<S, Insets>(property, function, converter, initialValue, inherits);
1517                 });
1518         return cssMetaData;
1519     }
1520 
1521     /**
1522      * Create a CssMetaData&lt;S, Insets&gt; with initial value, and inherit flag defaulting to false.
1523      * @param property The CSS property name.
1524      * @param function A function that returns the StyleableProperty&lt;Insets&gt; that corresponds to this CssMetaData.
1525      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1526      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1527      */
1528     public final CssMetaData<S, Insets>
1529     createInsetsCssMetaData(final String property, final Function<S,StyleableProperty<Insets>> function, final Insets initialValue)
1530     {
1531         return createInsetsCssMetaData(property, function, initialValue, false);
1532 
1533     }
1534     /**
1535      * Create a CssMetaData&lt;S, Insets&gt; with initial value of {@link javafx.geometry.Insets.EMPTY}, and inherit flag defaulting to false.
1536      * @param property The CSS property name.
1537      * @param function A function that returns the StyleableProperty&lt;Insets&gt; that corresponds to this CssMetaData.
1538      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1539      */
1540     public final CssMetaData<S, Insets>
1541     createInsetsCssMetaData(final String property, final Function<S,StyleableProperty<Insets>> function)
1542     {
1543         return createInsetsCssMetaData(property, function, Insets.EMPTY, false);
1544     }
1545 
1546     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1547     //                                                                                                              //
1548     // create CssMetaData<S, Paint>                                                                                 //
1549     //                                                                                                              //
1550     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1551 
1552     /**
1553      * Create a CssMetaData&lt;S, Paint&gt; with initial value, and inherit flag.
1554      * @param property The CSS property name.
1555      * @param function A function that returns the StyleableProperty&lt;Paint&gt; that corresponds to this CssMetaData.
1556      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1557      * @param inherits Whether or not the CSS style can be inherited by child nodes
1558      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1559      */
1560     public final CssMetaData<S, Paint>
1561     createPaintCssMetaData(final String property, final Function<S,StyleableProperty<Paint>> function, final Paint initialValue, final boolean inherits)
1562     {
1563         if (property == null || property.isEmpty()) {
1564             throw new IllegalArgumentException("property cannot be null or empty string");
1565         }
1566 
1567         if (function == null) {
1568             throw new IllegalArgumentException("function cannot be null");
1569         }
1570 
1571         @SuppressWarnings("unchecked") // getCssMetaData checks and will throw a ClassCastException
1572         CssMetaData<S,Paint> cssMetaData =
1573                 (CssMetaData<S,Paint>)getCssMetaData(Paint.class, property, key -> {
1574                     final StyleConverter<ParsedValue<?, Paint>,Paint> converter = StyleConverter.getPaintConverter();
1575                     return new SimpleCssMetaData<S, Paint>(property, function, converter, initialValue, inherits);
1576                 });
1577         return cssMetaData;
1578     }
1579 
1580     /**
1581      * Create a CssMetaData&lt;S, Paint&gt; with initial value, and inherit flag defaulting to false.
1582      * @param property The CSS property name.
1583      * @param function A function that returns the StyleableProperty&lt;Paint&gt; that corresponds to this CssMetaData.
1584      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1585      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1586      */
1587     public final CssMetaData<S, Paint>
1588     createPaintCssMetaData(final String property, final Function<S,StyleableProperty<Paint>> function, final Paint initialValue) {
1589         return createPaintCssMetaData(property, function, initialValue, false);
1590     }
1591 
1592     /**
1593      * Create a CssMetaData&lt;S, Paint&gt; with initial value of Color.BLACK, and inherit flag defaulting to false.
1594      * @param property The CSS property name.
1595      * @param function A function that returns the StyleableProperty&lt;Paint&gt; that corresponds to this CssMetaData.
1596      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1597      */
1598     public final CssMetaData<S, Paint>
1599     createPaintCssMetaData(final String property, final Function<S,StyleableProperty<Paint>> function) {
1600         return createPaintCssMetaData(property, function, Color.BLACK, false);
1601     }
1602 
1603     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1604     //                                                                                                              //
1605     // create CssMetaData<S, Number>                                                                                 //
1606     //                                                                                                              //
1607     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1608 
1609     /**
1610      * Create a CssMetaData&lt;S, Number&gt; with initial value, and inherit flag.
1611      * @param property The CSS property name.
1612      * @param function A function that returns the StyleableProperty&lt;Number&gt; that corresponds to this CssMetaData.
1613      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1614      * @param inherits Whether or not the CSS style can be inherited by child nodes
1615      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1616      */
1617     public final CssMetaData<S, Number>
1618     createSizeCssMetaData(final String property, final Function<S,StyleableProperty<Number>> function, final Number initialValue, final boolean inherits)
1619     {
1620         if (property == null || property.isEmpty()) {
1621             throw new IllegalArgumentException("property cannot be null or empty string");
1622         }
1623 
1624         if (function == null) {
1625             throw new IllegalArgumentException("function cannot be null");
1626         }
1627 
1628         @SuppressWarnings("unchecked") // getCssMetaData checks and will throw a ClassCastException
1629         CssMetaData<S,Number> cssMetaData =
1630                 (CssMetaData<S,Number>)getCssMetaData(Number.class, property, key -> {
1631                     final StyleConverter<?,Number> converter = StyleConverter.getSizeConverter();
1632                     return new SimpleCssMetaData<S, Number>(property, function, converter, initialValue, inherits);
1633                 });
1634         return cssMetaData;
1635     }
1636 
1637     /**
1638      * Create a CssMetaData&lt;S, Number&gt; with initial value, and inherit flag defaulting to false.
1639      * @param property The CSS property name.
1640      * @param function A function that returns the StyleableProperty&lt;Number&gt; that corresponds to this CssMetaData.
1641      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1642      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1643      */
1644     public final CssMetaData<S, Number>
1645     createSizeCssMetaData(final String property, final Function<S,StyleableProperty<Number>> function, final Number initialValue) {
1646         return createSizeCssMetaData(property, function, initialValue, false);
1647     }
1648 
1649     /**
1650      * Create a CssMetaData&lt;S, Number&gt; with initial value of <code>0d</code>, and inherit flag defaulting to false.
1651      * @param property The CSS property name.
1652      * @param function A function that returns the StyleableProperty&lt;Number&gt; that corresponds to this CssMetaData.
1653      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1654      */
1655     public final CssMetaData<S, Number>
1656     createSizeCssMetaData(final String property, final Function<S,StyleableProperty<Number>> function) {
1657         return createSizeCssMetaData(property, function, 0d, false);
1658     }
1659 
1660     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1661     //                                                                                                              //
1662     // create CssMetaData<S, String>                                                                                 //
1663     //                                                                                                              //
1664     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1665 
1666     /**
1667      * Create a CssMetaData&lt;S, String&gt; with initial value, and inherit flag.
1668      * @param property The CSS property name.
1669      * @param function A function that returns the StyleableProperty&lt;String&gt; that corresponds to this CssMetaData.
1670      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1671      * @param inherits Whether or not the CSS style can be inherited by child nodes
1672      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1673      */
1674     public final CssMetaData<S, String>
1675     createStringCssMetaData(final String property, final Function<S,StyleableProperty<String>> function, final String initialValue, final boolean inherits)
1676     {
1677         if (property == null || property.isEmpty()) {
1678             throw new IllegalArgumentException("property cannot be null or empty string");
1679         }
1680 
1681         if (function == null) {
1682             throw new IllegalArgumentException("function cannot be null");
1683         }
1684 
1685         @SuppressWarnings("unchecked") // getCssMetaData checks and will throw a ClassCastException
1686         CssMetaData<S,String> cssMetaData =
1687                 (CssMetaData<S,String>)getCssMetaData(String.class, property, key -> {
1688                     final StyleConverter<String,String> converter = StyleConverter.getStringConverter();
1689                     return new SimpleCssMetaData<S, String>(property, function, converter, initialValue, inherits);
1690                 });
1691         return cssMetaData;
1692     }
1693 
1694     /**
1695      * Create a CssMetaData&lt;S, String&gt; with initial value, and inherit flag defaulting to false.
1696      * @param property The CSS property name.
1697      * @param function A function that returns the StyleableProperty&lt;String&gt; that corresponds to this CssMetaData.
1698      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1699      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1700      */
1701     public final CssMetaData<S, String>
1702     createStringCssMetaData(final String property, final Function<S,StyleableProperty<String>> function, final String initialValue) {
1703         return createStringCssMetaData(property, function, initialValue, false);
1704     }
1705 
1706     /**
1707      * Create a CssMetaData&lt;S, String&gt; with initial value of null, and inherit flag defaulting to false.
1708      * @param property The CSS property name.
1709      * @param function A function that returns the StyleableProperty&lt;String&gt; that corresponds to this CssMetaData.
1710      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1711      */
1712     public final CssMetaData<S, String>
1713     createStringCssMetaData(final String property, final Function<S,StyleableProperty<String>> function) {
1714         return createStringCssMetaData(property, function, null, false);
1715     }
1716 
1717     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1718     //                                                                                                              //
1719     // create CssMetaData<S, String>                                                                                 //
1720     //                                                                                                              //
1721     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1722 
1723     /**
1724      * Create a CssMetaData&lt;S, String&gt; with initial value, and inherit flag.
1725      * Here, the String value represents a URL converted from a
1726      * <a href="http://www.w3.org/TR/CSS21/syndata.html#uri">CSS</a> url("<path>").
1727      * @param property The CSS property name.
1728      * @param function A function that returns the StyleableProperty&lt;String&gt; that corresponds to this CssMetaData.
1729      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1730      * @param inherits Whether or not the CSS style can be inherited by child nodes
1731      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1732      */
1733     public final CssMetaData<S, String>
1734     createUrlCssMetaData(final String property, final Function<S,StyleableProperty<String>> function, final String initialValue, final boolean inherits)
1735     {
1736         if (property == null || property.isEmpty()) {
1737             throw new IllegalArgumentException("property cannot be null or empty string");
1738         }
1739 
1740         if (function == null) {
1741             throw new IllegalArgumentException("function cannot be null");
1742         }
1743 
1744         @SuppressWarnings("unchecked") // getCssMetaData checks and will throw a ClassCastException
1745         CssMetaData<S,String> cssMetaData =
1746                 (CssMetaData<S,String>)getCssMetaData(java.net.URL.class, property, key -> {
1747                     final StyleConverter<ParsedValue[],String> converter = StyleConverter.getUrlConverter();
1748                     return new SimpleCssMetaData<S, String>(property, function, converter, initialValue, inherits);
1749                 });
1750         return cssMetaData;
1751     }
1752 
1753     /**
1754      * Create a CssMetaData&lt;S, String&gt; with initial value, and inherit flag defaulting to false.
1755      * Here, the String value represents a URL converted from a
1756      * <a href="http://www.w3.org/TR/CSS21/syndata.html#uri">CSS</a> url("<path>").
1757      * @param property The CSS property name.
1758      * @param function A function that returns the StyleableProperty&lt;String&gt; that corresponds to this CssMetaData.
1759      * @param initialValue The initial value of the property. CSS may reset the property to this value.
1760      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1761      */
1762     public final CssMetaData<S, String>
1763     createUrlCssMetaData(final String property, final Function<S,StyleableProperty<String>> function, final String initialValue) {
1764         return createUrlCssMetaData(property, function, initialValue, false);
1765     }
1766 
1767     /**
1768      * Create a CssMetaData&lt;S, String&gt; with initial value of null, and inherit flag defaulting to false.
1769      * Here, the String value represents a URL converted from a
1770      * <a href="http://www.w3.org/TR/CSS21/syndata.html#uri">CSS</a> url("<path>").
1771      * @param property The CSS property name.
1772      * @param function A function that returns the StyleableProperty&lt;String&gt; that corresponds to this CssMetaData.
1773      * @throws java.lang.IllegalArgumentException if <code>property</code> is null or an empty string, or <code>function</code> is null.
1774      */
1775     public final CssMetaData<S, String>
1776     createUrlCssMetaData(final String property, final Function<S,StyleableProperty<String>> function) {
1777         return createUrlCssMetaData(property, function, null, false);
1778     }
1779 
1780     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1781     //                                                                                                              //
1782     // SimpleCssMetaData is an implementation of CssMetaData that uses a Function<S, StyleableProperty<V>>          //
1783     // to get the StyleableProperty from the Styleable. This is the function that is passed in on the
1784     // various create methods.
1785     //                                                                                                              //
1786     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1787     private static class SimpleCssMetaData<S extends Styleable,V> extends CssMetaData<S,V> {
1788 
1789         SimpleCssMetaData(
1790                 final String property,
1791                 final Function<S, StyleableProperty<V>> function,
1792                 final StyleConverter<?, V> converter,
1793                 final V initialValue,
1794                 final boolean inherits)
1795         {
1796             super(property, converter, initialValue, inherits);
1797             this.function = function;
1798         }
1799 
1800         private final Function<S,StyleableProperty<V>> function;
1801 
1802         public final boolean isSettable(S styleable) {
1803             final StyleableProperty<V> prop = getStyleableProperty(styleable);
1804             if (prop instanceof Property) {
1805                 return !((Property)prop).isBound();
1806             }
1807             // can't set this property if getStyleableProperty returns null!
1808             return prop != null;
1809         }
1810 
1811         /** {@inheritDoc} */
1812         @Override
1813         public final StyleableProperty<V> getStyleableProperty(S styleable) {
1814             if (styleable != null) {
1815                 StyleableProperty<V> property = function.apply(styleable);
1816                 return property;
1817             }
1818             return null;
1819         }
1820 
1821     }
1822 
1823     // for testing only
1824     void clearDataForTesting() {
1825         metaDataMap.clear();
1826         metaDataList.clear();
1827     }
1828 
1829     private CssMetaData<S, ?> getCssMetaData(final Class ofClass, String property) {
1830         return getCssMetaData(ofClass, property, null);
1831     }
1832 
1833     private CssMetaData<S, ?> getCssMetaData(final Class ofClass, String property, final Function<String,CssMetaData<S,?>> createFunction) {
1834 
1835         final String key = property.toLowerCase();
1836 
1837         Pair<Class,CssMetaData<S,?>> entry = metaDataMap.get(key);
1838         if (entry != null) {
1839             if (entry.getKey() == ofClass) {
1840                 return entry.getValue();
1841             } else {
1842                 throw new ClassCastException("CssMetaData value is not " + ofClass + ": " + entry.getValue());
1843             }
1844         } else if (createFunction == null) {
1845             throw new NoSuchElementException("No CssMetaData for " + key);
1846         }
1847 
1848         // Entry was null
1849         CssMetaData<S,?> cssMetaData = createFunction.apply(key);
1850         metaDataMap.put(key, new Pair(ofClass, cssMetaData));
1851         metaDataList.add(cssMetaData);
1852         return cssMetaData;
1853     }
1854 
1855     private final Map<String,Pair<Class,CssMetaData<S,?>>> metaDataMap;
1856     private final List<CssMetaData<? extends Styleable,?>> unmodifiableMetaDataList;
1857     private final List<CssMetaData<? extends Styleable,?>> metaDataList;
1858     
1859 }