1 /*
   2  * Copyright (c) 2010, 2016, 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.beans.binding;
  27 
  28 import java.lang.ref.WeakReference;
  29 import java.text.Format;
  30 import java.util.List;
  31 import java.util.Locale;
  32 import java.util.Map;
  33 import java.util.Set;
  34 import java.util.concurrent.Callable;
  35 import javafx.beans.InvalidationListener;
  36 import javafx.beans.Observable;
  37 import javafx.beans.property.Property;
  38 import javafx.beans.value.ObservableBooleanValue;
  39 import javafx.beans.value.ObservableDoubleValue;
  40 import javafx.beans.value.ObservableFloatValue;
  41 import javafx.beans.value.ObservableIntegerValue;
  42 import javafx.beans.value.ObservableLongValue;
  43 import javafx.beans.value.ObservableNumberValue;
  44 import javafx.beans.value.ObservableObjectValue;
  45 import javafx.beans.value.ObservableStringValue;
  46 import javafx.beans.value.ObservableValue;
  47 import javafx.collections.FXCollections;
  48 import javafx.collections.ObservableList;
  49 import javafx.collections.ObservableMap;
  50 import javafx.collections.ObservableSet;
  51 import javafx.util.StringConverter;
  52 import com.sun.javafx.binding.BidirectionalBinding;
  53 import com.sun.javafx.binding.BidirectionalContentBinding;
  54 import com.sun.javafx.binding.ContentBinding;
  55 import com.sun.javafx.binding.DoubleConstant;
  56 import com.sun.javafx.binding.FloatConstant;
  57 import com.sun.javafx.binding.IntegerConstant;
  58 import com.sun.javafx.binding.Logging;
  59 import com.sun.javafx.binding.LongConstant;
  60 import com.sun.javafx.binding.ObjectConstant;
  61 import com.sun.javafx.binding.SelectBinding;
  62 import com.sun.javafx.binding.StringConstant;
  63 import com.sun.javafx.binding.StringFormatter;
  64 import com.sun.javafx.collections.ImmutableObservableList;
  65 import javafx.collections.ObservableArray;
  66 import javafx.collections.ObservableFloatArray;
  67 import javafx.collections.ObservableIntegerArray;
  68 
  69 /**
  70  * Bindings is a helper class with a lot of utility functions to create simple
  71  * bindings.
  72  * <p>
  73  * Usually there are two possibilities to define the same operation: the Fluent
  74  * API and the the factory methods in this class. This allows a developer to
  75  * define complex expression in a way that is most easy to understand. For
  76  * instance the expression {@code result = a*b + c*d} can be defined using only
  77  * the Fluent API:
  78  * <p>
  79  * {@code DoubleBinding result = a.multiply(b).add(c.multiply(d));}
  80  * <p>
  81  * Or using only factory methods in Bindings:
  82  * <p>
  83  * {@code NumberBinding result = add (multiply(a, b), multiply(c,d));}
  84  * <p>
  85  * Or mixing both possibilities:
  86  * <p>
  87  * {@code NumberBinding result = add (a.multiply(b), c.multiply(d));}
  88  * <p>
  89  * The main difference between using the Fluent API and using the factory
  90  * methods in this class is that the Fluent API requires that at least one of
  91  * the operands is an Expression (see {@link javafx.beans.binding}). (Every
  92  * Expression contains a static method that generates an Expression from an
  93  * {@link javafx.beans.value.ObservableValue}.)
  94  * <p>
  95  * Also if you watched closely, you might have noticed that the return type of
  96  * the Fluent API is different in the examples above. In a lot of cases the
  97  * Fluent API allows to be more specific about the returned type (see
  98  * {@link javafx.beans.binding.NumberExpression} for more details about implicit
  99  * casting.
 100  *
 101  * @see Binding
 102  * @see NumberBinding
 103  *
 104  *
 105  * @since JavaFX 2.0
 106  */
 107 public final class Bindings {
 108 
 109     private Bindings() {
 110     }
 111 
 112     // =================================================================================================================
 113     // Helper functions to create custom bindings
 114 
 115     /**
 116      * Helper function to create a custom {@link BooleanBinding}.
 117      *
 118      * @param func The function that calculates the value of this binding
 119      * @param dependencies The dependencies of this binding
 120      * @return The generated binding
 121      * @since JavaFX 2.1
 122      */
 123     public static BooleanBinding createBooleanBinding(final Callable<Boolean> func, final Observable... dependencies) {
 124         return new BooleanBinding() {
 125             {
 126                 bind(dependencies);
 127             }
 128 
 129             @Override
 130             protected boolean computeValue() {
 131                 try {
 132                     return func.call();
 133                 } catch (Exception e) {
 134                     Logging.getLogger().warning("Exception while evaluating binding", e);
 135                     return false;
 136                 }
 137             }
 138 
 139             @Override
 140             public void dispose() {
 141                 super.unbind(dependencies);
 142             }
 143 
 144             @Override
 145             public ObservableList<?> getDependencies() {
 146                 return  ((dependencies == null) || (dependencies.length == 0))?
 147                             FXCollections.emptyObservableList()
 148                         : (dependencies.length == 1)?
 149                             FXCollections.singletonObservableList(dependencies[0])
 150                         : new ImmutableObservableList<Observable>(dependencies);
 151             }
 152         };
 153     }
 154 
 155     /**
 156      * Helper function to create a custom {@link DoubleBinding}.
 157      *
 158      * @param func The function that calculates the value of this binding
 159      * @param dependencies The dependencies of this binding
 160      * @return The generated binding
 161      * @since JavaFX 2.1
 162      */
 163     public static DoubleBinding createDoubleBinding(final Callable<Double> func, final Observable... dependencies) {
 164         return new DoubleBinding() {
 165             {
 166                 bind(dependencies);
 167             }
 168 
 169             @Override
 170             protected double computeValue() {
 171                 try {
 172                     return func.call();
 173                 } catch (Exception e) {
 174                     Logging.getLogger().warning("Exception while evaluating binding", e);
 175                     return 0.0;
 176                 }
 177             }
 178 
 179             @Override
 180             public void dispose() {
 181                 super.unbind(dependencies);
 182             }
 183 
 184             @Override
 185             public ObservableList<?> getDependencies() {
 186                 return  ((dependencies == null) || (dependencies.length == 0))?
 187                             FXCollections.emptyObservableList()
 188                         : (dependencies.length == 1)?
 189                             FXCollections.singletonObservableList(dependencies[0])
 190                         : new ImmutableObservableList<Observable>(dependencies);
 191             }
 192         };
 193     }
 194 
 195     /**
 196      * Helper function to create a custom {@link FloatBinding}.
 197      *
 198      * @param func The function that calculates the value of this binding
 199      * @param dependencies The dependencies of this binding
 200      * @return The generated binding
 201      * @since JavaFX 2.1
 202      */
 203     public static FloatBinding createFloatBinding(final Callable<Float> func, final Observable... dependencies) {
 204         return new FloatBinding() {
 205             {
 206                 bind(dependencies);
 207             }
 208 
 209             @Override
 210             protected float computeValue() {
 211                 try {
 212                     return func.call();
 213                 } catch (Exception e) {
 214                     Logging.getLogger().warning("Exception while evaluating binding", e);
 215                     return 0.0f;
 216                 }
 217             }
 218 
 219             @Override
 220             public void dispose() {
 221                 super.unbind(dependencies);
 222             }
 223 
 224             @Override
 225             public ObservableList<?> getDependencies() {
 226                 return  ((dependencies == null) || (dependencies.length == 0))?
 227                             FXCollections.emptyObservableList()
 228                         : (dependencies.length == 1)?
 229                             FXCollections.singletonObservableList(dependencies[0])
 230                         : new ImmutableObservableList<Observable>(dependencies);
 231             }
 232         };
 233     }
 234 
 235     /**
 236      * Helper function to create a custom {@link IntegerBinding}.
 237      *
 238      * @param func The function that calculates the value of this binding
 239      * @param dependencies The dependencies of this binding
 240      * @return The generated binding
 241      * @since JavaFX 2.1
 242      */
 243     public static IntegerBinding createIntegerBinding(final Callable<Integer> func, final Observable... dependencies) {
 244         return new IntegerBinding() {
 245             {
 246                 bind(dependencies);
 247             }
 248 
 249             @Override
 250             protected int computeValue() {
 251                 try {
 252                     return func.call();
 253                 } catch (Exception e) {
 254                     Logging.getLogger().warning("Exception while evaluating binding", e);
 255                     return 0;
 256                 }
 257             }
 258 
 259             @Override
 260             public void dispose() {
 261                 super.unbind(dependencies);
 262             }
 263 
 264             @Override
 265             public ObservableList<?> getDependencies() {
 266                 return  ((dependencies == null) || (dependencies.length == 0))?
 267                             FXCollections.emptyObservableList()
 268                         : (dependencies.length == 1)?
 269                             FXCollections.singletonObservableList(dependencies[0])
 270                         : new ImmutableObservableList<Observable>(dependencies);
 271             }
 272         };
 273     }
 274 
 275     /**
 276      * Helper function to create a custom {@link LongBinding}.
 277      *
 278      * @param func The function that calculates the value of this binding
 279      * @param dependencies The dependencies of this binding
 280      * @return The generated binding
 281      * @since JavaFX 2.1
 282      */
 283     public static LongBinding createLongBinding(final Callable<Long> func, final Observable... dependencies) {
 284         return new LongBinding() {
 285             {
 286                 bind(dependencies);
 287             }
 288 
 289             @Override
 290             protected long computeValue() {
 291                 try {
 292                     return func.call();
 293                 } catch (Exception e) {
 294                     Logging.getLogger().warning("Exception while evaluating binding", e);
 295                     return 0L;
 296                 }
 297             }
 298 
 299             @Override
 300             public void dispose() {
 301                 super.unbind(dependencies);
 302             }
 303 
 304             @Override
 305             public ObservableList<?> getDependencies() {
 306                 return  ((dependencies == null) || (dependencies.length == 0))?
 307                             FXCollections.emptyObservableList()
 308                         : (dependencies.length == 1)?
 309                             FXCollections.singletonObservableList(dependencies[0])
 310                         : new ImmutableObservableList<Observable>(dependencies);
 311             }
 312         };
 313     }
 314 
 315     /**
 316      * Helper function to create a custom {@link ObjectBinding}.
 317      *
 318      * @param <T> the type of the bound {@code Object}
 319      * @param func The function that calculates the value of this binding
 320      * @param dependencies The dependencies of this binding
 321      * @return The generated binding
 322      * @since JavaFX 2.1
 323      */
 324     public static <T> ObjectBinding<T> createObjectBinding(final Callable<T> func, final Observable... dependencies) {
 325         return new ObjectBinding<T>() {
 326             {
 327                 bind(dependencies);
 328             }
 329 
 330             @Override
 331             protected T computeValue() {
 332                 try {
 333                     return func.call();
 334                 } catch (Exception e) {
 335                     Logging.getLogger().warning("Exception while evaluating binding", e);
 336                     return null;
 337                 }
 338             }
 339 
 340             @Override
 341             public void dispose() {
 342                 super.unbind(dependencies);
 343             }
 344 
 345             @Override
 346             public ObservableList<?> getDependencies() {
 347                 return  ((dependencies == null) || (dependencies.length == 0))?
 348                             FXCollections.emptyObservableList()
 349                         : (dependencies.length == 1)?
 350                             FXCollections.singletonObservableList(dependencies[0])
 351                         : new ImmutableObservableList<Observable>(dependencies);
 352             }
 353         };
 354     }
 355 
 356     /**
 357      * Helper function to create a custom {@link StringBinding}.
 358      *
 359      * @param func The function that calculates the value of this binding
 360      * @param dependencies The dependencies of this binding
 361      * @return The generated binding
 362      * @since JavaFX 2.1
 363      */
 364     public static StringBinding createStringBinding(final Callable<String> func, final Observable... dependencies) {
 365         return new StringBinding() {
 366             {
 367                 bind(dependencies);
 368             }
 369 
 370             @Override
 371             protected String computeValue() {
 372                 try {
 373                     return func.call();
 374                 } catch (Exception e) {
 375                     Logging.getLogger().warning("Exception while evaluating binding", e);
 376                     return "";
 377                 }
 378             }
 379 
 380             @Override
 381             public void dispose() {
 382                 super.unbind(dependencies);
 383             }
 384 
 385             @Override
 386             public ObservableList<?> getDependencies() {
 387                 return  ((dependencies == null) || (dependencies.length == 0))?
 388                             FXCollections.emptyObservableList()
 389                         : (dependencies.length == 1)?
 390                             FXCollections.singletonObservableList(dependencies[0])
 391                         : new ImmutableObservableList<Observable>(dependencies);
 392             }
 393         };
 394     }
 395 
 396 
 397     // =================================================================================================================
 398     // Select Bindings
 399 
 400     /**
 401      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 402      * of the binding will be {@code c}, or {@code null} if {@code c} could not
 403      * be reached (due to {@code b} not having a {@code c} property,
 404      * {@code b} being {@code null}, or {@code c} not being the right type etc.).
 405      * <p>
 406      * All classes and properties used in a select-binding have to be public.
 407      *
 408      * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
 409      *
 410      * @param <T> the type of the wrapped {@code Object}
 411      * @param root
 412      *            The root {@link javafx.beans.value.ObservableValue}
 413      * @param steps
 414      *            The property names to reach the final property
 415      * @return the created {@link ObjectBinding}
 416      */
 417     public static <T> ObjectBinding<T> select(ObservableValue<?> root, String... steps) {
 418         return new SelectBinding.AsObject<T>(root, steps);
 419     }
 420 
 421     /**
 422      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 423      * of the binding will be {@code c}, or {@code 0.0} if {@code c} could not
 424      * be reached (due to {@code b} not having a {@code c} property,
 425      * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
 426      * <p>
 427      * All classes and properties used in a select-binding have to be public.
 428      *
 429      * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
 430      *
 431      * @param root
 432      *            The root {@link javafx.beans.value.ObservableValue}
 433      * @param steps
 434      *            The property names to reach the final property
 435      * @return the created {@link DoubleBinding}
 436      */
 437     public static DoubleBinding selectDouble(ObservableValue<?> root, String... steps) {
 438         return new SelectBinding.AsDouble(root, steps);
 439     }
 440 
 441     /**
 442      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 443      * of the binding will be {@code c}, or {@code 0.0f} if {@code c} could not
 444      * be reached (due to {@code b} not having a {@code c} property,
 445      * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
 446      * <p>
 447      * All classes and properties used in a select-binding have to be public.
 448      *
 449      * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
 450      *
 451      * @param root
 452      *            The root {@link javafx.beans.value.ObservableValue}
 453      * @param steps
 454      *            The property names to reach the final property
 455      * @return the created {@link FloatBinding}
 456      */
 457     public static FloatBinding selectFloat(ObservableValue<?> root, String... steps) {
 458         return new SelectBinding.AsFloat(root, steps);
 459     }
 460 
 461     /**
 462      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 463      * of the binding will be {@code c}, or {@code 0} if {@code c} could not
 464      * be reached (due to {@code b} not having a {@code c} property,
 465      * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
 466      * <p>
 467      * All classes and properties used in a select-binding have to be public.
 468      *
 469      * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
 470      *
 471      * @param root
 472      *            The root {@link javafx.beans.value.ObservableValue}
 473      * @param steps
 474      *            The property names to reach the final property
 475      * @return the created {@link IntegerBinding}
 476      */
 477     public static IntegerBinding selectInteger(ObservableValue<?> root, String... steps) {
 478         return new SelectBinding.AsInteger(root, steps);
 479     }
 480 
 481     /**
 482      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 483      * of the binding will be {@code c}, or {@code 0L} if {@code c} could not
 484      * be reached (due to {@code b} not having a {@code c} property,
 485      * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
 486      * <p>
 487      * All classes and properties used in a select-binding have to be public.
 488      *
 489      * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
 490      *
 491      * @param root
 492      *            The root {@link javafx.beans.value.ObservableValue}
 493      * @param steps
 494      *            The property names to reach the final property
 495      * @return the created {@link LongBinding}
 496      */
 497     public static LongBinding selectLong(ObservableValue<?> root, String... steps) {
 498         return new SelectBinding.AsLong(root, steps);
 499     }
 500 
 501     /**
 502      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 503      * of the binding will be {@code c}, or {@code false} if {@code c} could not
 504      * be reached (due to {@code b} not having a {@code c} property,
 505      * {@code b} being {@code null}, or {@code c} not being a {@code boolean} etc.).
 506      * <p>
 507      * All classes and properties used in a select-binding have to be public.
 508      *
 509      * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
 510      *
 511      * @param root
 512      *            The root {@link javafx.beans.value.ObservableValue}
 513      * @param steps
 514      *            The property names to reach the final property
 515      * @return the created {@link ObjectBinding}
 516      */
 517     public static BooleanBinding selectBoolean(ObservableValue<?> root, String... steps) {
 518         return new SelectBinding.AsBoolean(root, steps);
 519     }
 520 
 521     /**
 522      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 523      * of the binding will be {@code c}, or {@code ""} if {@code c} could not
 524      * be reached (due to {@code b} not having a {@code c} property,
 525      * {@code b} being {@code null}, or {@code c} not being a {@code String} etc.).
 526      * <p>
 527      * All classes and properties used in a select-binding have to be public.
 528      *
 529      * Note: since 8.0, JavaBeans properties are supported and might be in the chain.
 530      *
 531      * @param root
 532      *            The root {@link javafx.beans.value.ObservableValue}
 533      * @param steps
 534      *            The property names to reach the final property
 535      * @return the created {@link ObjectBinding}
 536      */
 537     public static StringBinding selectString(ObservableValue<?> root, String... steps) {
 538         return new SelectBinding.AsString(root, steps);
 539     }
 540 
 541     /**
 542      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 543      * of the binding will be {@code c}, or {@code null} if {@code c} could not
 544      * be reached (due to {@code b} not having a {@code c} property,
 545      * {@code b} being {@code null}, or {@code c} not being the right type etc.).
 546      * <p>
 547      * All classes and properties used in a select-binding have to be public.
 548      *
 549      * If root has JavaFX properties, this call is equivalent to {@link #select(javafx.beans.value.ObservableValue, java.lang.String[])},
 550      * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
 551      *
 552      * @param <T> the type of the wrapped {@code Object}
 553      * @param root
 554      *            The root bean.
 555      * @param steps
 556      *            The property names to reach the final property. The first step
 557      *            must be specified as it marks the property of the root bean.
 558      * @return the created {@link ObjectBinding}
 559      * @since JavaFX 8.0
 560      */
 561     public static <T> ObjectBinding<T> select(Object root, String... steps) {
 562         return new SelectBinding.AsObject<T>(root, steps);
 563     }
 564 
 565     /**
 566      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 567      * of the binding will be {@code c}, or {@code 0.0} if {@code c} could not
 568      * be reached (due to {@code b} not having a {@code c} property,
 569      * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
 570      * <p>
 571      * All classes and properties used in a select-binding have to be public.
 572      *
 573      * If root has JavaFX properties, this call is equivalent to {@link #selectDouble(javafx.beans.value.ObservableValue, java.lang.String[])},
 574      * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
 575      *
 576      * @param root
 577      *            The root bean.
 578      * @param steps
 579      *            The property names to reach the final property. The first step
 580      *            must be specified as it marks the property of the root bean.
 581      * @return the created {@link DoubleBinding}
 582      * @since JavaFX 8.0
 583      */
 584     public static DoubleBinding selectDouble(Object root, String... steps) {
 585         return new SelectBinding.AsDouble(root, steps);
 586     }
 587 
 588     /**
 589      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 590      * of the binding will be {@code c}, or {@code 0.0f} if {@code c} could not
 591      * be reached (due to {@code b} not having a {@code c} property,
 592      * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
 593      * <p>
 594      * All classes and properties used in a select-binding have to be public.
 595      *
 596      * If root has JavaFX properties, this call is equivalent to {@link #selectFloat(javafx.beans.value.ObservableValue, java.lang.String[])},
 597      * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
 598      *
 599      * @param root
 600      *            The root bean.
 601      * @param steps
 602      *            The property names to reach the final property. The first step
 603      *            must be specified as it marks the property of the root bean.
 604      * @return the created {@link FloatBinding}
 605      * @since JavaFX 8.0
 606      */
 607     public static FloatBinding selectFloat(Object root, String... steps) {
 608         return new SelectBinding.AsFloat(root, steps);
 609     }
 610 
 611     /**
 612      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 613      * of the binding will be {@code c}, or {@code 0} if {@code c} could not
 614      * be reached (due to {@code b} not having a {@code c} property,
 615      * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
 616      * <p>
 617      * All classes and properties used in a select-binding have to be public.
 618      *
 619      * If root has JavaFX properties, this call is equivalent to {@link #selectInteger(javafx.beans.value.ObservableValue, java.lang.String[])},
 620      * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
 621      *
 622      * @param root
 623      *            The root bean.
 624      * @param steps
 625      *            The property names to reach the final property. The first step
 626      *            must be specified as it marks the property of the root bean.
 627      * @return the created {@link IntegerBinding}
 628      * @since JavaFX 8.0
 629      */
 630     public static IntegerBinding selectInteger(Object root, String... steps) {
 631         return new SelectBinding.AsInteger(root, steps);
 632     }
 633 
 634     /**
 635      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 636      * of the binding will be {@code c}, or {@code 0L} if {@code c} could not
 637      * be reached (due to {@code b} not having a {@code c} property,
 638      * {@code b} being {@code null}, or {@code c} not being a {@code Number} etc.).
 639      * <p>
 640      * All classes and properties used in a select-binding have to be public.
 641      *
 642      * If root has JavaFX properties, this call is equivalent to {@link #selectLong(javafx.beans.value.ObservableValue, java.lang.String[])},
 643      * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
 644      *
 645      * @param root
 646      *            The root bean.
 647      * @param steps
 648      *            The property names to reach the final property. The first step
 649      *            must be specified as it marks the property of the root bean.
 650      * @return the created {@link LongBinding}
 651      * @since JavaFX 8.0
 652      */
 653     public static LongBinding selectLong(Object root, String... steps) {
 654         return new SelectBinding.AsLong(root, steps);
 655     }
 656 
 657     /**
 658      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 659      * of the binding will be {@code c}, or {@code false} if {@code c} could not
 660      * be reached (due to {@code b} not having a {@code c} property,
 661      * {@code b} being {@code null}, or {@code c} not being a {@code boolean} etc.).
 662      * <p>
 663      * All classes and properties used in a select-binding have to be public.
 664      *
 665      * If root has JavaFX properties, this call is equivalent to {@link #selectBoolean(javafx.beans.value.ObservableValue, java.lang.String[])},
 666      * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
 667      *
 668      * @param root
 669      *            The root bean.
 670      * @param steps
 671      *            The property names to reach the final property. The first step
 672      *            must be specified as it marks the property of the root bean.
 673      * @return the created {@link ObjectBinding}
 674      * @since JavaFX 8.0
 675      */
 676     public static BooleanBinding selectBoolean(Object root, String... steps) {
 677         return new SelectBinding.AsBoolean(root, steps);
 678     }
 679 
 680     /**
 681      * Creates a binding used to get a member, such as {@code a.b.c}. The value
 682      * of the binding will be {@code c}, or {@code ""} if {@code c} could not
 683      * be reached (due to {@code b} not having a {@code c} property,
 684      * {@code b} being {@code null}, or {@code c} not being a {@code String} etc.).
 685      * <p>
 686      * All classes and properties used in a select-binding have to be public.
 687      *
 688      * If root has JavaFX properties, this call is equivalent to {@link #selectString(javafx.beans.value.ObservableValue, java.lang.String[])},
 689      * with the {@code root} and {@code step[0]} being substituted with the relevant property object.
 690      *
 691      * @param root
 692      *            The root bean.
 693      * @param steps
 694      *            The property names to reach the final property. The first step
 695      *            must be specified as it marks the property of the root bean.
 696      * @return the created {@link ObjectBinding}
 697      * @since JavaFX 8.0
 698      */
 699     public static StringBinding selectString(Object root, String... steps) {
 700         return new SelectBinding.AsString(root, steps);
 701     }
 702 
 703     /**
 704      * Creates a binding that calculates the result of a ternary expression. See
 705      * the description of class {@link When} for details.
 706      *
 707      * @see When
 708      *
 709      * @param condition
 710      *            the condition of the ternary expression
 711      * @return an intermediate class to build the complete binding
 712      */
 713     public static When when(final ObservableBooleanValue condition) {
 714         return new When(condition);
 715     }
 716 
 717     // =================================================================================================================
 718     // Bidirectional Bindings
 719 
 720     /**
 721      * Generates a bidirectional binding (or "bind with inverse") between two
 722      * instances of {@link javafx.beans.property.Property}.
 723      * <p>
 724      * A bidirectional binding is a binding that works in both directions. If
 725      * two properties {@code a} and {@code b} are linked with a bidirectional
 726      * binding and the value of {@code a} changes, {@code b} is set to the same
 727      * value automatically. And vice versa, if {@code b} changes, {@code a} is
 728      * set to the same value.
 729      * <p>
 730      * A bidirectional binding can be removed with
 731      * {@link #unbindBidirectional(Property, Property)}.
 732      * <p>
 733      * Note: this implementation of a bidirectional binding behaves differently
 734      * from all other bindings here in two important aspects. A property that is
 735      * linked to another property with a bidirectional binding can still be set
 736      * (usually bindings would throw an exception). Secondly bidirectional
 737      * bindings are calculated eagerly, i.e. a bound property is updated
 738      * immediately.
 739      *
 740      * @param <T>
 741      *            the types of the properties
 742      * @param property1
 743      *            the first {@code Property<T>}
 744      * @param property2
 745      *            the second {@code Property<T>}
 746      * @throws NullPointerException
 747      *            if one of the properties is {@code null}
 748      * @throws IllegalArgumentException
 749      *            if both properties are equal
 750      */
 751     public static <T> void bindBidirectional(Property<T> property1, Property<T> property2) {
 752         BidirectionalBinding.bind(property1, property2);
 753     }
 754 
 755     /**
 756      * Delete a bidirectional binding that was previously defined with
 757      * {@link #bindBidirectional(Property, Property)}.
 758      *
 759      * @param <T>
 760      *            the types of the properties
 761      * @param property1
 762      *            the first {@code Property<T>}
 763      * @param property2
 764      *            the second {@code Property<T>}
 765      * @throws NullPointerException
 766      *            if one of the properties is {@code null}
 767      * @throws IllegalArgumentException
 768      *            if both properties are equal
 769      */
 770     public static <T> void unbindBidirectional(Property<T> property1, Property<T> property2) {
 771         BidirectionalBinding.unbind(property1, property2);
 772     }
 773 
 774     /**
 775      * Delete a bidirectional binding that was previously defined with
 776      * {@link #bindBidirectional(Property, Property)} or
 777      * {@link #bindBidirectional(javafx.beans.property.Property, javafx.beans.property.Property, java.text.Format)}.
 778      *
 779      * @param property1
 780      *            the first {@code Property<T>}
 781      * @param property2
 782      *            the second {@code Property<T>}
 783      * @throws NullPointerException
 784      *            if one of the properties is {@code null}
 785      * @throws IllegalArgumentException
 786      *            if both properties are equal
 787      * @since JavaFX 2.1
 788      */
 789     public static void unbindBidirectional(Object property1, Object property2) {
 790         BidirectionalBinding.unbind(property1, property2);
 791     }
 792 
 793     /**
 794      * Generates a bidirectional binding (or "bind with inverse") between a
 795      * {@code String}-{@link javafx.beans.property.Property} and another {@code Property}
 796      * using the specified {@code Format} for conversion.
 797      * <p>
 798      * A bidirectional binding is a binding that works in both directions. If
 799      * two properties {@code a} and {@code b} are linked with a bidirectional
 800      * binding and the value of {@code a} changes, {@code b} is set to the same
 801      * value automatically. And vice versa, if {@code b} changes, {@code a} is
 802      * set to the same value.
 803      * <p>
 804      * A bidirectional binding can be removed with
 805      * {@link #unbindBidirectional(Object, Object)}.
 806      * <p>
 807      * Note: this implementation of a bidirectional binding behaves differently
 808      * from all other bindings here in two important aspects. A property that is
 809      * linked to another property with a bidirectional binding can still be set
 810      * (usually bindings would throw an exception). Secondly bidirectional
 811      * bindings are calculated eagerly, i.e. a bound property is updated
 812      * immediately.
 813      *
 814      * @param stringProperty
 815      *            the {@code String} {@code Property}
 816      * @param otherProperty
 817      *            the other (non-{@code String}) {@code Property}
 818      * @param format
 819      *            the {@code Format} used to convert between the properties
 820      * @throws NullPointerException
 821      *            if one of the properties or the {@code format} is {@code null}
 822      * @throws IllegalArgumentException
 823      *            if both properties are equal
 824      * @since JavaFX 2.1
 825      */
 826     public  static void bindBidirectional(Property<String> stringProperty, Property<?> otherProperty, Format format) {
 827         BidirectionalBinding.bind(stringProperty, otherProperty, format);
 828     }
 829 
 830     /**
 831      * Generates a bidirectional binding (or "bind with inverse") between a
 832      * {@code String}-{@link javafx.beans.property.Property} and another {@code Property}
 833      * using the specified {@link javafx.util.StringConverter} for conversion.
 834      * <p>
 835      * A bidirectional binding is a binding that works in both directions. If
 836      * two properties {@code a} and {@code b} are linked with a bidirectional
 837      * binding and the value of {@code a} changes, {@code b} is set to the same
 838      * value automatically. And vice versa, if {@code b} changes, {@code a} is
 839      * set to the same value.
 840      * <p>
 841      * A bidirectional binding can be removed with
 842      * {@link #unbindBidirectional(Object, Object)}.
 843      * <p>
 844      * Note: this implementation of a bidirectional binding behaves differently
 845      * from all other bindings here in two important aspects. A property that is
 846      * linked to another property with a bidirectional binding can still be set
 847      * (usually bindings would throw an exception). Secondly bidirectional
 848      * bindings are calculated eagerly, i.e. a bound property is updated
 849      * immediately.
 850      *
 851      * @param <T> the type of the wrapped {@code Object}
 852      * @param stringProperty
 853      *            the {@code String} {@code Property}
 854      * @param otherProperty
 855      *            the other (non-{@code String}) {@code Property}
 856      * @param converter
 857      *            the {@code StringConverter} used to convert between the properties
 858      * @throws NullPointerException
 859      *            if one of the properties or the {@code converter} is {@code null}
 860      * @throws IllegalArgumentException
 861      *            if both properties are equal
 862      * @since JavaFX 2.1
 863      */
 864     public static <T> void bindBidirectional(Property<String> stringProperty, Property<T> otherProperty, StringConverter<T> converter) {
 865         BidirectionalBinding.bind(stringProperty, otherProperty, converter);
 866     }
 867 
 868     /**
 869      * Generates a bidirectional binding (or "bind with inverse") between two
 870      * instances of {@link javafx.collections.ObservableList}.
 871      * <p>
 872      * A bidirectional binding is a binding that works in both directions. If
 873      * two properties {@code a} and {@code b} are linked with a bidirectional
 874      * binding and the value of {@code a} changes, {@code b} is set to the same
 875      * value automatically. And vice versa, if {@code b} changes, {@code a} is
 876      * set to the same value.
 877      * <p>
 878      * Only the content of the two lists is synchronized, which means that
 879      * both lists are different, but they contain the same elements.
 880      * <p>
 881      * A bidirectional content-binding can be removed with
 882      * {@link #unbindContentBidirectional(Object, Object)}.
 883      * <p>
 884      * Note: this implementation of a bidirectional binding behaves differently
 885      * from all other bindings here in two important aspects. A property that is
 886      * linked to another property with a bidirectional binding can still be set
 887      * (usually bindings would throw an exception). Secondly bidirectional
 888      * bindings are calculated eagerly, i.e. a bound property is updated
 889      * immediately.
 890      *
 891      * @param <E>
 892      *            the type of the list elements
 893      * @param list1
 894      *            the first {@code ObservableList<E>}
 895      * @param list2
 896      *            the second {@code ObservableList<E>}
 897      * @throws NullPointerException
 898      *            if one of the lists is {@code null}
 899      * @throws IllegalArgumentException
 900      *            if {@code list1} == {@code list2}
 901      * @since JavaFX 2.1
 902      */
 903     public static <E> void bindContentBidirectional(ObservableList<E> list1, ObservableList<E> list2) {
 904         BidirectionalContentBinding.bind(list1, list2);
 905     }
 906 
 907     /**
 908      * Generates a bidirectional binding (or "bind with inverse") between two
 909      * instances of {@link javafx.collections.ObservableSet}.
 910      * <p>
 911      * A bidirectional binding is a binding that works in both directions. If
 912      * two properties {@code a} and {@code b} are linked with a bidirectional
 913      * binding and the value of {@code a} changes, {@code b} is set to the same
 914      * value automatically. And vice versa, if {@code b} changes, {@code a} is
 915      * set to the same value.
 916      * <p>
 917      * Only the content of the two sets is synchronized, which means that
 918      * both sets are different, but they contain the same elements.
 919      * <p>
 920      * A bidirectional content-binding can be removed with
 921      * {@link #unbindContentBidirectional(Object, Object)}.
 922      * <p>
 923      * Note: this implementation of a bidirectional binding behaves differently
 924      * from all other bindings here in two important aspects. A property that is
 925      * linked to another property with a bidirectional binding can still be set
 926      * (usually bindings would throw an exception). Secondly bidirectional
 927      * bindings are calculated eagerly, i.e. a bound property is updated
 928      * immediately.
 929      *
 930      * @param <E>
 931      *            the type of the set elements
 932      * @param set1
 933      *            the first {@code ObservableSet<E>}
 934      * @param set2
 935      *            the second {@code ObservableSet<E>}
 936      * @throws NullPointerException
 937      *            if one of the sets is {@code null}
 938      * @throws IllegalArgumentException
 939      *            if {@code set1} == {@code set2}
 940      * @since JavaFX 2.1
 941      */
 942     public static <E> void bindContentBidirectional(ObservableSet<E> set1, ObservableSet<E> set2) {
 943         BidirectionalContentBinding.bind(set1, set2);
 944     }
 945 
 946     /**
 947      * Generates a bidirectional binding (or "bind with inverse") between two
 948      * instances of {@link javafx.collections.ObservableMap}.
 949      * <p>
 950      * A bidirectional binding is a binding that works in both directions. If
 951      * two properties {@code a} and {@code b} are linked with a bidirectional
 952      * binding and the value of {@code a} changes, {@code b} is set to the same
 953      * value automatically. And vice versa, if {@code b} changes, {@code a} is
 954      * set to the same value.
 955      * <p>
 956      * Only the content of the two maps is synchronized, which means that
 957      * both maps are different, but they contain the same elements.
 958      * <p>
 959      * A bidirectional content-binding can be removed with
 960      * {@link #unbindContentBidirectional(Object, Object)}.
 961      * <p>
 962      * Note: this implementation of a bidirectional binding behaves differently
 963      * from all other bindings here in two important aspects. A property that is
 964      * linked to another property with a bidirectional binding can still be set
 965      * (usually bindings would throw an exception). Secondly bidirectional
 966      * bindings are calculated eagerly, i.e. a bound property is updated
 967      * immediately.
 968      *
 969      * @param <K>
 970      *            the type of the key elements
 971      * @param <V>
 972      *            the type of the value elements
 973      * @param map1
 974      *            the first {@code ObservableMap<K, V>}
 975      * @param map2
 976      *            the second {@code ObservableMap<K, V>}
 977      * @since JavaFX 2.1
 978      */
 979     public static <K, V> void bindContentBidirectional(ObservableMap<K, V> map1, ObservableMap<K, V> map2) {
 980         BidirectionalContentBinding.bind(map1, map2);
 981     }
 982 
 983     /**
 984      * Remove a bidirectional content binding.
 985      *
 986      * @param obj1
 987      *            the first {@code Object}
 988      * @param obj2
 989      *            the second {@code Object}
 990      * @since JavaFX 2.1
 991      */
 992     public static void unbindContentBidirectional(Object obj1, Object obj2) {
 993         BidirectionalContentBinding.unbind(obj1, obj2);
 994     }
 995 
 996     /**
 997      * Generates a content binding between an {@link javafx.collections.ObservableList} and a {@link java.util.List}.
 998      * <p>
 999      * A content binding ensures that the {@code List} contains the same elements as the {@code ObservableList}.
1000      * If the content of the {@code ObservableList} changes, the {@code List} will be updated automatically.
1001      * <p>
1002      * Once a {@code List} is bound to an {@code ObservableList}, the {@code List} must not be changed directly
1003      * anymore. Doing so would lead to unexpected results.
1004      * <p>
1005      * A content-binding can be removed with {@link #unbindContent(Object, Object)}.
1006      *
1007      * @param <E>
1008      *            the type of the {@code List} elements
1009      * @param list1
1010      *            the {@code List}
1011      * @param list2
1012      *            the {@code ObservableList}
1013      * @since JavaFX 2.1
1014      */
1015     public static <E> void bindContent(List<E> list1, ObservableList<? extends E> list2) {
1016         ContentBinding.bind(list1, list2);
1017     }
1018 
1019     /**
1020      * Generates a content binding between an {@link javafx.collections.ObservableSet} and a {@link java.util.Set}.
1021      * <p>
1022      * A content binding ensures that the {@code Set} contains the same elements as the {@code ObservableSet}.
1023      * If the content of the {@code ObservableSet} changes, the {@code Set} will be updated automatically.
1024      * <p>
1025      * Once a {@code Set} is bound to an {@code ObservableSet}, the {@code Set} must not be changed directly
1026      * anymore. Doing so would lead to unexpected results.
1027      * <p>
1028      * A content-binding can be removed with {@link #unbindContent(Object, Object)}.
1029      *
1030      * @param <E>
1031      *            the type of the {@code Set} elements
1032      * @param set1
1033      *            the {@code Set}
1034      * @param set2
1035      *            the {@code ObservableSet}
1036      * @throws NullPointerException
1037      *            if one of the sets is {@code null}
1038      * @throws IllegalArgumentException
1039      *            if {@code set1} == {@code set2}
1040      * @since JavaFX 2.1
1041      */
1042     public static <E> void bindContent(Set<E> set1, ObservableSet<? extends E> set2) {
1043         ContentBinding.bind(set1, set2);
1044     }
1045 
1046     /**
1047      * Generates a content binding between an {@link javafx.collections.ObservableMap} and a {@link java.util.Map}.
1048      * <p>
1049      * A content binding ensures that the {@code Map} contains the same elements as the {@code ObservableMap}.
1050      * If the content of the {@code ObservableMap} changes, the {@code Map} will be updated automatically.
1051      * <p>
1052      * Once a {@code Map} is bound to an {@code ObservableMap}, the {@code Map} must not be changed directly
1053      * anymore. Doing so would lead to unexpected results.
1054      * <p>
1055      * A content-binding can be removed with {@link #unbindContent(Object, Object)}.
1056      *
1057      * @param <K>
1058      *            the type of the key elements of the {@code Map}
1059      * @param <V>
1060      *            the type of the value elements of the {@code Map}
1061      * @param map1
1062      *            the {@code Map}
1063      * @param map2
1064      *            the {@code ObservableMap}
1065      * @throws NullPointerException
1066      *            if one of the maps is {@code null}
1067      * @throws IllegalArgumentException
1068      *            if {@code map1} == {@code map2}
1069      * @since JavaFX 2.1
1070      */
1071     public static <K, V> void bindContent(Map<K, V> map1, ObservableMap<? extends K, ? extends V> map2) {
1072         ContentBinding.bind(map1, map2);
1073     }
1074 
1075     /**
1076      * Remove a content binding.
1077      *
1078      * @param obj1
1079      *            the first {@code Object}
1080      * @param obj2
1081      *            the second {@code Object}
1082      * @throws NullPointerException
1083      *            if one of the {@code Objects} is {@code null}
1084      * @throws IllegalArgumentException
1085      *            if {@code obj1} == {@code obj2}
1086      * @since JavaFX 2.1
1087      */
1088     public static void unbindContent(Object obj1, Object obj2) {
1089         ContentBinding.unbind(obj1, obj2);
1090     }
1091 
1092 
1093 
1094     // =================================================================================================================
1095     // Negation
1096 
1097     /**
1098      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1099      * the negation of a {@link javafx.beans.value.ObservableNumberValue}.
1100      *
1101      * @param value
1102      *            the operand
1103      * @return the new {@code NumberBinding}
1104      * @throws NullPointerException
1105      *             if the value is {@code null}
1106      */
1107     public static NumberBinding negate(final ObservableNumberValue value) {
1108         if (value == null) {
1109             throw new NullPointerException("Operand cannot be null.");
1110         }
1111 
1112         if (value instanceof ObservableDoubleValue) {
1113             return new DoubleBinding() {
1114                 {
1115                     super.bind(value);
1116                 }
1117 
1118                 @Override
1119                 public void dispose() {
1120                     super.unbind(value);
1121                 }
1122 
1123                 @Override
1124                 protected double computeValue() {
1125                     return -value.doubleValue();
1126                 }
1127 
1128                 @Override
1129                 public ObservableList<?> getDependencies() {
1130                     return FXCollections.singletonObservableList(value);
1131                 }
1132             };
1133         } else if (value instanceof ObservableFloatValue) {
1134             return new FloatBinding() {
1135                 {
1136                     super.bind(value);
1137                 }
1138 
1139                 @Override
1140                 public void dispose() {
1141                     super.unbind(value);
1142                 }
1143 
1144                 @Override
1145                 protected float computeValue() {
1146                     return -value.floatValue();
1147                 }
1148 
1149                 @Override
1150                 public ObservableList<?> getDependencies() {
1151                     return FXCollections.singletonObservableList(value);
1152                 }
1153             };
1154         } else if (value instanceof ObservableLongValue) {
1155             return new LongBinding() {
1156                 {
1157                     super.bind(value);
1158                 }
1159 
1160                 @Override
1161                 public void dispose() {
1162                     super.unbind(value);
1163                 }
1164 
1165                 @Override
1166                 protected long computeValue() {
1167                     return -value.longValue();
1168                 }
1169 
1170                 @Override
1171                 public ObservableList<?> getDependencies() {
1172                     return FXCollections.singletonObservableList(value);
1173                 }
1174             };
1175         } else {
1176             return new IntegerBinding() {
1177                 {
1178                     super.bind(value);
1179                 }
1180 
1181                 @Override
1182                 public void dispose() {
1183                     super.unbind(value);
1184                 }
1185 
1186                 @Override
1187                 protected int computeValue() {
1188                     return -value.intValue();
1189                 }
1190 
1191                 @Override
1192                 public ObservableList<?> getDependencies() {
1193                     return FXCollections.singletonObservableList(value);
1194                 }
1195             };
1196         }
1197     }
1198 
1199     // =================================================================================================================
1200     // Sum
1201 
1202     private static NumberBinding add(final ObservableNumberValue op1, final ObservableNumberValue op2, final Observable... dependencies) {
1203         if ((op1 == null) || (op2 == null)) {
1204             throw new NullPointerException("Operands cannot be null.");
1205         }
1206         assert (dependencies != null) && (dependencies.length > 0);
1207 
1208         if ((op1 instanceof ObservableDoubleValue) || (op2 instanceof ObservableDoubleValue)) {
1209             return new DoubleBinding() {
1210                 {
1211                     super.bind(dependencies);
1212                 }
1213 
1214                 @Override
1215                 public void dispose() {
1216                     super.unbind(dependencies);
1217                 }
1218 
1219                 @Override
1220                 protected double computeValue() {
1221                     return op1.doubleValue() + op2.doubleValue();
1222                 }
1223 
1224                 @Override
1225                 public ObservableList<?> getDependencies() {
1226                     return (dependencies.length == 1)?
1227                             FXCollections.singletonObservableList(dependencies[0])
1228                             : new ImmutableObservableList<Observable>(dependencies);
1229                 }
1230             };
1231         } else if ((op1 instanceof ObservableFloatValue) || (op2 instanceof ObservableFloatValue)) {
1232             return new FloatBinding() {
1233                 {
1234                     super.bind(dependencies);
1235                 }
1236 
1237                 @Override
1238                 public void dispose() {
1239                     super.unbind(dependencies);
1240                 }
1241 
1242                 @Override
1243                 protected float computeValue() {
1244                     return op1.floatValue() + op2.floatValue();
1245                 }
1246 
1247                 @Override
1248                 public ObservableList<?> getDependencies() {
1249                     return (dependencies.length == 1)?
1250                             FXCollections.singletonObservableList(dependencies[0])
1251                             : new ImmutableObservableList<Observable>(dependencies);
1252                 }
1253             };
1254         } else if ((op1 instanceof ObservableLongValue) || (op2 instanceof ObservableLongValue)) {
1255             return new LongBinding() {
1256                 {
1257                     super.bind(dependencies);
1258                 }
1259 
1260                 @Override
1261                 public void dispose() {
1262                     super.unbind(dependencies);
1263                 }
1264 
1265                 @Override
1266                 protected long computeValue() {
1267                     return op1.longValue() + op2.longValue();
1268                 }
1269 
1270                 @Override
1271                 public ObservableList<?> getDependencies() {
1272                     return (dependencies.length == 1)?
1273                             FXCollections.singletonObservableList(dependencies[0])
1274                             : new ImmutableObservableList<Observable>(dependencies);
1275                 }
1276             };
1277         } else {
1278             return new IntegerBinding() {
1279                 {
1280                     super.bind(dependencies);
1281                 }
1282 
1283                 @Override
1284                 public void dispose() {
1285                     super.unbind(dependencies);
1286                 }
1287 
1288                 @Override
1289                 protected int computeValue() {
1290                     return op1.intValue() + op2.intValue();
1291                 }
1292 
1293                 @Override
1294                 public ObservableList<?> getDependencies() {
1295                     return (dependencies.length == 1)?
1296                             FXCollections.singletonObservableList(dependencies[0])
1297                             : new ImmutableObservableList<Observable>(dependencies);
1298                 }
1299             };
1300         }
1301     }
1302 
1303     /**
1304      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1305      * the sum of the values of two instances of
1306      * {@link javafx.beans.value.ObservableNumberValue}.
1307      *
1308      * @param op1
1309      *            the first operand
1310      * @param op2
1311      *            the second operand
1312      * @return the new {@code NumberBinding}
1313      * @throws NullPointerException
1314      *             if one of the operands is {@code null}
1315      */
1316     public static NumberBinding add(final ObservableNumberValue op1, final ObservableNumberValue op2) {
1317         return Bindings.add(op1, op2, op1, op2);
1318     }
1319 
1320     /**
1321      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
1322      * the sum of the value of a
1323      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1324      *
1325      * @param op1
1326      *            the {@code ObservableNumberValue}
1327      * @param op2
1328      *            the constant value
1329      * @return the new {@code DoubleBinding}
1330      * @throws NullPointerException
1331      *             if the {@code ObservableNumberValue} is {@code null}
1332      */
1333     public static DoubleBinding add(final ObservableNumberValue op1, double op2) {
1334         return (DoubleBinding) Bindings.add(op1, DoubleConstant.valueOf(op2), op1);
1335     }
1336 
1337     /**
1338      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
1339      * the sum of the value of a
1340      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1341      *
1342      * @param op1
1343      *            the constant value
1344      * @param op2
1345      *            the {@code ObservableNumberValue}
1346      * @return the new {@code DoubleBinding}
1347      * @throws NullPointerException
1348      *             if the {@code ObservableNumberValue} is {@code null}
1349      */
1350     public static DoubleBinding add(double op1, final ObservableNumberValue op2) {
1351         return (DoubleBinding) Bindings.add(DoubleConstant.valueOf(op1), op2, op2);
1352     }
1353 
1354     /**
1355      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1356      * the sum of the value of a
1357      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1358      *
1359      * @param op1
1360      *            the {@code ObservableNumberValue}
1361      * @param op2
1362      *            the constant value
1363      * @return the new {@code NumberBinding}
1364      * @throws NullPointerException
1365      *             if the {@code ObservableNumberValue} is {@code null}
1366      */
1367     public static NumberBinding add(final ObservableNumberValue op1, float op2) {
1368         return Bindings.add(op1, FloatConstant.valueOf(op2), op1);
1369     }
1370 
1371     /**
1372      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1373      * the sum of the value of a
1374      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1375      *
1376      * @param op1
1377      *            the constant value
1378      * @param op2
1379      *            the {@code ObservableNumberValue}
1380      * @return the new {@code NumberBinding}
1381      * @throws NullPointerException
1382      *             if the {@code ObservableNumberValue} is {@code null}
1383      */
1384     public static NumberBinding add(float op1, final ObservableNumberValue op2) {
1385         return Bindings.add(FloatConstant.valueOf(op1), op2, op2);
1386     }
1387 
1388     /**
1389      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1390      * the sum of the value of a
1391      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1392      *
1393      * @param op1
1394      *            the {@code ObservableNumberValue}
1395      * @param op2
1396      *            the constant value
1397      * @return the new {@code NumberBinding}
1398      * @throws NullPointerException
1399      *             if the {@code ObservableNumberValue} is {@code null}
1400      */
1401     public static NumberBinding add(final ObservableNumberValue op1, long op2) {
1402         return Bindings.add(op1, LongConstant.valueOf(op2), op1);
1403     }
1404 
1405     /**
1406      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1407      * the sum of the value of a
1408      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1409      *
1410      * @param op1
1411      *            the constant value
1412      * @param op2
1413      *            the {@code ObservableNumberValue}
1414      * @return the new {@code NumberBinding}
1415      * @throws NullPointerException
1416      *             if the {@code ObservableNumberValue} is {@code null}
1417      */
1418     public static NumberBinding add(long op1, final ObservableNumberValue op2) {
1419         return Bindings.add(LongConstant.valueOf(op1), op2, op2);
1420     }
1421 
1422     /**
1423      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1424      * the sum of the value of a
1425      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1426      *
1427      * @param op1
1428      *            the {@code ObservableNumberValue}
1429      * @param op2
1430      *            the constant value
1431      * @return the new {@code NumberBinding}
1432      * @throws NullPointerException
1433      *             if the {@code ObservableNumberValue} is {@code null}
1434      */
1435     public static NumberBinding add(final ObservableNumberValue op1, int op2) {
1436         return Bindings.add(op1, IntegerConstant.valueOf(op2), op1);
1437     }
1438 
1439     /**
1440      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1441      * the sum of the value of a
1442      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1443      *
1444      * @param op1
1445      *            the constant value
1446      * @param op2
1447      *            the {@code ObservableNumberValue}
1448      * @return the new {@code NumberBinding}
1449      * @throws NullPointerException
1450      *             if the {@code ObservableNumberValue} is {@code null}
1451      */
1452     public static NumberBinding add(int op1, final ObservableNumberValue op2) {
1453         return Bindings.add(IntegerConstant.valueOf(op1), op2, op2);
1454     }
1455 
1456     // =================================================================================================================
1457     // Diff
1458 
1459     private static NumberBinding subtract(final ObservableNumberValue op1, final ObservableNumberValue op2, final Observable... dependencies) {
1460         if ((op1 == null) || (op2 == null)) {
1461             throw new NullPointerException("Operands cannot be null.");
1462         }
1463         assert (dependencies != null) && (dependencies.length > 0);
1464 
1465         if ((op1 instanceof ObservableDoubleValue) || (op2 instanceof ObservableDoubleValue)) {
1466             return new DoubleBinding() {
1467                 {
1468                     super.bind(dependencies);
1469                 }
1470 
1471                 @Override
1472                 public void dispose() {
1473                     super.unbind(dependencies);
1474                 }
1475 
1476                 @Override
1477                 protected double computeValue() {
1478                     return op1.doubleValue() - op2.doubleValue();
1479                 }
1480 
1481                 @Override
1482                 public ObservableList<?> getDependencies() {
1483                     return (dependencies.length == 1)?
1484                             FXCollections.singletonObservableList(dependencies[0])
1485                             : new ImmutableObservableList<Observable>(dependencies);
1486                 }
1487             };
1488         } else if ((op1 instanceof ObservableFloatValue) || (op2 instanceof ObservableFloatValue)) {
1489             return new FloatBinding() {
1490                 {
1491                     super.bind(dependencies);
1492                 }
1493 
1494                 @Override
1495                 public void dispose() {
1496                     super.unbind(dependencies);
1497                 }
1498 
1499                 @Override
1500                 protected float computeValue() {
1501                     return op1.floatValue() - op2.floatValue();
1502                 }
1503 
1504                 @Override
1505                 public ObservableList<?> getDependencies() {
1506                     return (dependencies.length == 1)?
1507                             FXCollections.singletonObservableList(dependencies[0])
1508                             : new ImmutableObservableList<Observable>(dependencies);
1509                 }
1510             };
1511         } else if ((op1 instanceof ObservableLongValue) || (op2 instanceof ObservableLongValue)) {
1512             return new LongBinding() {
1513                 {
1514                     super.bind(dependencies);
1515                 }
1516 
1517                 @Override
1518                 public void dispose() {
1519                     super.unbind(dependencies);
1520                 }
1521 
1522                 @Override
1523                 protected long computeValue() {
1524                     return op1.longValue() - op2.longValue();
1525                 }
1526 
1527                 @Override
1528                 public ObservableList<?> getDependencies() {
1529                     return (dependencies.length == 1)?
1530                             FXCollections.singletonObservableList(dependencies[0])
1531                             : new ImmutableObservableList<Observable>(dependencies);
1532                 }
1533             };
1534         } else {
1535             return new IntegerBinding() {
1536                 {
1537                     super.bind(dependencies);
1538                 }
1539 
1540                 @Override
1541                 public void dispose() {
1542                     super.unbind(dependencies);
1543                 }
1544 
1545                 @Override
1546                 protected int computeValue() {
1547                     return op1.intValue() - op2.intValue();
1548                 }
1549 
1550                 @Override
1551                 public ObservableList<?> getDependencies() {
1552                     return (dependencies.length == 1)?
1553                             FXCollections.singletonObservableList(dependencies[0])
1554                             : new ImmutableObservableList<Observable>(dependencies);
1555                 }
1556             };
1557         }
1558     }
1559 
1560     /**
1561      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1562      * the difference of the values of two instances of
1563      * {@link javafx.beans.value.ObservableNumberValue}.
1564      *
1565      * @param op1
1566      *            the first operand
1567      * @param op2
1568      *            the second operand
1569      * @return the new {@code NumberBinding}
1570      * @throws NullPointerException
1571      *             if one of the operands is {@code null}
1572      */
1573     public static NumberBinding subtract(final ObservableNumberValue op1, final ObservableNumberValue op2) {
1574         return Bindings.subtract(op1, op2, op1, op2);
1575     }
1576 
1577     /**
1578      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
1579      * the difference of the value of a
1580      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1581      *
1582      * @param op1
1583      *            the {@code ObservableNumberValue}
1584      * @param op2
1585      *            the constant value
1586      * @return the new {@code DoubleBinding}
1587      * @throws NullPointerException
1588      *             if the {@code ObservableNumberValue} is {@code null}
1589      */
1590     public static DoubleBinding subtract(final ObservableNumberValue op1, double op2) {
1591         return (DoubleBinding) Bindings.subtract(op1, DoubleConstant.valueOf(op2), op1);
1592     }
1593 
1594     /**
1595      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
1596      * the difference of a constant value and the value of a
1597      * {@link javafx.beans.value.ObservableNumberValue}.
1598      *
1599      * @param op1
1600      *            the constant value
1601      * @param op2
1602      *            the {@code ObservableNumberValue}
1603      * @return the new {@code DoubleBinding}
1604      * @throws NullPointerException
1605      *             if the {@code ObservableNumberValue} is {@code null}
1606      */
1607     public static DoubleBinding subtract(double op1, final ObservableNumberValue op2) {
1608         return (DoubleBinding) Bindings.subtract(DoubleConstant.valueOf(op1), op2, op2);
1609     }
1610 
1611     /**
1612      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1613      * the difference of the value of a
1614      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1615      *
1616      * @param op1
1617      *            the constant value
1618      * @param op2
1619      *            the {@code ObservableNumberValue}
1620      * @return the new {@code NumberBinding}
1621      * @throws NullPointerException
1622      *             if the {@code ObservableNumberValue} is {@code null}
1623      */
1624     public static NumberBinding subtract(final ObservableNumberValue op1, float op2) {
1625         return Bindings.subtract(op1, FloatConstant.valueOf(op2), op1);
1626     }
1627 
1628     /**
1629      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1630      * the difference of a constant value and the value of a
1631      * {@link javafx.beans.value.ObservableNumberValue}.
1632      *
1633      * @param op1
1634      *            the {@code ObservableNumberValue}
1635      * @param op2
1636      *            the constant value
1637      * @return the new {@code NumberBinding}
1638      * @throws NullPointerException
1639      *             if the {@code ObservableNumberValue} is {@code null}
1640      */
1641     public static NumberBinding subtract(float op1, final ObservableNumberValue op2) {
1642         return Bindings.subtract(FloatConstant.valueOf(op1), op2, op2);
1643     }
1644 
1645     /**
1646      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1647      * the difference of the value of a
1648      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1649      *
1650      * @param op1
1651      *            the constant value
1652      * @param op2
1653      *            the {@code ObservableNumberValue}
1654      * @return the new {@code NumberBinding}
1655      * @throws NullPointerException
1656      *             if the {@code ObservableNumberValue} is {@code null}
1657      */
1658     public static NumberBinding subtract(final ObservableNumberValue op1, long op2) {
1659         return Bindings.subtract(op1, LongConstant.valueOf(op2), op1);
1660     }
1661 
1662     /**
1663      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1664      * the difference of a constant value and the value of a
1665      * {@link javafx.beans.value.ObservableNumberValue}.
1666      *
1667      * @param op1
1668      *            the {@code ObservableNumberValue}
1669      * @param op2
1670      *            the constant value
1671      * @return the new {@code NumberBinding}
1672      * @throws NullPointerException
1673      *             if the {@code ObservableNumberValue} is {@code null}
1674      */
1675     public static NumberBinding subtract(long op1, final ObservableNumberValue op2) {
1676         return Bindings.subtract(LongConstant.valueOf(op1), op2, op2);
1677     }
1678 
1679     /**
1680      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1681      * the difference of the value of a
1682      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1683      *
1684      * @param op1
1685      *            the constant value
1686      * @param op2
1687      *            the {@code ObservableNumberValue}
1688      * @return the new {@code NumberBinding}
1689      * @throws NullPointerException
1690      *             if the {@code ObservableNumberValue} is {@code null}
1691      */
1692     public static NumberBinding subtract(final ObservableNumberValue op1, int op2) {
1693         return Bindings.subtract(op1, IntegerConstant.valueOf(op2), op1);
1694     }
1695 
1696     /**
1697      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1698      * the difference of a constant value and the value of a
1699      * {@link javafx.beans.value.ObservableNumberValue}.
1700      *
1701      * @param op1
1702      *            the {@code ObservableNumberValue}
1703      * @param op2
1704      *            the constant value
1705      * @return the new {@code NumberBinding}
1706      * @throws NullPointerException
1707      *             if the {@code ObservableNumberValue} is {@code null}
1708      */
1709     public static NumberBinding subtract(int op1, final ObservableNumberValue op2) {
1710         return Bindings.subtract(IntegerConstant.valueOf(op1), op2, op2);
1711     }
1712 
1713     // =================================================================================================================
1714     // Multiply
1715 
1716     private static NumberBinding multiply(final ObservableNumberValue op1, final ObservableNumberValue op2, final Observable... dependencies) {
1717         if ((op1 == null) || (op2 == null)) {
1718             throw new NullPointerException("Operands cannot be null.");
1719         }
1720         assert (dependencies != null) && (dependencies.length > 0);
1721 
1722         if ((op1 instanceof ObservableDoubleValue) || (op2 instanceof ObservableDoubleValue)) {
1723             return new DoubleBinding() {
1724                 {
1725                     super.bind(dependencies);
1726                 }
1727 
1728                 @Override
1729                 public void dispose() {
1730                     super.unbind(dependencies);
1731                 }
1732 
1733                 @Override
1734                 protected double computeValue() {
1735                     return op1.doubleValue() * op2.doubleValue();
1736                 }
1737 
1738                 @Override
1739                 public ObservableList<?> getDependencies() {
1740                     return (dependencies.length == 1)?
1741                             FXCollections.singletonObservableList(dependencies[0])
1742                             : new ImmutableObservableList<Observable>(dependencies);
1743                 }
1744             };
1745         } else if ((op1 instanceof ObservableFloatValue) || (op2 instanceof ObservableFloatValue)) {
1746             return new FloatBinding() {
1747                 {
1748                     super.bind(dependencies);
1749                 }
1750 
1751                 @Override
1752                 public void dispose() {
1753                     super.unbind(dependencies);
1754                 }
1755 
1756                 @Override
1757                 protected float computeValue() {
1758                     return op1.floatValue() * op2.floatValue();
1759                 }
1760 
1761                 @Override
1762                 public ObservableList<?> getDependencies() {
1763                     return (dependencies.length == 1)?
1764                             FXCollections.singletonObservableList(dependencies[0])
1765                             : new ImmutableObservableList<Observable>(dependencies);
1766                 }
1767             };
1768         } else if ((op1 instanceof ObservableLongValue) || (op2 instanceof ObservableLongValue)) {
1769             return new LongBinding() {
1770                 {
1771                     super.bind(dependencies);
1772                 }
1773 
1774                 @Override
1775                 public void dispose() {
1776                     super.unbind(dependencies);
1777                 }
1778 
1779                 @Override
1780                 protected long computeValue() {
1781                     return op1.longValue() * op2.longValue();
1782                 }
1783 
1784                 @Override
1785                 public ObservableList<?> getDependencies() {
1786                     return (dependencies.length == 1)?
1787                             FXCollections.singletonObservableList(dependencies[0])
1788                             : new ImmutableObservableList<Observable>(dependencies);
1789                 }
1790             };
1791         } else {
1792             return new IntegerBinding() {
1793                 {
1794                     super.bind(dependencies);
1795                 }
1796 
1797                 @Override
1798                 public void dispose() {
1799                     super.unbind(dependencies);
1800                 }
1801 
1802                 @Override
1803                 protected int computeValue() {
1804                     return op1.intValue() * op2.intValue();
1805                 }
1806 
1807                 @Override
1808                 public ObservableList<?> getDependencies() {
1809                     return (dependencies.length == 1)?
1810                             FXCollections.singletonObservableList(dependencies[0])
1811                             : new ImmutableObservableList<Observable>(dependencies);
1812                 }
1813             };
1814         }
1815     }
1816 
1817     /**
1818      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1819      * the product of the values of two instances of
1820      * {@link javafx.beans.value.ObservableNumberValue}.
1821      *
1822      * @param op1
1823      *            the first operand
1824      * @param op2
1825      *            the second operand
1826      * @return the new {@code NumberBinding}
1827      * @throws NullPointerException
1828      *             if one of the operands is {@code null}
1829      */
1830     public static NumberBinding multiply(final ObservableNumberValue op1, final ObservableNumberValue op2) {
1831         return Bindings.multiply(op1, op2, op1, op2);
1832     }
1833 
1834     /**
1835      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
1836      * the product of the value of a
1837      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1838      *
1839      * @param op1
1840      *            the {@code ObservableNumberValue}
1841      * @param op2
1842      *            the constant value
1843      * @return the new {@code DoubleBinding}
1844      * @throws NullPointerException
1845      *             if the {@code ObservableNumberValue} is {@code null}
1846      */
1847     public static DoubleBinding multiply(final ObservableNumberValue op1, double op2) {
1848         return (DoubleBinding) Bindings.multiply(op1, DoubleConstant.valueOf(op2), op1);
1849     }
1850 
1851     /**
1852      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
1853      * the product of the value of a
1854      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1855      *
1856      * @param op1
1857      *            the constant value
1858      * @param op2
1859      *            the {@code ObservableNumberValue}
1860      * @return the new {@code DoubleBinding}
1861      * @throws NullPointerException
1862      *             if the {@code ObservableNumberValue} is {@code null}
1863      */
1864     public static DoubleBinding multiply(double op1, final ObservableNumberValue op2) {
1865         return (DoubleBinding) Bindings.multiply(DoubleConstant.valueOf(op1), op2, op2);
1866     }
1867 
1868     /**
1869      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1870      * the product of the value of a
1871      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1872      *
1873      * @param op1
1874      *            the constant value
1875      * @param op2
1876      *            the {@code ObservableNumberValue}
1877      * @return the new {@code NumberBinding}
1878      * @throws NullPointerException
1879      *             if the {@code ObservableNumberValue} is {@code null}
1880      */
1881     public static NumberBinding multiply(final ObservableNumberValue op1, float op2) {
1882         return Bindings.multiply(op1, FloatConstant.valueOf(op2), op1);
1883     }
1884 
1885     /**
1886      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1887      * the product of the value of a
1888      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1889      *
1890      * @param op1
1891      *            the constant value
1892      * @param op2
1893      *            the {@code ObservableNumberValue}
1894      * @return the new {@code NumberBinding}
1895      * @throws NullPointerException
1896      *             if the {@code ObservableNumberValue} is {@code null}
1897      */
1898     public static NumberBinding multiply(float op1, final ObservableNumberValue op2) {
1899         return Bindings.multiply(FloatConstant.valueOf(op1), op2, op2);
1900     }
1901 
1902     /**
1903      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1904      * the product of the value of a
1905      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1906      *
1907      * @param op1
1908      *            the constant value
1909      * @param op2
1910      *            the {@code ObservableNumberValue}
1911      * @return the new {@code NumberBinding}
1912      * @throws NullPointerException
1913      *             if the {@code ObservableNumberValue} is {@code null}
1914      */
1915     public static NumberBinding multiply(final ObservableNumberValue op1, long op2) {
1916         return Bindings.multiply(op1, LongConstant.valueOf(op2), op1);
1917     }
1918 
1919     /**
1920      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1921      * the product of the value of a
1922      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1923      *
1924      * @param op1
1925      *            the constant value
1926      * @param op2
1927      *            the {@code ObservableNumberValue}
1928      * @return the new {@code NumberBinding}
1929      * @throws NullPointerException
1930      *             if the {@code ObservableNumberValue} is {@code null}
1931      */
1932     public static NumberBinding multiply(long op1, final ObservableNumberValue op2) {
1933         return Bindings.multiply(LongConstant.valueOf(op1), op2, op2);
1934     }
1935 
1936     /**
1937      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1938      * the product of the value of a
1939      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1940      *
1941      * @param op1
1942      *            the constant value
1943      * @param op2
1944      *            the {@code ObservableNumberValue}
1945      * @return the new {@code NumberBinding}
1946      * @throws NullPointerException
1947      *             if the {@code ObservableNumberValue} is {@code null}
1948      */
1949     public static NumberBinding multiply(final ObservableNumberValue op1, int op2) {
1950         return Bindings.multiply(op1, IntegerConstant.valueOf(op2), op1);
1951     }
1952 
1953     /**
1954      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
1955      * the product of the value of a
1956      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
1957      *
1958      * @param op1
1959      *            the constant value
1960      * @param op2
1961      *            the {@code ObservableNumberValue}
1962      * @return the new {@code NumberBinding}
1963      * @throws NullPointerException
1964      *             if the {@code ObservableNumberValue} is {@code null}
1965      */
1966     public static NumberBinding multiply(int op1, final ObservableNumberValue op2) {
1967         return Bindings.multiply(IntegerConstant.valueOf(op1), op2, op2);
1968     }
1969 
1970     // =================================================================================================================
1971     // Divide
1972 
1973     private static NumberBinding divide(final ObservableNumberValue op1, final ObservableNumberValue op2, final Observable... dependencies) {
1974         if ((op1 == null) || (op2 == null)) {
1975             throw new NullPointerException("Operands cannot be null.");
1976         }
1977         assert (dependencies != null) && (dependencies.length > 0);
1978 
1979         if ((op1 instanceof ObservableDoubleValue) || (op2 instanceof ObservableDoubleValue)) {
1980             return new DoubleBinding() {
1981                 {
1982                     super.bind(dependencies);
1983                 }
1984 
1985                 @Override
1986                 public void dispose() {
1987                     super.unbind(dependencies);
1988                 }
1989 
1990                 @Override
1991                 protected double computeValue() {
1992                     return op1.doubleValue() / op2.doubleValue();
1993                 }
1994 
1995                 @Override
1996                 public ObservableList<?> getDependencies() {
1997                     return (dependencies.length == 1)?
1998                             FXCollections.singletonObservableList(dependencies[0])
1999                             : new ImmutableObservableList<Observable>(dependencies);
2000                 }
2001             };
2002         } else if ((op1 instanceof ObservableFloatValue) || (op2 instanceof ObservableFloatValue)) {
2003             return new FloatBinding() {
2004                 {
2005                     super.bind(dependencies);
2006                 }
2007 
2008                 @Override
2009                 public void dispose() {
2010                     super.unbind(dependencies);
2011                 }
2012 
2013                 @Override
2014                 protected float computeValue() {
2015                     return op1.floatValue() / op2.floatValue();
2016                 }
2017 
2018                 @Override
2019                 public ObservableList<?> getDependencies() {
2020                     return (dependencies.length == 1)?
2021                             FXCollections.singletonObservableList(dependencies[0])
2022                             : new ImmutableObservableList<Observable>(dependencies);
2023                 }
2024             };
2025         } else if ((op1 instanceof ObservableLongValue) || (op2 instanceof ObservableLongValue)) {
2026             return new LongBinding() {
2027                 {
2028                     super.bind(dependencies);
2029                 }
2030 
2031                 @Override
2032                 public void dispose() {
2033                     super.unbind(dependencies);
2034                 }
2035 
2036                 @Override
2037                 protected long computeValue() {
2038                     return op1.longValue() / op2.longValue();
2039                 }
2040 
2041                 @Override
2042                 public ObservableList<?> getDependencies() {
2043                     return (dependencies.length == 1)?
2044                             FXCollections.singletonObservableList(dependencies[0])
2045                             : new ImmutableObservableList<Observable>(dependencies);
2046                 }
2047             };
2048         } else {
2049             return new IntegerBinding() {
2050                 {
2051                     super.bind(dependencies);
2052                 }
2053 
2054                 @Override
2055                 public void dispose() {
2056                     super.unbind(dependencies);
2057                 }
2058 
2059                 @Override
2060                 protected int computeValue() {
2061                     return op1.intValue() / op2.intValue();
2062                 }
2063 
2064                 @Override
2065                 public ObservableList<?> getDependencies() {
2066                     return (dependencies.length == 1)?
2067                             FXCollections.singletonObservableList(dependencies[0])
2068                             : new ImmutableObservableList<Observable>(dependencies);
2069                 }
2070             };
2071         }
2072     }
2073 
2074     /**
2075      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
2076      * the division of the values of two instances of
2077      * {@link javafx.beans.value.ObservableNumberValue}.
2078      *
2079      * @param op1
2080      *            the first operand
2081      * @param op2
2082      *            the second operand
2083      * @return the new {@code NumberBinding}
2084      * @throws NullPointerException
2085      *             if one of the operands is {@code null}
2086      */
2087     public static NumberBinding divide(final ObservableNumberValue op1, final ObservableNumberValue op2) {
2088         return Bindings.divide(op1, op2, op1, op2);
2089     }
2090 
2091     /**
2092      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
2093      * the division of the value of a
2094      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
2095      *
2096      * @param op1
2097      *            the {@code ObservableNumberValue}
2098      * @param op2
2099      *            the constant value
2100      * @return the new {@code DoubleBinding}
2101      * @throws NullPointerException
2102      *             if the {@code ObservableNumberValue} is {@code null}
2103      */
2104     public static DoubleBinding divide(final ObservableNumberValue op1, double op2) {
2105         return (DoubleBinding) Bindings.divide(op1, DoubleConstant.valueOf(op2), op1);
2106     }
2107 
2108     /**
2109      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
2110      * the division of a constant value and the value of a
2111      * {@link javafx.beans.value.ObservableNumberValue}.
2112      *
2113      * @param op1
2114      *            the constant value
2115      * @param op2
2116      *            the {@code ObservableNumberValue}
2117      * @return the new {@code DoubleBinding}
2118      * @throws NullPointerException
2119      *             if the {@code ObservableNumberValue} is {@code null}
2120      */
2121     public static DoubleBinding divide(double op1, final ObservableNumberValue op2) {
2122         return (DoubleBinding) Bindings.divide(DoubleConstant.valueOf(op1), op2, op2);
2123     }
2124 
2125     /**
2126      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
2127      * the division of the value of a
2128      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
2129      *
2130      * @param op1
2131      *            the constant value
2132      * @param op2
2133      *            the {@code ObservableNumberValue}
2134      * @return the new {@code NumberBinding}
2135      * @throws NullPointerException
2136      *             if the {@code ObservableNumberValue} is {@code null}
2137      */
2138     public static NumberBinding divide(final ObservableNumberValue op1, float op2) {
2139         return Bindings.divide(op1, FloatConstant.valueOf(op2), op1);
2140     }
2141 
2142     /**
2143      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
2144      * the division of a constant value and the value of a
2145      * {@link javafx.beans.value.ObservableNumberValue}.
2146      *
2147      * @param op1
2148      *            the {@code ObservableNumberValue}
2149      * @param op2
2150      *            the constant value
2151      * @return the new {@code NumberBinding}
2152      * @throws NullPointerException
2153      *             if the {@code ObservableNumberValue} is {@code null}
2154      */
2155     public static NumberBinding divide(float op1, final ObservableNumberValue op2) {
2156         return Bindings.divide(FloatConstant.valueOf(op1), op2, op2);
2157     }
2158 
2159     /**
2160      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
2161      * the division of the value of a
2162      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
2163      *
2164      * @param op1
2165      *            the constant value
2166      * @param op2
2167      *            the {@code ObservableNumberValue}
2168      * @return the new {@code NumberBinding}
2169      * @throws NullPointerException
2170      *             if the {@code ObservableNumberValue} is {@code null}
2171      */
2172     public static NumberBinding divide(final ObservableNumberValue op1, long op2) {
2173         return Bindings.divide(op1, LongConstant.valueOf(op2), op1);
2174     }
2175 
2176     /**
2177      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
2178      * the division of a constant value and the value of a
2179      * {@link javafx.beans.value.ObservableNumberValue}.
2180      *
2181      * @param op1
2182      *            the {@code ObservableNumberValue}
2183      * @param op2
2184      *            the constant value
2185      * @return the new {@code NumberBinding}
2186      * @throws NullPointerException
2187      *             if the {@code ObservableNumberValue} is {@code null}
2188      */
2189     public static NumberBinding divide(long op1, final ObservableNumberValue op2) {
2190         return Bindings.divide(LongConstant.valueOf(op1), op2, op2);
2191     }
2192 
2193     /**
2194      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
2195      * the division of the value of a
2196      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
2197      *
2198      * @param op1
2199      *            the constant value
2200      * @param op2
2201      *            the {@code ObservableNumberValue}
2202      * @return the new {@code NumberBinding}
2203      * @throws NullPointerException
2204      *             if the {@code ObservableNumberValue} is {@code null}
2205      */
2206     public static NumberBinding divide(final ObservableNumberValue op1, int op2) {
2207         return Bindings.divide(op1, IntegerConstant.valueOf(op2), op1);
2208     }
2209 
2210     /**
2211      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
2212      * the division of a constant value and the value of a
2213      * {@link javafx.beans.value.ObservableNumberValue}.
2214      *
2215      * @param op1
2216      *            the {@code ObservableNumberValue}
2217      * @param op2
2218      *            the constant value
2219      * @return the new {@code NumberBinding}
2220      * @throws NullPointerException
2221      *             if the {@code ObservableNumberValue} is {@code null}
2222      */
2223     public static NumberBinding divide(int op1, final ObservableNumberValue op2) {
2224         return Bindings.divide(IntegerConstant.valueOf(op1), op2, op2);
2225     }
2226 
2227     // =================================================================================================================
2228     // Equals
2229 
2230     private static BooleanBinding equal(final ObservableNumberValue op1, final ObservableNumberValue op2, final double epsilon, final Observable... dependencies) {
2231         if ((op1 == null) || (op2 == null)) {
2232             throw new NullPointerException("Operands cannot be null.");
2233         }
2234         assert (dependencies != null) && (dependencies.length > 0);
2235 
2236         if ((op1 instanceof ObservableDoubleValue) || (op2 instanceof ObservableDoubleValue)) {
2237             return new BooleanBinding() {
2238                 {
2239                     super.bind(dependencies);
2240                 }
2241 
2242                 @Override
2243                 public void dispose() {
2244                     super.unbind(dependencies);
2245                 }
2246 
2247                 @Override
2248                 protected boolean computeValue() {
2249                     return Math.abs(op1.doubleValue() - op2.doubleValue()) <= epsilon;
2250                 }
2251 
2252                 @Override
2253                 public ObservableList<?> getDependencies() {
2254                     return (dependencies.length == 1)?
2255                             FXCollections.singletonObservableList(dependencies[0])
2256                             : new ImmutableObservableList<Observable>(dependencies);
2257                 }
2258             };
2259         } else if ((op1 instanceof ObservableFloatValue) || (op2 instanceof ObservableFloatValue)) {
2260             return new BooleanBinding() {
2261                 {
2262                     super.bind(dependencies);
2263                 }
2264 
2265                 @Override
2266                 public void dispose() {
2267                     super.unbind(dependencies);
2268                 }
2269 
2270                 @Override
2271                 protected boolean computeValue() {
2272                     return Math.abs(op1.floatValue() - op2.floatValue()) <= epsilon;
2273                 }
2274 
2275                 @Override
2276                 public ObservableList<?> getDependencies() {
2277                     return (dependencies.length == 1)?
2278                             FXCollections.singletonObservableList(dependencies[0])
2279                             : new ImmutableObservableList<Observable>(dependencies);
2280                 }
2281             };
2282         } else if ((op1 instanceof ObservableLongValue) || (op2 instanceof ObservableLongValue)) {
2283             return new BooleanBinding() {
2284                 {
2285                     super.bind(dependencies);
2286                 }
2287 
2288                 @Override
2289                 public void dispose() {
2290                     super.unbind(dependencies);
2291                 }
2292 
2293                 @Override
2294                 protected boolean computeValue() {
2295                     return Math.abs(op1.longValue() - op2.longValue()) <= epsilon;
2296                 }
2297 
2298                 @Override
2299                 public ObservableList<?> getDependencies() {
2300                     return (dependencies.length == 1)?
2301                             FXCollections.singletonObservableList(dependencies[0])
2302                             : new ImmutableObservableList<Observable>(dependencies);
2303                 }
2304             };
2305         } else {
2306             return new BooleanBinding() {
2307                 {
2308                     super.bind(dependencies);
2309                 }
2310 
2311                 @Override
2312                 public void dispose() {
2313                     super.unbind(dependencies);
2314                 }
2315 
2316                 @Override
2317                 protected boolean computeValue() {
2318                     return Math.abs(op1.intValue() - op2.intValue()) <= epsilon;
2319                 }
2320 
2321                 @Override
2322                 public ObservableList<?> getDependencies() {
2323                     return (dependencies.length == 1)?
2324                             FXCollections.singletonObservableList(dependencies[0])
2325                             : new ImmutableObservableList<Observable>(dependencies);
2326                 }
2327             };
2328         }
2329     }
2330 
2331     /**
2332      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2333      * if the values of two instances of
2334      * {@link javafx.beans.value.ObservableNumberValue} are equal (with a
2335      * tolerance).
2336      * <p>
2337      * Two operands {@code a} and {@code b} are considered equal if
2338      * {@code Math.abs(a-b) <= epsilon}.
2339      * <p>
2340      * Allowing a small tolerance is recommended when comparing floating-point
2341      * numbers because of rounding-errors.
2342      *
2343      * @param op1
2344      *            the first operand
2345      * @param op2
2346      *            the second operand
2347      * @param epsilon
2348      *            the permitted tolerance
2349      * @return the new {@code BooleanBinding}
2350      * @throws NullPointerException
2351      *             if one of the operands is {@code null}
2352      */
2353     public static BooleanBinding equal(final ObservableNumberValue op1, final ObservableNumberValue op2, final double epsilon) {
2354         return Bindings.equal(op1, op2, epsilon, op1, op2);
2355     }
2356 
2357     /**
2358      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2359      * if the values of two instances of
2360      * {@link javafx.beans.value.ObservableNumberValue} are equal.
2361      * <p>
2362      * When comparing floating-point numbers it is recommended to use the
2363      * {@link #equal(ObservableNumberValue, ObservableNumberValue, double)
2364      * equal()} method that allows a small tolerance.
2365      *
2366      * @param op1
2367      *            the first operand
2368      * @param op2
2369      *            the second operand
2370      * @return the new {@code BooleanBinding}
2371      * @throws NullPointerException
2372      *             if one of the operands is {@code null}
2373      */
2374     public static BooleanBinding equal(final ObservableNumberValue op1, final ObservableNumberValue op2) {
2375         return equal(op1, op2, 0.0, op1, op2);
2376     }
2377 
2378     /**
2379      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2380      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2381      * equal to a constant value (with a tolerance).
2382      * <p>
2383      * Two operands {@code a} and {@code b} are considered equal if
2384      * {@code Math.abs(a-b) <= epsilon}.
2385      * <p>
2386      * Allowing a small tolerance is recommended when comparing floating-point
2387      * numbers because of rounding-errors.
2388      *
2389      * @param op1
2390      *            the {@code ObservableNumberValue}
2391      * @param op2
2392      *            the constant value
2393      * @param epsilon
2394      *            the permitted tolerance
2395      * @return the new {@code BooleanBinding}
2396      * @throws NullPointerException
2397      *             if the {@code ObservableNumberValue} is {@code null}
2398      */
2399     public static BooleanBinding equal(final ObservableNumberValue op1, final double op2, final double epsilon) {
2400         return equal(op1, DoubleConstant.valueOf(op2), epsilon,  op1);
2401     }
2402 
2403     /**
2404      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2405      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2406      * equal to a constant value (with a tolerance).
2407      * <p>
2408      * Two operands {@code a} and {@code b} are considered equal if
2409      * {@code Math.abs(a-b) <= epsilon}.
2410      * <p>
2411      * Allowing a small tolerance is recommended when comparing floating-point
2412      * numbers because of rounding-errors.
2413      *
2414      * @param op1
2415      *            the constant value
2416      * @param op2
2417      *            the {@code ObservableNumberValue}
2418      * @param epsilon
2419      *            the permitted tolerance
2420      * @return the new {@code BooleanBinding}
2421      * @throws NullPointerException
2422      *             if the {@code ObservableNumberValue} is {@code null}
2423      */
2424     public static BooleanBinding equal(final double op1, final ObservableNumberValue op2, final double epsilon) {
2425         return equal(DoubleConstant.valueOf(op1), op2, epsilon, op2);
2426     }
2427 
2428     /**
2429      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2430      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2431      * equal to a constant value (with a tolerance).
2432      * <p>
2433      * Two operands {@code a} and {@code b} are considered equal if
2434      * {@code Math.abs(a-b) <= epsilon}.
2435      * <p>
2436      * Allowing a small tolerance is recommended when comparing floating-point
2437      * numbers because of rounding-errors.
2438      *
2439      * @param op1
2440      *            the {@code ObservableNumberValue}
2441      * @param op2
2442      *            the constant value
2443      * @param epsilon
2444      *            the permitted tolerance
2445      * @return the new {@code BooleanBinding}
2446      * @throws NullPointerException
2447      *             if the {@code ObservableNumberValue} is {@code null}
2448      */
2449     public static BooleanBinding equal(final ObservableNumberValue op1, final float op2, final double epsilon) {
2450         return equal(op1, FloatConstant.valueOf(op2), epsilon, op1);
2451     }
2452 
2453     /**
2454      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2455      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2456      * equal to a constant value (with a tolerance).
2457      * <p>
2458      * Two operands {@code a} and {@code b} are considered equal if
2459      * {@code Math.abs(a-b) <= epsilon}.
2460      * <p>
2461      * Allowing a small tolerance is recommended when comparing floating-point
2462      * numbers because of rounding-errors.
2463      *
2464      * @param op1
2465      *            the constant value
2466      * @param op2
2467      *            the {@code ObservableNumberValue}
2468      * @param epsilon
2469      *            the permitted tolerance
2470      * @return the new {@code BooleanBinding}
2471      * @throws NullPointerException
2472      *             if the {@code ObservableNumberValue} is {@code null}
2473      */
2474     public static BooleanBinding equal(final float op1, final ObservableNumberValue op2, final double epsilon) {
2475         return equal(FloatConstant.valueOf(op1), op2, epsilon, op2);
2476     }
2477 
2478     /**
2479      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2480      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2481      * equal to a constant value (with a tolerance).
2482      * <p>
2483      * Two operands {@code a} and {@code b} are considered equal if
2484      * {@code Math.abs(a-b) <= epsilon}.
2485      * <p>
2486      * Allowing a small tolerance is recommended when comparing floating-point
2487      * numbers because of rounding-errors.
2488      *
2489      * @param op1
2490      *            the {@code ObservableNumberValue}
2491      * @param op2
2492      *            the constant value
2493      * @param epsilon
2494      *            the permitted tolerance
2495      * @return the new {@code BooleanBinding}
2496      * @throws NullPointerException
2497      *             if the {@code ObservableNumberValue} is {@code null}
2498      */
2499     public static BooleanBinding equal(final ObservableNumberValue op1, final long op2, final double epsilon) {
2500         return equal(op1, LongConstant.valueOf(op2), epsilon, op1);
2501     }
2502 
2503     /**
2504      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2505      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2506      * equal to a constant value.
2507      * <p>
2508      * When comparing floating-point numbers it is recommended to use the
2509      * {@link #equal(ObservableNumberValue, long, double) equal()} method that
2510      * allows a small tolerance.
2511      *
2512      * @param op1
2513      *            the {@code ObservableNumberValue}
2514      * @param op2
2515      *            the constant value
2516      * @return the new {@code BooleanBinding}
2517      * @throws NullPointerException
2518      *             if the {@code ObservableNumberValue} is {@code null}
2519      */
2520     public static BooleanBinding equal(final ObservableNumberValue op1, final long op2) {
2521         return equal(op1, LongConstant.valueOf(op2), 0.0, op1);
2522     }
2523 
2524     /**
2525      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2526      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2527      * equal to a constant value (with a tolerance).
2528      * <p>
2529      * Two operands {@code a} and {@code b} are considered equal if
2530      * {@code Math.abs(a-b) <= epsilon}.
2531      * <p>
2532      * Allowing a small tolerance is recommended when comparing floating-point
2533      * numbers because of rounding-errors.
2534      *
2535      * @param op1
2536      *            the constant value
2537      * @param op2
2538      *            the {@code ObservableNumberValue}
2539      * @param epsilon
2540      *            the permitted tolerance
2541      * @return the new {@code BooleanBinding}
2542      * @throws NullPointerException
2543      *             if the {@code ObservableNumberValue} is {@code null}
2544      */
2545     public static BooleanBinding equal(final long op1, final ObservableNumberValue op2, final double epsilon) {
2546         return equal(LongConstant.valueOf(op1), op2, epsilon, op2);
2547     }
2548 
2549     /**
2550      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2551      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2552      * equal to a constant value.
2553      * <p>
2554      * When comparing floating-point numbers it is recommended to use the
2555      * {@link #equal(long, ObservableNumberValue, double) equal()} method that
2556      * allows a small tolerance.
2557      *
2558      * @param op1
2559      *            the constant value
2560      * @param op2
2561      *            the {@code ObservableNumberValue}
2562      * @return the new {@code BooleanBinding}
2563      * @throws NullPointerException
2564      *             if the {@code ObservableNumberValue} is {@code null}
2565      */
2566     public static BooleanBinding equal(final long op1, final ObservableNumberValue op2) {
2567         return equal(LongConstant.valueOf(op1), op2, 0.0, op2);
2568     }
2569 
2570     /**
2571      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2572      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2573      * equal to a constant value (with a tolerance).
2574      * <p>
2575      * Two operands {@code a} and {@code b} are considered equal if
2576      * {@code Math.abs(a-b) <= epsilon}.
2577      * <p>
2578      * Allowing a small tolerance is recommended when comparing floating-point
2579      * numbers because of rounding-errors.
2580      *
2581      * @param op1
2582      *            the {@code ObservableNumberValue}
2583      * @param op2
2584      *            the constant value
2585      * @param epsilon
2586      *            the permitted tolerance
2587      * @return the new {@code BooleanBinding}
2588      * @throws NullPointerException
2589      *             if the {@code ObservableNumberValue} is {@code null}
2590      */
2591     public static BooleanBinding equal(final ObservableNumberValue op1, final int op2, final double epsilon) {
2592         return equal(op1, IntegerConstant.valueOf(op2), epsilon, op1);
2593     }
2594 
2595     /**
2596      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2597      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2598      * equal to a constant value.
2599      * <p>
2600      * When comparing floating-point numbers it is recommended to use the
2601      * {@link #equal(ObservableNumberValue, int, double) equal()} method that
2602      * allows a small tolerance.
2603      *
2604      * @param op1
2605      *            the {@code ObservableNumberValue}
2606      * @param op2
2607      *            the constant value
2608      * @return the new {@code BooleanBinding}
2609      * @throws NullPointerException
2610      *             if the {@code ObservableNumberValue} is {@code null}
2611      */
2612     public static BooleanBinding equal(final ObservableNumberValue op1, final int op2) {
2613         return equal(op1, IntegerConstant.valueOf(op2), 0.0, op1);
2614     }
2615 
2616     /**
2617      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2618      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2619      * equal to a constant value (with a tolerance).
2620      * <p>
2621      * Two operands {@code a} and {@code b} are considered equal if
2622      * {@code Math.abs(a-b) <= epsilon}.
2623      * <p>
2624      * Allowing a small tolerance is recommended when comparing floating-point
2625      * numbers because of rounding-errors.
2626      *
2627      * @param op1
2628      *            the constant value
2629      * @param op2
2630      *            the {@code ObservableNumberValue}
2631      * @param epsilon
2632      *            the permitted tolerance
2633      * @return the new {@code BooleanBinding}
2634      * @throws NullPointerException
2635      *             if the {@code ObservableNumberValue} is {@code null}
2636      */
2637     public static BooleanBinding equal(final int op1, final ObservableNumberValue op2, final double epsilon) {
2638         return equal(IntegerConstant.valueOf(op1), op2, epsilon, op2);
2639     }
2640 
2641     /**
2642      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2643      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
2644      * equal to a constant value.
2645      * <p>
2646      * When comparing floating-point numbers it is recommended to use the
2647      * {@link #equal(int, ObservableNumberValue, double) equal()} method that
2648      * allows a small tolerance.
2649      *
2650      * @param op1
2651      *            the constant value
2652      * @param op2
2653      *            the {@code ObservableNumberValue}
2654      * @return the new {@code BooleanBinding}
2655      * @throws NullPointerException
2656      *             if the {@code ObservableNumberValue} is {@code null}
2657      */
2658     public static BooleanBinding equal(final int op1, final ObservableNumberValue op2) {
2659         return equal(IntegerConstant.valueOf(op1), op2, 0.0, op2);
2660     }
2661 
2662     // =================================================================================================================
2663     // Not Equal
2664 
2665     private static BooleanBinding notEqual(final ObservableNumberValue op1, final ObservableNumberValue op2, final double epsilon, final Observable... dependencies) {
2666         if ((op1 == null) || (op2 == null)) {
2667             throw new NullPointerException("Operands cannot be null.");
2668         }
2669         assert (dependencies != null) && (dependencies.length > 0);
2670 
2671         if ((op1 instanceof ObservableDoubleValue) || (op2 instanceof ObservableDoubleValue)) {
2672             return new BooleanBinding() {
2673                 {
2674                     super.bind(dependencies);
2675                 }
2676 
2677                 @Override
2678                 public void dispose() {
2679                     super.unbind(dependencies);
2680                 }
2681 
2682                 @Override
2683                 protected boolean computeValue() {
2684                     return Math.abs(op1.doubleValue() - op2.doubleValue()) > epsilon;
2685                 }
2686 
2687                 @Override
2688                 public ObservableList<?> getDependencies() {
2689                     return (dependencies.length == 1)?
2690                             FXCollections.singletonObservableList(dependencies[0])
2691                             : new ImmutableObservableList<Observable>(dependencies);
2692                 }
2693             };
2694         } else if ((op1 instanceof ObservableFloatValue) || (op2 instanceof ObservableFloatValue)) {
2695             return new BooleanBinding() {
2696                 {
2697                     super.bind(dependencies);
2698                 }
2699 
2700                 @Override
2701                 public void dispose() {
2702                     super.unbind(dependencies);
2703                 }
2704 
2705                 @Override
2706                 protected boolean computeValue() {
2707                     return Math.abs(op1.floatValue() - op2.floatValue()) > epsilon;
2708                 }
2709 
2710                 @Override
2711                 public ObservableList<?> getDependencies() {
2712                     return (dependencies.length == 1)?
2713                             FXCollections.singletonObservableList(dependencies[0])
2714                             : new ImmutableObservableList<Observable>(dependencies);
2715                 }
2716             };
2717         } else if ((op1 instanceof ObservableLongValue) || (op2 instanceof ObservableLongValue)) {
2718             return new BooleanBinding() {
2719                 {
2720                     super.bind(dependencies);
2721                 }
2722 
2723                 @Override
2724                 public void dispose() {
2725                     super.unbind(dependencies);
2726                 }
2727 
2728                 @Override
2729                 protected boolean computeValue() {
2730                     return Math.abs(op1.longValue() - op2.longValue()) > epsilon;
2731                 }
2732 
2733                 @Override
2734                 public ObservableList<?> getDependencies() {
2735                     return (dependencies.length == 1)?
2736                             FXCollections.singletonObservableList(dependencies[0])
2737                             : new ImmutableObservableList<Observable>(dependencies);
2738                 }
2739             };
2740         } else {
2741             return new BooleanBinding() {
2742                 {
2743                     super.bind(dependencies);
2744                 }
2745 
2746                 @Override
2747                 public void dispose() {
2748                     super.unbind(dependencies);
2749                 }
2750 
2751                 @Override
2752                 protected boolean computeValue() {
2753                     return Math.abs(op1.intValue() - op2.intValue()) > epsilon;
2754                 }
2755 
2756                 @Override
2757                 public ObservableList<?> getDependencies() {
2758                     return (dependencies.length == 1)?
2759                             FXCollections.singletonObservableList(dependencies[0])
2760                             : new ImmutableObservableList<Observable>(dependencies);
2761                 }
2762             };
2763         }
2764     }
2765 
2766     /**
2767      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2768      * if the values of two instances of
2769      * {@link javafx.beans.value.ObservableNumberValue} are not equal (with a
2770      * tolerance).
2771      * <p>
2772      * Two operands {@code a} and {@code b} are considered equal if
2773      * {@code Math.abs(a-b) <= epsilon}.
2774      * <p>
2775      * Allowing a small tolerance is recommended when comparing floating-point
2776      * numbers because of rounding-errors.
2777      *
2778      * @param op1
2779      *            the first operand
2780      * @param op2
2781      *            the second operand
2782      * @param epsilon
2783      *            the permitted tolerance
2784      * @return the new {@code BooleanBinding}
2785      * @throws NullPointerException
2786      *             if one of the operands is {@code null}
2787      */
2788     public static BooleanBinding notEqual(final ObservableNumberValue op1, final ObservableNumberValue op2, final double epsilon) {
2789         return Bindings.notEqual(op1, op2, epsilon, op1, op2);
2790     }
2791 
2792     /**
2793      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2794      * if the values of two instances of
2795      * {@link javafx.beans.value.ObservableNumberValue} are not equal.
2796      * <p>
2797      * When comparing floating-point numbers it is recommended to use the
2798      * {@link #notEqual(ObservableNumberValue, ObservableNumberValue, double)
2799      * notEqual()} method that allows a small tolerance.
2800      *
2801      * @param op1
2802      *            the first operand
2803      * @param op2
2804      *            the second operand
2805      * @return the new {@code BooleanBinding}
2806      * @throws NullPointerException
2807      *             if one of the operands is {@code null}
2808      */
2809     public static BooleanBinding notEqual(final ObservableNumberValue op1, final ObservableNumberValue op2) {
2810         return notEqual(op1, op2, 0.0, op1, op2);
2811     }
2812 
2813     /**
2814      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2815      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
2816      * equal to a constant value (with a tolerance).
2817      * <p>
2818      * Two operands {@code a} and {@code b} are considered equal if
2819      * {@code Math.abs(a-b) <= epsilon}.
2820      * <p>
2821      * Allowing a small tolerance is recommended when comparing floating-point
2822      * numbers because of rounding-errors.
2823      *
2824      * @param op1
2825      *            the {@code ObservableNumberValue}
2826      * @param op2
2827      *            the constant value
2828      * @param epsilon
2829      *            the permitted tolerance
2830      * @return the new {@code BooleanBinding}
2831      * @throws NullPointerException
2832      *             if the {@code ObservableNumberValue} is {@code null}
2833      */
2834     public static BooleanBinding notEqual(final ObservableNumberValue op1, final double op2, final double epsilon) {
2835         return notEqual(op1, DoubleConstant.valueOf(op2), epsilon, op1);
2836     }
2837 
2838     /**
2839      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2840      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
2841      * equal to a constant value (with a tolerance).
2842      * <p>
2843      * Two operands {@code a} and {@code b} are considered equal if
2844      * {@code Math.abs(a-b) <= epsilon}.
2845      * <p>
2846      * Allowing a small tolerance is recommended when comparing floating-point
2847      * numbers because of rounding-errors.
2848      *
2849      * @param op1
2850      *            the constant value
2851      * @param op2
2852      *            the {@code ObservableNumberValue}
2853      * @param epsilon
2854      *            the permitted tolerance
2855      * @return the new {@code BooleanBinding}
2856      * @throws NullPointerException
2857      *             if the {@code ObservableNumberValue} is {@code null}
2858      */
2859     public static BooleanBinding notEqual(final double op1, final ObservableNumberValue op2, final double epsilon) {
2860         return notEqual(DoubleConstant.valueOf(op1), op2, epsilon, op2);
2861     }
2862 
2863     /**
2864      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2865      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
2866      * equal to a constant value (with a tolerance).
2867      * <p>
2868      * Two operands {@code a} and {@code b} are considered equal if
2869      * {@code Math.abs(a-b) <= epsilon}.
2870      * <p>
2871      * Allowing a small tolerance is recommended when comparing floating-point
2872      * numbers because of rounding-errors.
2873      *
2874      * @param op1
2875      *            the {@code ObservableNumberValue}
2876      * @param op2
2877      *            the constant value
2878      * @param epsilon
2879      *            the permitted tolerance
2880      * @return the new {@code BooleanBinding}
2881      * @throws NullPointerException
2882      *             if the {@code ObservableNumberValue} is {@code null}
2883      */
2884     public static BooleanBinding notEqual(final ObservableNumberValue op1, final float op2, final double epsilon) {
2885         return notEqual(op1, FloatConstant.valueOf(op2), epsilon, op1);
2886     }
2887 
2888     /**
2889      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2890      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
2891      * equal to a constant value (with a tolerance).
2892      * <p>
2893      * Two operands {@code a} and {@code b} are considered equal if
2894      * {@code Math.abs(a-b) <= epsilon}.
2895      * <p>
2896      * Allowing a small tolerance is recommended when comparing floating-point
2897      * numbers because of rounding-errors.
2898      *
2899      * @param op1
2900      *            the constant value
2901      * @param op2
2902      *            the {@code ObservableNumberValue}
2903      * @param epsilon
2904      *            the permitted tolerance
2905      * @return the new {@code BooleanBinding}
2906      * @throws NullPointerException
2907      *             if the {@code ObservableNumberValue} is {@code null}
2908      */
2909     public static BooleanBinding notEqual(final float op1, final ObservableNumberValue op2, final double epsilon) {
2910         return notEqual(FloatConstant.valueOf(op1), op2, epsilon, op2);
2911     }
2912 
2913     /**
2914      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2915      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
2916      * equal to a constant value (with a tolerance).
2917      * <p>
2918      * Two operands {@code a} and {@code b} are considered equal if
2919      * {@code Math.abs(a-b) <= epsilon}.
2920      * <p>
2921      * Allowing a small tolerance is recommended when comparing floating-point
2922      * numbers because of rounding-errors.
2923      *
2924      * @param op1
2925      *            the {@code ObservableNumberValue}
2926      * @param op2
2927      *            the constant value
2928      * @param epsilon
2929      *            the permitted tolerance
2930      * @return the new {@code BooleanBinding}
2931      * @throws NullPointerException
2932      *             if the {@code ObservableNumberValue} is {@code null}
2933      */
2934     public static BooleanBinding notEqual(final ObservableNumberValue op1, final long op2, final double epsilon) {
2935         return notEqual(op1, LongConstant.valueOf(op2), epsilon, op1);
2936     }
2937 
2938     /**
2939      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2940      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
2941      * equal to a constant value.
2942      * <p>
2943      * When comparing floating-point numbers it is recommended to use the
2944      * {@link #notEqual(ObservableNumberValue, long, double) notEqual()} method
2945      * that allows a small tolerance.
2946      *
2947      * @param op1
2948      *            the {@code ObservableNumberValue}
2949      * @param op2
2950      *            the constant value
2951      * @return the new {@code BooleanBinding}
2952      * @throws NullPointerException
2953      *             if the {@code ObservableNumberValue} is {@code null}
2954      */
2955     public static BooleanBinding notEqual(final ObservableNumberValue op1, final long op2) {
2956         return notEqual(op1, LongConstant.valueOf(op2), 0.0, op1);
2957     }
2958 
2959     /**
2960      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2961      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
2962      * equal to a constant value (with a tolerance).
2963      * <p>
2964      * Two operands {@code a} and {@code b} are considered equal if
2965      * {@code Math.abs(a-b) <= epsilon}.
2966      * <p>
2967      * Allowing a small tolerance is recommended when comparing floating-point
2968      * numbers because of rounding-errors.
2969      *
2970      * @param op1
2971      *            the constant value
2972      * @param op2
2973      *            the {@code ObservableNumberValue}
2974      * @param epsilon
2975      *            the permitted tolerance
2976      * @return the new {@code BooleanBinding}
2977      * @throws NullPointerException
2978      *             if the {@code ObservableNumberValue} is {@code null}
2979      */
2980     public static BooleanBinding notEqual(final long op1, final ObservableNumberValue op2, final double epsilon) {
2981         return notEqual(LongConstant.valueOf(op1), op2, epsilon, op2);
2982     }
2983 
2984     /**
2985      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
2986      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
2987      * equal to a constant value.
2988      * <p>
2989      * When comparing floating-point numbers it is recommended to use the
2990      * {@link #notEqual(long, ObservableNumberValue, double) notEqual()} method
2991      * that allows a small tolerance.
2992      *
2993      * @param op1
2994      *            the constant value
2995      * @param op2
2996      *            the {@code ObservableNumberValue}
2997      * @return the new {@code BooleanBinding}
2998      * @throws NullPointerException
2999      *             if the {@code ObservableNumberValue} is {@code null}
3000      */
3001     public static BooleanBinding notEqual(final long op1, final ObservableNumberValue op2) {
3002         return notEqual(LongConstant.valueOf(op1), op2, 0.0, op2);
3003     }
3004 
3005     /**
3006      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3007      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
3008      * equal to a constant value (with a tolerance).
3009      * <p>
3010      * Two operands {@code a} and {@code b} are considered equal if
3011      * {@code Math.abs(a-b) <= epsilon}.
3012      * <p>
3013      * Allowing a small tolerance is recommended when comparing floating-point
3014      * numbers because of rounding-errors.
3015      *
3016      * @param op1
3017      *            the {@code ObservableNumberValue}
3018      * @param op2
3019      *            the constant value
3020      * @param epsilon
3021      *            the permitted tolerance
3022      * @return the new {@code BooleanBinding}
3023      * @throws NullPointerException
3024      *             if the {@code ObservableNumberValue} is {@code null}
3025      */
3026     public static BooleanBinding notEqual(final ObservableNumberValue op1, final int op2, final double epsilon) {
3027         return notEqual(op1, IntegerConstant.valueOf(op2), epsilon, op1);
3028     }
3029 
3030     /**
3031      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3032      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
3033      * equal to a constant value.
3034      * <p>
3035      * When comparing floating-point numbers it is recommended to use the
3036      * {@link #notEqual(ObservableNumberValue, int, double) notEqual()} method
3037      * that allows a small tolerance.
3038      *
3039      * @param op1
3040      *            the {@code ObservableNumberValue}
3041      * @param op2
3042      *            the constant value
3043      * @return the new {@code BooleanBinding}
3044      * @throws NullPointerException
3045      *             if the {@code ObservableNumberValue} is {@code null}
3046      */
3047     public static BooleanBinding notEqual(final ObservableNumberValue op1, final int op2) {
3048         return notEqual(op1, IntegerConstant.valueOf(op2), 0.0, op1);
3049     }
3050 
3051     /**
3052      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3053      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
3054      * equal to a constant value (with a tolerance).
3055      * <p>
3056      * Two operands {@code a} and {@code b} are considered equal if
3057      * {@code Math.abs(a-b) <= epsilon}.
3058      * <p>
3059      * Allowing a small tolerance is recommended when comparing floating-point
3060      * numbers because of rounding-errors.
3061      *
3062      * @param op1
3063      *            the constant value
3064      * @param op2
3065      *            the {@code ObservableNumberValue}
3066      * @param epsilon
3067      *            the permitted tolerance
3068      * @return the new {@code BooleanBinding}
3069      * @throws NullPointerException
3070      *             if the {@code ObservableNumberValue} is {@code null}
3071      */
3072     public static BooleanBinding notEqual(final int op1, final ObservableNumberValue op2, final double epsilon) {
3073         return notEqual(IntegerConstant.valueOf(op1), op2, epsilon, op2);
3074     }
3075 
3076     /**
3077      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3078      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is not
3079      * equal to a constant value.
3080      * <p>
3081      * When comparing floating-point numbers it is recommended to use the
3082      * {@link #notEqual(int, ObservableNumberValue, double) notEqual()} method
3083      * that allows a small tolerance.
3084      *
3085      * @param op1
3086      *            the constant value
3087      * @param op2
3088      *            the {@code ObservableNumberValue}
3089      * @return the new {@code BooleanBinding}
3090      * @throws NullPointerException
3091      *             if the {@code ObservableNumberValue} is {@code null}
3092      */
3093     public static BooleanBinding notEqual(final int op1, final ObservableNumberValue op2) {
3094         return notEqual(IntegerConstant.valueOf(op1), op2, 0.0, op2);
3095     }
3096 
3097     // =================================================================================================================
3098     // Greater Than
3099 
3100     private static BooleanBinding greaterThan(final ObservableNumberValue op1, final ObservableNumberValue op2, final Observable... dependencies) {
3101         if ((op1 == null) || (op2 == null)) {
3102             throw new NullPointerException("Operands cannot be null.");
3103         }
3104         assert (dependencies != null) && (dependencies.length > 0);
3105 
3106         if ((op1 instanceof ObservableDoubleValue) || (op2 instanceof ObservableDoubleValue)) {
3107             return new BooleanBinding() {
3108                 {
3109                     super.bind(dependencies);
3110                 }
3111 
3112                 @Override
3113                 public void dispose() {
3114                     super.unbind(dependencies);
3115                 }
3116 
3117                 @Override
3118                 protected boolean computeValue() {
3119                     return op1.doubleValue() > op2.doubleValue();
3120                 }
3121 
3122                 @Override
3123                 public ObservableList<?> getDependencies() {
3124                     return (dependencies.length == 1)?
3125                             FXCollections.singletonObservableList(dependencies[0])
3126                             : new ImmutableObservableList<Observable>(dependencies);
3127                 }
3128             };
3129         } else if ((op1 instanceof ObservableFloatValue) || (op2 instanceof ObservableFloatValue)) {
3130             return new BooleanBinding() {
3131                 {
3132                     super.bind(dependencies);
3133                 }
3134 
3135                 @Override
3136                 public void dispose() {
3137                     super.unbind(dependencies);
3138                 }
3139 
3140                 @Override
3141                 protected boolean computeValue() {
3142                     return op1.floatValue() > op2.floatValue();
3143                 }
3144 
3145                 @Override
3146                 public ObservableList<?> getDependencies() {
3147                     return (dependencies.length == 1)?
3148                             FXCollections.singletonObservableList(dependencies[0])
3149                             : new ImmutableObservableList<Observable>(dependencies);
3150                 }
3151             };
3152         } else if ((op1 instanceof ObservableLongValue) || (op2 instanceof ObservableLongValue)) {
3153             return new BooleanBinding() {
3154                 {
3155                     super.bind(dependencies);
3156                 }
3157 
3158                 @Override
3159                 public void dispose() {
3160                     super.unbind(dependencies);
3161                 }
3162 
3163                 @Override
3164                 protected boolean computeValue() {
3165                     return op1.longValue() > op2.longValue();
3166                 }
3167 
3168                 @Override
3169                 public ObservableList<?> getDependencies() {
3170                     return (dependencies.length == 1)?
3171                             FXCollections.singletonObservableList(dependencies[0])
3172                             : new ImmutableObservableList<Observable>(dependencies);
3173                 }
3174             };
3175         } else {
3176             return new BooleanBinding() {
3177                 {
3178                     super.bind(dependencies);
3179                 }
3180 
3181                 @Override
3182                 public void dispose() {
3183                     super.unbind(dependencies);
3184                 }
3185 
3186                 @Override
3187                 protected boolean computeValue() {
3188                     return op1.intValue() > op2.intValue();
3189                 }
3190 
3191                 @Override
3192                 public ObservableList<?> getDependencies() {
3193                     return (dependencies.length == 1)?
3194                             FXCollections.singletonObservableList(dependencies[0])
3195                             : new ImmutableObservableList<Observable>(dependencies);
3196                 }
3197             };
3198         }
3199     }
3200 
3201     /**
3202      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3203      * if the value of the first
3204      * {@link javafx.beans.value.ObservableNumberValue} is greater than the
3205      * value of the second.
3206      *
3207      * @param op1
3208      *            the first operand
3209      * @param op2
3210      *            the second operand
3211      * @return the new {@code BooleanBinding}
3212      * @throws NullPointerException
3213      *             if one of the operands is {@code null}
3214      */
3215     public static BooleanBinding greaterThan(final ObservableNumberValue op1, final ObservableNumberValue op2) {
3216         return Bindings.greaterThan(op1, op2, op1, op2);
3217     }
3218 
3219     /**
3220      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3221      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3222      * greater than a constant value.
3223      *
3224      * @param op1
3225      *            the {@code ObservableNumberValue}
3226      * @param op2
3227      *            the constant value
3228      * @return the new {@code BooleanBinding}
3229      * @throws NullPointerException
3230      *             if the {@code ObservableNumberValue} is {@code null}
3231      */
3232     public static BooleanBinding greaterThan(final ObservableNumberValue op1, final double op2) {
3233         return greaterThan(op1, DoubleConstant.valueOf(op2), op1);
3234     }
3235 
3236     /**
3237      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3238      * if a constant value is greater than the value of a
3239      * {@link javafx.beans.value.ObservableNumberValue}.
3240      *
3241      * @param op1
3242      *            the constant value
3243      * @param op2
3244      *            the {@code ObservableNumberValue}
3245      * @return the new {@code BooleanBinding}
3246      * @throws NullPointerException
3247      *             if the {@code ObservableNumberValue} is {@code null}
3248      */
3249     public static BooleanBinding greaterThan(final double op1, final ObservableNumberValue op2) {
3250         return greaterThan(DoubleConstant.valueOf(op1), op2, op2);
3251     }
3252 
3253     /**
3254      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3255      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3256      * greater than a constant value.
3257      *
3258      * @param op1
3259      *            the {@code ObservableNumberValue}
3260      * @param op2
3261      *            the constant value
3262      * @return the new {@code BooleanBinding}
3263      * @throws NullPointerException
3264      *             if the {@code ObservableNumberValue} is {@code null}
3265      */
3266     public static BooleanBinding greaterThan(final ObservableNumberValue op1, final float op2) {
3267         return greaterThan(op1, FloatConstant.valueOf(op2), op1);
3268     }
3269 
3270     /**
3271      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3272      * if a constant value is greater than the value of a
3273      * {@link javafx.beans.value.ObservableNumberValue}.
3274      *
3275      * @param op1
3276      *            the constant value
3277      * @param op2
3278      *            the {@code ObservableNumberValue}
3279      * @return the new {@code BooleanBinding}
3280      * @throws NullPointerException
3281      *             if the {@code ObservableNumberValue} is {@code null}
3282      */
3283     public static BooleanBinding greaterThan(final float op1, final ObservableNumberValue op2) {
3284         return greaterThan(FloatConstant.valueOf(op1), op2, op2);
3285     }
3286 
3287     /**
3288      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3289      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3290      * greater than a constant value.
3291      *
3292      * @param op1
3293      *            the {@code ObservableNumberValue}
3294      * @param op2
3295      *            the constant value
3296      * @return the new {@code BooleanBinding}
3297      * @throws NullPointerException
3298      *             if the {@code ObservableNumberValue} is {@code null}
3299      */
3300     public static BooleanBinding greaterThan(final ObservableNumberValue op1, final long op2) {
3301         return greaterThan(op1, LongConstant.valueOf(op2), op1);
3302     }
3303 
3304     /**
3305      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3306      * if a constant value is greater than the value of a
3307      * {@link javafx.beans.value.ObservableNumberValue}.
3308      *
3309      * @param op1
3310      *            the constant value
3311      * @param op2
3312      *            the {@code ObservableNumberValue}
3313      * @return the new {@code BooleanBinding}
3314      * @throws NullPointerException
3315      *             if the {@code ObservableNumberValue} is {@code null}
3316      */
3317     public static BooleanBinding greaterThan(final long op1, final ObservableNumberValue op2) {
3318         return greaterThan(LongConstant.valueOf(op1), op2, op2);
3319     }
3320 
3321     /**
3322      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3323      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3324      * greater than a constant value.
3325      *
3326      * @param op1
3327      *            the {@code ObservableNumberValue}
3328      * @param op2
3329      *            the constant value
3330      * @return the new {@code BooleanBinding}
3331      * @throws NullPointerException
3332      *             if the {@code ObservableNumberValue} is {@code null}
3333      */
3334     public static BooleanBinding greaterThan(final ObservableNumberValue op1, final int op2) {
3335         return greaterThan(op1, IntegerConstant.valueOf(op2), op1);
3336     }
3337 
3338     /**
3339      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3340      * if a constant value is greater than the value of a
3341      * {@link javafx.beans.value.ObservableNumberValue}.
3342      *
3343      * @param op1
3344      *            the constant value
3345      * @param op2
3346      *            the {@code ObservableNumberValue}
3347      * @return the new {@code BooleanBinding}
3348      * @throws NullPointerException
3349      *             if the {@code ObservableNumberValue} is {@code null}
3350      */
3351     public static BooleanBinding greaterThan(final int op1, final ObservableNumberValue op2) {
3352         return greaterThan(IntegerConstant.valueOf(op1), op2, op2);
3353     }
3354 
3355     // =================================================================================================================
3356     // Less Than
3357 
3358     private static BooleanBinding lessThan(final ObservableNumberValue op1, final ObservableNumberValue op2, final Observable... dependencies) {
3359         return greaterThan(op2, op1, dependencies);
3360     }
3361 
3362     /**
3363      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3364      * if the value of the first
3365      * {@link javafx.beans.value.ObservableNumberValue} is less than the value
3366      * of the second.
3367      *
3368      * @param op1
3369      *            the first operand
3370      * @param op2
3371      *            the second operand
3372      * @return the new {@code BooleanBinding}
3373      * @throws NullPointerException
3374      *             if one of the operands is {@code null}
3375      */
3376     public static BooleanBinding lessThan(final ObservableNumberValue op1, final ObservableNumberValue op2) {
3377         return lessThan(op1, op2, op1, op2);
3378     }
3379 
3380     /**
3381      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3382      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3383      * less than a constant value.
3384      *
3385      * @param op1
3386      *            the {@code ObservableNumberValue}
3387      * @param op2
3388      *            the constant value
3389      * @return the new {@code BooleanBinding}
3390      * @throws NullPointerException
3391      *             if the {@code ObservableNumberValue} is {@code null}
3392      */
3393     public static BooleanBinding lessThan(final ObservableNumberValue op1, final double op2) {
3394         return lessThan(op1, DoubleConstant.valueOf(op2), op1);
3395     }
3396 
3397     /**
3398      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3399      * if a constant value is less than the value of a
3400      * {@link javafx.beans.value.ObservableNumberValue}.
3401      *
3402      * @param op1
3403      *            the constant value
3404      * @param op2
3405      *            the {@code ObservableNumberValue}
3406      * @return the new {@code BooleanBinding}
3407      * @throws NullPointerException
3408      *             if the {@code ObservableNumberValue} is {@code null}
3409      */
3410     public static BooleanBinding lessThan(final double op1, final ObservableNumberValue op2) {
3411         return lessThan(DoubleConstant.valueOf(op1), op2, op2);
3412     }
3413 
3414     /**
3415      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3416      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3417      * less than a constant value.
3418      *
3419      * @param op1
3420      *            the {@code ObservableNumberValue}
3421      * @param op2
3422      *            the constant value
3423      * @return the new {@code BooleanBinding}
3424      * @throws NullPointerException
3425      *             if the {@code ObservableNumberValue} is {@code null}
3426      */
3427     public static BooleanBinding lessThan(final ObservableNumberValue op1, final float op2) {
3428         return lessThan(op1, FloatConstant.valueOf(op2), op1);
3429     }
3430 
3431     /**
3432      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3433      * if a constant value is less than the value of a
3434      * {@link javafx.beans.value.ObservableNumberValue}.
3435      *
3436      * @param op1
3437      *            the constant value
3438      * @param op2
3439      *            the {@code ObservableNumberValue}
3440      * @return the new {@code BooleanBinding}
3441      * @throws NullPointerException
3442      *             if the {@code ObservableNumberValue} is {@code null}
3443      */
3444     public static BooleanBinding lessThan(final float op1, final ObservableNumberValue op2) {
3445         return lessThan(FloatConstant.valueOf(op1), op2, op2);
3446     }
3447 
3448     /**
3449      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3450      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3451      * less than a constant value.
3452      *
3453      * @param op1
3454      *            the {@code ObservableNumberValue}
3455      * @param op2
3456      *            the constant value
3457      * @return the new {@code BooleanBinding}
3458      * @throws NullPointerException
3459      *             if the {@code ObservableNumberValue} is {@code null}
3460      */
3461     public static BooleanBinding lessThan(final ObservableNumberValue op1, final long op2) {
3462         return lessThan(op1, LongConstant.valueOf(op2), op1);
3463     }
3464 
3465     /**
3466      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3467      * if a constant value is less than the value of a
3468      * {@link javafx.beans.value.ObservableNumberValue}.
3469      *
3470      * @param op1
3471      *            the constant value
3472      * @param op2
3473      *            the {@code ObservableNumberValue}
3474      * @return the new {@code BooleanBinding}
3475      * @throws NullPointerException
3476      *             if the {@code ObservableNumberValue} is {@code null}
3477      */
3478     public static BooleanBinding lessThan(final long op1, final ObservableNumberValue op2) {
3479         return lessThan(LongConstant.valueOf(op1), op2, op2);
3480     }
3481 
3482     /**
3483      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3484      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3485      * less than a constant value.
3486      *
3487      * @param op1
3488      *            the {@code ObservableNumberValue}
3489      * @param op2
3490      *            the constant value
3491      * @return the new {@code BooleanBinding}
3492      * @throws NullPointerException
3493      *             if the {@code ObservableNumberValue} is {@code null}
3494      */
3495     public static BooleanBinding lessThan(final ObservableNumberValue op1, final int op2) {
3496         return lessThan(op1, IntegerConstant.valueOf(op2), op1);
3497     }
3498 
3499     /**
3500      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3501      * if a constant value is less than the value of a
3502      * {@link javafx.beans.value.ObservableNumberValue}.
3503      *
3504      * @param op1
3505      *            the constant value
3506      * @param op2
3507      *            the {@code ObservableNumberValue}
3508      * @return the new {@code BooleanBinding}
3509      * @throws NullPointerException
3510      *             if the {@code ObservableNumberValue} is {@code null}
3511      */
3512     public static BooleanBinding lessThan(final int op1, final ObservableNumberValue op2) {
3513         return lessThan(IntegerConstant.valueOf(op1), op2, op2);
3514     }
3515 
3516     // =================================================================================================================
3517     // Greater Than or Equal
3518 
3519     private static BooleanBinding greaterThanOrEqual(final ObservableNumberValue op1, final ObservableNumberValue op2, final Observable... dependencies) {
3520         if ((op1 == null) || (op2 == null)) {
3521             throw new NullPointerException("Operands cannot be null.");
3522         }
3523         assert (dependencies != null) && (dependencies.length > 0);
3524 
3525         if ((op1 instanceof ObservableDoubleValue) || (op2 instanceof ObservableDoubleValue)) {
3526             return new BooleanBinding() {
3527                 {
3528                     super.bind(dependencies);
3529                 }
3530 
3531                 @Override
3532                 public void dispose() {
3533                     super.unbind(dependencies);
3534                 }
3535 
3536                 @Override
3537                 protected boolean computeValue() {
3538                     return op1.doubleValue() >= op2.doubleValue();
3539                 }
3540 
3541                 @Override
3542                 public ObservableList<?> getDependencies() {
3543                     return (dependencies.length == 1)?
3544                             FXCollections.singletonObservableList(dependencies[0])
3545                             : new ImmutableObservableList<Observable>(dependencies);
3546                 }
3547             };
3548         } else if ((op1 instanceof ObservableFloatValue) || (op2 instanceof ObservableFloatValue)) {
3549             return new BooleanBinding() {
3550                 {
3551                     super.bind(dependencies);
3552                 }
3553 
3554                 @Override
3555                 public void dispose() {
3556                     super.unbind(dependencies);
3557                 }
3558 
3559                 @Override
3560                 protected boolean computeValue() {
3561                     return op1.floatValue() >= op2.floatValue();
3562                 }
3563 
3564                 @Override
3565                 public ObservableList<?> getDependencies() {
3566                     return (dependencies.length == 1)?
3567                             FXCollections.singletonObservableList(dependencies[0])
3568                             : new ImmutableObservableList<Observable>(dependencies);
3569                 }
3570             };
3571         } else if ((op1 instanceof ObservableLongValue) || (op2 instanceof ObservableLongValue)) {
3572             return new BooleanBinding() {
3573                 {
3574                     super.bind(dependencies);
3575                 }
3576 
3577                 @Override
3578                 public void dispose() {
3579                     super.unbind(dependencies);
3580                 }
3581 
3582                 @Override
3583                 protected boolean computeValue() {
3584                     return op1.longValue() >= op2.longValue();
3585                 }
3586 
3587                 @Override
3588                 public ObservableList<?> getDependencies() {
3589                     return (dependencies.length == 1)?
3590                             FXCollections.singletonObservableList(dependencies[0])
3591                             : new ImmutableObservableList<Observable>(dependencies);
3592                 }
3593             };
3594         } else {
3595             return new BooleanBinding() {
3596                 {
3597                     super.bind(dependencies);
3598                 }
3599 
3600                 @Override
3601                 public void dispose() {
3602                     super.unbind(dependencies);
3603                 }
3604 
3605                 @Override
3606                 protected boolean computeValue() {
3607                     return op1.intValue() >= op2.intValue();
3608                 }
3609 
3610                 @Override
3611                 public ObservableList<?> getDependencies() {
3612                     return (dependencies.length == 1)?
3613                             FXCollections.singletonObservableList(dependencies[0])
3614                             : new ImmutableObservableList<Observable>(dependencies);
3615                 }
3616             };
3617         }
3618     }
3619 
3620     /**
3621      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3622      * if the value of the first
3623      * {@link javafx.beans.value.ObservableNumberValue} is greater than or equal
3624      * to the value of the second.
3625      *
3626      * @param op1
3627      *            the first operand
3628      * @param op2
3629      *            the second operand
3630      * @return the new {@code BooleanBinding}
3631      * @throws NullPointerException
3632      *             if one of the operands is {@code null}
3633      */
3634     public static BooleanBinding greaterThanOrEqual(final ObservableNumberValue op1, final ObservableNumberValue op2) {
3635         return greaterThanOrEqual(op1, op2, op1, op2);
3636     }
3637 
3638     /**
3639      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3640      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3641      * greater than or equal to a constant value.
3642      *
3643      * @param op1
3644      *            the {@code ObservableNumberValue}
3645      * @param op2
3646      *            the constant value
3647      * @return the new {@code BooleanBinding}
3648      * @throws NullPointerException
3649      *             if the {@code ObservableNumberValue} is {@code null}
3650      */
3651     public static BooleanBinding greaterThanOrEqual(final ObservableNumberValue op1, final double op2) {
3652         return greaterThanOrEqual(op1, DoubleConstant.valueOf(op2), op1);
3653     }
3654 
3655     /**
3656      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3657      * if a constant value is greater than or equal to the value of a
3658      * {@link javafx.beans.value.ObservableNumberValue}.
3659      *
3660      * @param op1
3661      *            the constant value
3662      * @param op2
3663      *            the {@code ObservableNumberValue}
3664      * @return the new {@code BooleanBinding}
3665      * @throws NullPointerException
3666      *             if the {@code ObservableNumberValue} is {@code null}
3667      */
3668     public static BooleanBinding greaterThanOrEqual(final double op1, final ObservableNumberValue op2) {
3669         return greaterThanOrEqual(DoubleConstant.valueOf(op1), op2, op2);
3670     }
3671 
3672     /**
3673      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3674      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3675      * greater than or equal to a constant value.
3676      *
3677      * @param op1
3678      *            the {@code ObservableNumberValue}
3679      * @param op2
3680      *            the constant value
3681      * @return the new {@code BooleanBinding}
3682      * @throws NullPointerException
3683      *             if the {@code ObservableNumberValue} is {@code null}
3684      */
3685     public static BooleanBinding greaterThanOrEqual(final ObservableNumberValue op1, final float op2) {
3686         return greaterThanOrEqual(op1, FloatConstant.valueOf(op2), op1);
3687     }
3688 
3689     /**
3690      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3691      * if a constant value is greater than or equal to the value of a
3692      * {@link javafx.beans.value.ObservableNumberValue}.
3693      *
3694      * @param op1
3695      *            the constant value
3696      * @param op2
3697      *            the {@code ObservableNumberValue}
3698      * @return the new {@code BooleanBinding}
3699      * @throws NullPointerException
3700      *             if the {@code ObservableNumberValue} is {@code null}
3701      */
3702     public static BooleanBinding greaterThanOrEqual(final float op1, final ObservableNumberValue op2) {
3703         return greaterThanOrEqual(FloatConstant.valueOf(op1), op2, op2);
3704     }
3705 
3706     /**
3707      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3708      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3709      * greater than or equal to a constant value.
3710      *
3711      * @param op1
3712      *            the {@code ObservableNumberValue}
3713      * @param op2
3714      *            the constant value
3715      * @return the new {@code BooleanBinding}
3716      * @throws NullPointerException
3717      *             if the {@code ObservableNumberValue} is {@code null}
3718      */
3719     public static BooleanBinding greaterThanOrEqual(final ObservableNumberValue op1, final long op2) {
3720         return greaterThanOrEqual(op1, LongConstant.valueOf(op2), op1);
3721     }
3722 
3723     /**
3724      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3725      * if a constant value is greater than or equal to the value of a
3726      * {@link javafx.beans.value.ObservableNumberValue}.
3727      *
3728      * @param op1
3729      *            the constant value
3730      * @param op2
3731      *            the {@code ObservableNumberValue}
3732      * @return the new {@code BooleanBinding}
3733      * @throws NullPointerException
3734      *             if the {@code ObservableNumberValue} is {@code null}
3735      */
3736     public static BooleanBinding greaterThanOrEqual(final long op1, final ObservableNumberValue op2) {
3737         return greaterThanOrEqual(LongConstant.valueOf(op1), op2, op2);
3738     }
3739 
3740     /**
3741      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3742      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3743      * greater than or equal to a constant value.
3744      *
3745      * @param op1
3746      *            the {@code ObservableNumberValue}
3747      * @param op2
3748      *            the constant value
3749      * @return the new {@code BooleanBinding}
3750      * @throws NullPointerException
3751      *             if the {@code ObservableNumberValue} is {@code null}
3752      */
3753     public static BooleanBinding greaterThanOrEqual(final ObservableNumberValue op1, final int op2) {
3754         return greaterThanOrEqual(op1, IntegerConstant.valueOf(op2), op1);
3755     }
3756 
3757     /**
3758      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3759      * if a constant value is greater than or equal to the value of a
3760      * {@link javafx.beans.value.ObservableNumberValue}.
3761      *
3762      * @param op1
3763      *            the constant value
3764      * @param op2
3765      *            the {@code ObservableNumberValue}
3766      * @return the new {@code BooleanBinding}
3767      * @throws NullPointerException
3768      *             if the {@code ObservableNumberValue} is {@code null}
3769      */
3770     public static BooleanBinding greaterThanOrEqual(final int op1, final ObservableNumberValue op2) {
3771         return greaterThanOrEqual(IntegerConstant.valueOf(op1), op2, op2);
3772     }
3773 
3774     // =================================================================================================================
3775     // Less Than or Equal
3776 
3777     private static BooleanBinding lessThanOrEqual(final ObservableNumberValue op1, final ObservableNumberValue op2, Observable... dependencies) {
3778         return greaterThanOrEqual(op2, op1, dependencies);
3779     }
3780 
3781 
3782     /**
3783      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3784      * if the value of the first
3785      * {@link javafx.beans.value.ObservableNumberValue} is less than or equal to
3786      * the value of the second.
3787      *
3788      * @param op1
3789      *            the first operand
3790      * @param op2
3791      *            the second operand
3792      * @return the new {@code BooleanBinding}
3793      * @throws NullPointerException
3794      *             if one of the operands is {@code null}
3795      */
3796     public static BooleanBinding lessThanOrEqual(final ObservableNumberValue op1, final ObservableNumberValue op2) {
3797         return lessThanOrEqual(op1, op2, op1, op2);
3798     }
3799 
3800     /**
3801      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3802      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3803      * less than or equal to a constant value.
3804      *
3805      * @param op1
3806      *            the {@code ObservableNumberValue}
3807      * @param op2
3808      *            the constant value
3809      * @return the new {@code BooleanBinding}
3810      * @throws NullPointerException
3811      *             if the {@code ObservableNumberValue} is {@code null}
3812      */
3813     public static BooleanBinding lessThanOrEqual(final ObservableNumberValue op1, final double op2) {
3814         return lessThanOrEqual(op1, DoubleConstant.valueOf(op2), op1);
3815     }
3816 
3817     /**
3818      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3819      * if a constant value is less than or equal to the value of a
3820      * {@link javafx.beans.value.ObservableNumberValue}.
3821      *
3822      * @param op1
3823      *            the constant value
3824      * @param op2
3825      *            the {@code ObservableNumberValue}
3826      * @return the new {@code BooleanBinding}
3827      * @throws NullPointerException
3828      *             if the {@code ObservableNumberValue} is {@code null}
3829      */
3830     public static BooleanBinding lessThanOrEqual(final double op1, final ObservableNumberValue op2) {
3831         return lessThanOrEqual(DoubleConstant.valueOf(op1), op2, op2);
3832     }
3833 
3834     /**
3835      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3836      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3837      * less than or equal to a constant value.
3838      *
3839      * @param op1
3840      *            the {@code ObservableNumberValue}
3841      * @param op2
3842      *            the constant value
3843      * @return the new {@code BooleanBinding}
3844      * @throws NullPointerException
3845      *             if the {@code ObservableNumberValue} is {@code null}
3846      */
3847     public static BooleanBinding lessThanOrEqual(final ObservableNumberValue op1, final float op2) {
3848         return lessThanOrEqual(op1, FloatConstant.valueOf(op2), op1);
3849     }
3850 
3851     /**
3852      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3853      * if a constant value is less than or equal to the value of a
3854      * {@link javafx.beans.value.ObservableNumberValue}.
3855      *
3856      * @param op1
3857      *            the constant value
3858      * @param op2
3859      *            the {@code ObservableNumberValue}
3860      * @return the new {@code BooleanBinding}
3861      * @throws NullPointerException
3862      *             if the {@code ObservableNumberValue} is {@code null}
3863      */
3864     public static BooleanBinding lessThanOrEqual(final float op1, final ObservableNumberValue op2) {
3865         return lessThanOrEqual(FloatConstant.valueOf(op1), op2, op2);
3866     }
3867 
3868     /**
3869      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3870      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3871      * less than or equal to a constant value.
3872      *
3873      * @param op1
3874      *            the {@code ObservableNumberValue}
3875      * @param op2
3876      *            the constant value
3877      * @return the new {@code BooleanBinding}
3878      * @throws NullPointerException
3879      *             if the {@code ObservableNumberValue} is {@code null}
3880      */
3881     public static BooleanBinding lessThanOrEqual(final ObservableNumberValue op1, final long op2) {
3882         return lessThanOrEqual(op1, LongConstant.valueOf(op2), op1);
3883     }
3884 
3885     /**
3886      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3887      * if a constant value is less than or equal to the value of a
3888      * {@link javafx.beans.value.ObservableNumberValue}.
3889      *
3890      * @param op1
3891      *            the constant value
3892      * @param op2
3893      *            the {@code ObservableNumberValue}
3894      * @return the new {@code BooleanBinding}
3895      * @throws NullPointerException
3896      *             if the {@code ObservableNumberValue} is {@code null}
3897      */
3898     public static BooleanBinding lessThanOrEqual(final long op1, final ObservableNumberValue op2) {
3899         return lessThanOrEqual(LongConstant.valueOf(op1), op2, op2);
3900     }
3901 
3902     /**
3903      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3904      * if the value of a {@link javafx.beans.value.ObservableNumberValue} is
3905      * less than or equal to a constant value.
3906      *
3907      * @param op1
3908      *            the {@code ObservableNumberValue}
3909      * @param op2
3910      *            the constant value
3911      * @return the new {@code BooleanBinding}
3912      * @throws NullPointerException
3913      *             if the {@code ObservableNumberValue} is {@code null}
3914      */
3915     public static BooleanBinding lessThanOrEqual(final ObservableNumberValue op1, final int op2) {
3916         return lessThanOrEqual(op1, IntegerConstant.valueOf(op2), op1);
3917     }
3918 
3919     /**
3920      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
3921      * if a constant value is less than or equal to the value of a
3922      * {@link javafx.beans.value.ObservableNumberValue}.
3923      *
3924      * @param op1
3925      *            the constant value
3926      * @param op2
3927      *            the {@code ObservableNumberValue}
3928      * @return the new {@code BooleanBinding}
3929      * @throws NullPointerException
3930      *             if the {@code ObservableNumberValue} is {@code null}
3931      */
3932     public static BooleanBinding lessThanOrEqual(final int op1, final ObservableNumberValue op2) {
3933         return lessThanOrEqual(IntegerConstant.valueOf(op1), op2, op2);
3934     }
3935 
3936     // =================================================================================================================
3937     // Minimum
3938 
3939     private static NumberBinding min(final ObservableNumberValue op1, final ObservableNumberValue op2, final Observable... dependencies) {
3940         if ((op1 == null) || (op2 == null)) {
3941             throw new NullPointerException("Operands cannot be null.");
3942         }
3943         assert (dependencies != null) && (dependencies.length > 0);
3944 
3945         if ((op1 instanceof ObservableDoubleValue) || (op2 instanceof ObservableDoubleValue)) {
3946             return new DoubleBinding() {
3947                 {
3948                     super.bind(dependencies);
3949                 }
3950 
3951                 @Override
3952                 public void dispose() {
3953                     super.unbind(dependencies);
3954                 }
3955 
3956                 @Override
3957                 protected double computeValue() {
3958                     return Math.min(op1.doubleValue(), op2.doubleValue());
3959                 }
3960 
3961                 @Override
3962                 public ObservableList<?> getDependencies() {
3963                     return (dependencies.length == 1)?
3964                             FXCollections.singletonObservableList(dependencies[0])
3965                             : new ImmutableObservableList<Observable>(dependencies);
3966                 }
3967             };
3968         } else if ((op1 instanceof ObservableFloatValue) || (op2 instanceof ObservableFloatValue)) {
3969             return new FloatBinding() {
3970                 {
3971                     super.bind(dependencies);
3972                 }
3973 
3974                 @Override
3975                 public void dispose() {
3976                     super.unbind(dependencies);
3977                 }
3978 
3979                 @Override
3980                 protected float computeValue() {
3981                     return Math.min(op1.floatValue(), op2.floatValue());
3982                 }
3983 
3984                 @Override
3985                 public ObservableList<?> getDependencies() {
3986                     return (dependencies.length == 1)?
3987                             FXCollections.singletonObservableList(dependencies[0])
3988                             : new ImmutableObservableList<Observable>(dependencies);
3989                 }
3990             };
3991         } else if ((op1 instanceof ObservableLongValue) || (op2 instanceof ObservableLongValue)) {
3992             return new LongBinding() {
3993                 {
3994                     super.bind(dependencies);
3995                 }
3996 
3997                 @Override
3998                 public void dispose() {
3999                     super.unbind(dependencies);
4000                 }
4001 
4002                 @Override
4003                 protected long computeValue() {
4004                     return Math.min(op1.longValue(), op2.longValue());
4005                 }
4006 
4007                 @Override
4008                 public ObservableList<?> getDependencies() {
4009                     return (dependencies.length == 1)?
4010                             FXCollections.singletonObservableList(dependencies[0])
4011                             : new ImmutableObservableList<Observable>(dependencies);
4012                 }
4013             };
4014         } else {
4015             return new IntegerBinding() {
4016                 {
4017                     super.bind(dependencies);
4018                 }
4019 
4020                 @Override
4021                 public void dispose() {
4022                     super.unbind(dependencies);
4023                 }
4024 
4025                 @Override
4026                 protected int computeValue() {
4027                     return Math.min(op1.intValue(), op2.intValue());
4028                 }
4029 
4030                 @Override
4031                 public ObservableList<?> getDependencies() {
4032                     return (dependencies.length == 1)?
4033                             FXCollections.singletonObservableList(dependencies[0])
4034                             : new ImmutableObservableList<Observable>(dependencies);
4035                 }
4036             };
4037         }
4038     }
4039 
4040     /**
4041      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4042      * the minimum of the values of two instances of
4043      * {@link javafx.beans.value.ObservableNumberValue}.
4044      *
4045      * @param op1
4046      *            the first operand
4047      * @param op2
4048      *            the second operand
4049      * @return the new {@code NumberBinding}
4050      * @throws NullPointerException
4051      *             if one of the operands is {@code null}
4052      */
4053     public static NumberBinding min(final ObservableNumberValue op1, final ObservableNumberValue op2) {
4054         return min(op1, op2, op1, op2);
4055     }
4056 
4057     /**
4058      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
4059      * the minimum of the value of a
4060      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4061      *
4062      * @param op1
4063      *            the {@code ObservableNumberValue}
4064      * @param op2
4065      *            the constant value
4066      * @return the new {@code DoubleBinding}
4067      * @throws NullPointerException
4068      *             if the {@code ObservableNumberValue} is {@code null}
4069      */
4070     public static DoubleBinding min(final ObservableNumberValue op1, final double op2) {
4071         return (DoubleBinding) min(op1, DoubleConstant.valueOf(op2), op1);
4072     }
4073 
4074     /**
4075      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
4076      * the minimum of the value of a
4077      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4078      *
4079      * @param op1
4080      *            the constant value
4081      * @param op2
4082      *            the {@code ObservableNumberValue}
4083      * @return the new {@code DoubleBinding}
4084      * @throws NullPointerException
4085      *             if the {@code ObservableNumberValue} is {@code null}
4086      */
4087     public static DoubleBinding min(final double op1, final ObservableNumberValue op2) {
4088         return (DoubleBinding) min(DoubleConstant.valueOf(op1), op2, op2);
4089     }
4090 
4091     /**
4092      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4093      * the minimum of the value of a
4094      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4095      *
4096      * @param op1
4097      *            the {@code ObservableNumberValue}
4098      * @param op2
4099      *            the constant value
4100      * @return the new {@code NumberBinding}
4101      * @throws NullPointerException
4102      *             if the {@code ObservableNumberValue} is {@code null}
4103      */
4104     public static NumberBinding min(final ObservableNumberValue op1, final float op2) {
4105         return min(op1, FloatConstant.valueOf(op2), op1);
4106     }
4107 
4108     /**
4109      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4110      * the minimum of the value of a
4111      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4112      *
4113      * @param op1
4114      *            the constant value
4115      * @param op2
4116      *            the {@code ObservableNumberValue}
4117      * @return the new {@code NumberBinding}
4118      * @throws NullPointerException
4119      *             if the {@code ObservableNumberValue} is {@code null}
4120      */
4121     public static NumberBinding min(final float op1, final ObservableNumberValue op2) {
4122         return min(FloatConstant.valueOf(op1), op2, op2);
4123     }
4124 
4125     /**
4126      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4127      * the minimum of the value of a
4128      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4129      *
4130      * @param op1
4131      *            the {@code ObservableNumberValue}
4132      * @param op2
4133      *            the constant value
4134      * @return the new {@code NumberBinding}
4135      * @throws NullPointerException
4136      *             if the {@code ObservableNumberValue} is {@code null}
4137      */
4138     public static NumberBinding min(final ObservableNumberValue op1, final long op2) {
4139         return min(op1, LongConstant.valueOf(op2), op1);
4140     }
4141 
4142     /**
4143      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4144      * the minimum of the value of a
4145      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4146      *
4147      * @param op1
4148      *            the constant value
4149      * @param op2
4150      *            the {@code ObservableNumberValue}
4151      * @return the new {@code NumberBinding}
4152      * @throws NullPointerException
4153      *             if the {@code ObservableNumberValue} is {@code null}
4154      */
4155     public static NumberBinding min(final long op1, final ObservableNumberValue op2) {
4156         return min(LongConstant.valueOf(op1), op2, op2);
4157     }
4158 
4159     /**
4160      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4161      * the minimum of the value of a
4162      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4163      *
4164      * @param op1
4165      *            the {@code ObservableNumberValue}
4166      * @param op2
4167      *            the constant value
4168      * @return the new {@code NumberBinding}
4169      * @throws NullPointerException
4170      *             if the {@code ObservableNumberValue} is {@code null}
4171      */
4172     public static NumberBinding min(final ObservableNumberValue op1, final int op2) {
4173         return min(op1, IntegerConstant.valueOf(op2), op1);
4174     }
4175 
4176     /**
4177      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4178      * the minimum of the value of a
4179      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4180      *
4181      * @param op1
4182      *            the constant value
4183      * @param op2
4184      *            the {@code ObservableNumberValue}
4185      * @return the new {@code NumberBinding}
4186      * @throws NullPointerException
4187      *             if the {@code ObservableNumberValue} is {@code null}
4188      */
4189     public static NumberBinding min(final int op1, final ObservableNumberValue op2) {
4190         return min(IntegerConstant.valueOf(op1), op2, op2);
4191     }
4192 
4193     // =================================================================================================================
4194     // Maximum
4195 
4196     private static NumberBinding max(final ObservableNumberValue op1, final ObservableNumberValue op2, final Observable... dependencies) {
4197         if ((op1 == null) || (op2 == null)) {
4198             throw new NullPointerException("Operands cannot be null.");
4199         }
4200         assert (dependencies != null) && (dependencies.length > 0);
4201 
4202         if ((op1 instanceof ObservableDoubleValue) || (op2 instanceof ObservableDoubleValue)) {
4203             return new DoubleBinding() {
4204                 {
4205                     super.bind(dependencies);
4206                 }
4207 
4208                 @Override
4209                 public void dispose() {
4210                     super.unbind(dependencies);
4211                 }
4212 
4213                 @Override
4214                 protected double computeValue() {
4215                     return Math.max(op1.doubleValue(), op2.doubleValue());
4216                 }
4217 
4218                 @Override
4219                 public ObservableList<?> getDependencies() {
4220                     return (dependencies.length == 1)?
4221                             FXCollections.singletonObservableList(dependencies[0])
4222                             : new ImmutableObservableList<Observable>(dependencies);
4223                 }
4224             };
4225         } else if ((op1 instanceof ObservableFloatValue) || (op2 instanceof ObservableFloatValue)) {
4226             return new FloatBinding() {
4227                 {
4228                     super.bind(dependencies);
4229                 }
4230 
4231                 @Override
4232                 public void dispose() {
4233                     super.unbind(dependencies);
4234                 }
4235 
4236                 @Override
4237                 protected float computeValue() {
4238                     return Math.max(op1.floatValue(), op2.floatValue());
4239                 }
4240 
4241                 @Override
4242                 public ObservableList<?> getDependencies() {
4243                     return (dependencies.length == 1)?
4244                             FXCollections.singletonObservableList(dependencies[0])
4245                             : new ImmutableObservableList<Observable>(dependencies);
4246                 }
4247             };
4248         } else if ((op1 instanceof ObservableLongValue) || (op2 instanceof ObservableLongValue)) {
4249             return new LongBinding() {
4250                 {
4251                     super.bind(dependencies);
4252                 }
4253 
4254                 @Override
4255                 public void dispose() {
4256                     super.unbind(dependencies);
4257                 }
4258 
4259                 @Override
4260                 protected long computeValue() {
4261                     return Math.max(op1.longValue(), op2.longValue());
4262                 }
4263 
4264                 @Override
4265                 public ObservableList<?> getDependencies() {
4266                     return (dependencies.length == 1)?
4267                             FXCollections.singletonObservableList(dependencies[0])
4268                             : new ImmutableObservableList<Observable>(dependencies);
4269                 }
4270             };
4271         } else {
4272             return new IntegerBinding() {
4273                 {
4274                     super.bind(dependencies);
4275                 }
4276 
4277                 @Override
4278                 public void dispose() {
4279                     super.unbind(dependencies);
4280                 }
4281 
4282                 @Override
4283                 protected int computeValue() {
4284                     return Math.max(op1.intValue(), op2.intValue());
4285                 }
4286 
4287                 @Override
4288                 public ObservableList<?> getDependencies() {
4289                     return (dependencies.length == 1)?
4290                             FXCollections.singletonObservableList(dependencies[0])
4291                             : new ImmutableObservableList<Observable>(dependencies);
4292                 }
4293             };
4294         }
4295     }
4296 
4297     /**
4298      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4299      * the maximum of the values of two instances of
4300      * {@link javafx.beans.value.ObservableNumberValue}.
4301      *
4302      * @param op1
4303      *            the first operand
4304      * @param op2
4305      *            the second operand
4306      * @return the new {@code NumberBinding}
4307      * @throws NullPointerException
4308      *             if one of the operands is {@code null}
4309      */
4310     public static NumberBinding max(final ObservableNumberValue op1, final ObservableNumberValue op2) {
4311         return max(op1, op2, op1, op2);
4312     }
4313 
4314     /**
4315      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
4316      * the maximum of the value of a
4317      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4318      *
4319      * @param op1
4320      *            the {@code ObservableNumberValue}
4321      * @param op2
4322      *            the constant value
4323      * @return the new {@code DoubleBinding}
4324      * @throws NullPointerException
4325      *             if the {@code ObservableNumberValue} is {@code null}
4326      */
4327     public static DoubleBinding max(final ObservableNumberValue op1, final double op2) {
4328         return (DoubleBinding) max(op1, DoubleConstant.valueOf(op2), op1);
4329     }
4330 
4331     /**
4332      * Creates a new {@link javafx.beans.binding.DoubleBinding} that calculates
4333      * the maximum of the value of a
4334      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4335      *
4336      * @param op1
4337      *            the constant value
4338      * @param op2
4339      *            the {@code ObservableNumberValue}
4340      * @return the new {@code DoubleBinding}
4341      * @throws NullPointerException
4342      *             if the {@code ObservableNumberValue} is {@code null}
4343      */
4344     public static DoubleBinding max(final double op1, final ObservableNumberValue op2) {
4345         return (DoubleBinding) max(DoubleConstant.valueOf(op1), op2, op2);
4346     }
4347 
4348     /**
4349      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4350      * the maximum of the value of a
4351      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4352      *
4353      * @param op1
4354      *            the {@code ObservableNumberValue}
4355      * @param op2
4356      *            the constant value
4357      * @return the new {@code NumberBinding}
4358      * @throws NullPointerException
4359      *             if the {@code ObservableNumberValue} is {@code null}
4360      */
4361     public static NumberBinding max(final ObservableNumberValue op1, final float op2) {
4362         return max(op1, FloatConstant.valueOf(op2), op1);
4363     }
4364 
4365     /**
4366      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4367      * the maximum of the value of a
4368      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4369      *
4370      * @param op1
4371      *            the constant value
4372      * @param op2
4373      *            the {@code ObservableNumberValue}
4374      * @return the new {@code NumberBinding}
4375      * @throws NullPointerException
4376      *             if the {@code ObservableNumberValue} is {@code null}
4377      */
4378     public static NumberBinding max(final float op1, final ObservableNumberValue op2) {
4379         return max(FloatConstant.valueOf(op1), op2, op2);
4380     }
4381 
4382     /**
4383      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4384      * the maximum of the value of a
4385      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4386      *
4387      * @param op1
4388      *            the {@code ObservableNumberValue}
4389      * @param op2
4390      *            the constant value
4391      * @return the new {@code NumberBinding}
4392      * @throws NullPointerException
4393      *             if the {@code ObservableNumberValue} is {@code null}
4394      */
4395     public static NumberBinding max(final ObservableNumberValue op1, final long op2) {
4396         return max(op1, LongConstant.valueOf(op2), op1);
4397     }
4398 
4399     /**
4400      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4401      * the maximum of the value of a
4402      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4403      *
4404      * @param op1
4405      *            the constant value
4406      * @param op2
4407      *            the {@code ObservableNumberValue}
4408      * @return the new {@code NumberBinding}
4409      * @throws NullPointerException
4410      *             if the {@code ObservableNumberValue} is {@code null}
4411      */
4412     public static NumberBinding max(final long op1, final ObservableNumberValue op2) {
4413         return max(LongConstant.valueOf(op1), op2, op2);
4414     }
4415 
4416     /**
4417      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4418      * the maximum of the value of a
4419      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4420      *
4421      * @param op1
4422      *            the {@code ObservableNumberValue}
4423      * @param op2
4424      *            the constant value
4425      * @return the new {@code NumberBinding}
4426      * @throws NullPointerException
4427      *             if the {@code ObservableNumberValue} is {@code null}
4428      */
4429     public static NumberBinding max(final ObservableNumberValue op1, final int op2) {
4430         return max(op1, IntegerConstant.valueOf(op2), op1);
4431     }
4432 
4433     /**
4434      * Creates a new {@link javafx.beans.binding.NumberBinding} that calculates
4435      * the maximum of the value of a
4436      * {@link javafx.beans.value.ObservableNumberValue} and a constant value.
4437      *
4438      * @param op1
4439      *            the constant value
4440      * @param op2
4441      *            the {@code ObservableNumberValue}
4442      * @return the new {@code NumberBinding}
4443      * @throws NullPointerException
4444      *             if the {@code ObservableNumberValue} is {@code null}
4445      */
4446     public static NumberBinding max(final int op1, final ObservableNumberValue op2) {
4447         return max(IntegerConstant.valueOf(op1), op2, op2);
4448     }
4449 
4450     // boolean
4451     // =================================================================================================================
4452 
4453      private static class BooleanAndBinding extends BooleanBinding {
4454 
4455         private final ObservableBooleanValue op1;
4456         private final ObservableBooleanValue op2;
4457         private final InvalidationListener observer;
4458 
4459         public BooleanAndBinding(ObservableBooleanValue op1, ObservableBooleanValue op2) {
4460             this.op1 = op1;
4461             this.op2 = op2;
4462 
4463             observer = new ShortCircuitAndInvalidator(this);
4464 
4465             op1.addListener(observer);
4466             op2.addListener(observer);
4467         }
4468 
4469 
4470         @Override
4471         public void dispose() {
4472             op1.removeListener(observer);
4473             op2.removeListener(observer);
4474         }
4475 
4476         @Override
4477         protected boolean computeValue() {
4478             return op1.get() && op2.get();
4479         }
4480 
4481         @Override
4482         public ObservableList<?> getDependencies() {
4483             return new ImmutableObservableList<>(op1, op2);
4484         }
4485     }
4486 
4487     private static class ShortCircuitAndInvalidator implements InvalidationListener {
4488 
4489         private final WeakReference<BooleanAndBinding> ref;
4490 
4491         private ShortCircuitAndInvalidator(BooleanAndBinding binding) {
4492             assert binding != null;
4493             ref = new WeakReference<>(binding);
4494         }
4495 
4496         @Override
4497         public void invalidated(Observable observable) {
4498             final BooleanAndBinding binding = ref.get();
4499             if (binding == null) {
4500                 observable.removeListener(this);
4501             } else {
4502                 // short-circuit invalidation. This BooleanBinding becomes
4503                 // only invalid if the first operator changes or the
4504                 // first parameter is true.
4505                 if ((binding.op1.equals(observable) || (binding.isValid() && binding.op1.get()))) {
4506                     binding.invalidate();
4507                 }
4508             }
4509         }
4510 
4511     }
4512 
4513     /**
4514      * Creates a {@link BooleanBinding} that calculates the conditional-AND
4515      * operation on the value of two instance of
4516      * {@link javafx.beans.value.ObservableBooleanValue}.
4517      *
4518      * @param op1
4519      *            first {@code ObservableBooleanValue}
4520      * @param op2
4521      *            second {@code ObservableBooleanValue}
4522      * @return the new {@code BooleanBinding}
4523      * @throws NullPointerException
4524      *             if one of the operands is {@code null}
4525      */
4526     public static BooleanBinding and(final ObservableBooleanValue op1, final ObservableBooleanValue op2) {
4527         if ((op1 == null) || (op2 == null)) {
4528             throw new NullPointerException("Operands cannot be null.");
4529         }
4530 
4531         return new BooleanAndBinding(op1, op2);
4532     }
4533 
4534     private static class BooleanOrBinding extends BooleanBinding {
4535 
4536         private final ObservableBooleanValue op1;
4537         private final ObservableBooleanValue op2;
4538         private final InvalidationListener observer;
4539 
4540         public BooleanOrBinding(ObservableBooleanValue op1, ObservableBooleanValue op2) {
4541             this.op1 = op1;
4542             this.op2 = op2;
4543             observer = new ShortCircuitOrInvalidator(this);
4544             op1.addListener(observer);
4545             op2.addListener(observer);
4546         }
4547 
4548 
4549         @Override
4550         public void dispose() {
4551             op1.removeListener(observer);
4552             op2.removeListener(observer);
4553         }
4554 
4555         @Override
4556         protected boolean computeValue() {
4557             return op1.get() || op2.get();
4558         }
4559 
4560         @Override
4561         public ObservableList<?> getDependencies() {
4562             return new ImmutableObservableList<>(op1, op2);
4563         }
4564     }
4565 
4566 
4567     private static class ShortCircuitOrInvalidator implements InvalidationListener {
4568 
4569         private final WeakReference<BooleanOrBinding> ref;
4570 
4571         private ShortCircuitOrInvalidator(BooleanOrBinding binding) {
4572             assert binding != null;
4573             ref = new WeakReference<>(binding);
4574         }
4575 
4576         @Override
4577         public void invalidated(Observable observable) {
4578             final BooleanOrBinding binding = ref.get();
4579             if (binding == null) {
4580                 observable.removeListener(this);
4581             } else {
4582                 // short circuit invalidation. This BooleanBinding becomes
4583                 // only invalid if the first operator changes or the
4584                 // first parameter is false.
4585                 if ((binding.op1.equals(observable) || (binding.isValid() && !binding.op1.get()))) {
4586                     binding.invalidate();
4587                 }
4588             }
4589         }
4590 
4591     }
4592 
4593     /**
4594      * Creates a {@link BooleanBinding} that calculates the conditional-OR
4595      * operation on the value of two instance of
4596      * {@link javafx.beans.value.ObservableBooleanValue}.
4597      *
4598      * @param op1
4599      *            first {@code ObservableBooleanValue}
4600      * @param op2
4601      *            second {@code ObservableBooleanValue}
4602      * @return the new {@code BooleanBinding}
4603      * @throws NullPointerException
4604      *             if one of the operands is {@code null}
4605      */
4606     public static BooleanBinding or(final ObservableBooleanValue op1, final ObservableBooleanValue op2) {
4607         if ((op1 == null) || (op2 == null)) {
4608             throw new NullPointerException("Operands cannot be null.");
4609         }
4610 
4611         return new BooleanOrBinding(op1, op2);
4612     }
4613 
4614     /**
4615      * Creates a {@link BooleanBinding} that calculates the inverse of the value
4616      * of a {@link javafx.beans.value.ObservableBooleanValue}.
4617      *
4618      * @param op
4619      *            the {@code ObservableBooleanValue}
4620      * @return the new {@code BooleanBinding}
4621      * @throws NullPointerException
4622      *             if the operand is {@code null}
4623      */
4624     public static BooleanBinding not(final ObservableBooleanValue op) {
4625         if (op == null) {
4626             throw new NullPointerException("Operand cannot be null.");
4627         }
4628 
4629         return new BooleanBinding() {
4630             {
4631                 super.bind(op);
4632             }
4633 
4634             @Override
4635             public void dispose() {
4636                 super.unbind(op);
4637             }
4638 
4639             @Override
4640             protected boolean computeValue() {
4641                 return !op.get();
4642             }
4643 
4644             @Override
4645             public ObservableList<?> getDependencies() {
4646                 return FXCollections.singletonObservableList(op);
4647             }
4648         };
4649     }
4650 
4651     /**
4652      * Creates a new {@link BooleanBinding} that holds {@code true} if the values of two
4653      * instances of {@link javafx.beans.value.ObservableBooleanValue} are equal.
4654      *
4655      * @param op1
4656      *            the first operand
4657      * @param op2
4658      *            the second operand
4659      * @return the new {@code BooleanBinding}
4660      * @throws NullPointerException
4661      *             if one of the operands is {@code null}
4662      */
4663     public static BooleanBinding equal(final ObservableBooleanValue op1, final ObservableBooleanValue op2) {
4664         if ((op1 == null) || (op2 == null)) {
4665             throw new NullPointerException("Operands cannot be null.");
4666         }
4667 
4668         return new BooleanBinding() {
4669             {
4670                 super.bind(op1, op2);
4671             }
4672 
4673             @Override
4674             public void dispose() {
4675                 super.unbind(op1, op2);
4676             }
4677 
4678             @Override
4679             protected boolean computeValue() {
4680                 return op1.get() == op2.get();
4681             }
4682 
4683             @Override
4684             public ObservableList<?> getDependencies() {
4685                 return new ImmutableObservableList<ObservableBooleanValue>(op1, op2);
4686             }
4687         };
4688     }
4689 
4690     /**
4691      * Creates a new {@link BooleanBinding} that holds {@code true} if the values of two
4692      * instances of {@link javafx.beans.value.ObservableBooleanValue} are not
4693      * equal.
4694      *
4695      * @param op1
4696      *            the first operand
4697      * @param op2
4698      *            the second operand
4699      * @return the new {@code BooleanBinding}
4700      * @throws NullPointerException
4701      *             if one of the operands is {@code null}
4702      */
4703     public static BooleanBinding notEqual(final ObservableBooleanValue op1, final ObservableBooleanValue op2) {
4704         if ((op1 == null) || (op2 == null)) {
4705             throw new NullPointerException("Operands cannot be null.");
4706         }
4707 
4708         return new BooleanBinding() {
4709             {
4710                 super.bind(op1, op2);
4711             }
4712 
4713             @Override
4714             public void dispose() {
4715                 super.unbind(op1, op2);
4716             }
4717 
4718             @Override
4719             protected boolean computeValue() {
4720                 return op1.get() != op2.get();
4721             }
4722 
4723             @Override
4724             public ObservableList<?> getDependencies() {
4725                 return new ImmutableObservableList<ObservableBooleanValue>(op1, op2);
4726             }
4727         };
4728     }
4729 
4730     // String
4731     // =================================================================================================================
4732 
4733     /**
4734      * Returns a {@link javafx.beans.binding.StringExpression} that wraps a
4735      * {@link javafx.beans.value.ObservableValue}. If the
4736      * {@code ObservableValue} is already a {@code StringExpression}, it will be
4737      * returned. Otherwise a new {@link javafx.beans.binding.StringBinding} is
4738      * created that holds the value of the {@code ObservableValue} converted to
4739      * a {@code String}.
4740      *
4741      * @param observableValue
4742      *            The source {@code ObservableValue}
4743      * @return A {@code StringExpression} that wraps the {@code ObservableValue}
4744      *         if necessary
4745      * @throws NullPointerException
4746      *             if {@code observableValue} is {@code null}
4747      */
4748     public static StringExpression convert(ObservableValue<?> observableValue) {
4749         return StringFormatter.convert(observableValue);
4750     }
4751 
4752     /**
4753      * Returns a {@link javafx.beans.binding.StringExpression} that holds the
4754      * value of the concatenation of multiple {@code Objects}.
4755      * <p>
4756      * If one of the arguments implements
4757      * {@link javafx.beans.value.ObservableValue} and the value of this
4758      * {@code ObservableValue} changes, the change is automatically reflected in
4759      * the {@code StringExpression}.
4760      * <p>
4761      * If {@code null} or an empty array is passed to this method, a
4762      * {@code StringExpression} that contains an empty {@code String} is
4763      * returned
4764      *
4765      * @param args
4766      *            the {@code Objects} that should be concatenated
4767      * @return the new {@code StringExpression}
4768      */
4769     public static StringExpression concat(Object... args) {
4770         return StringFormatter.concat(args);
4771     }
4772 
4773     /**
4774      * Creates a {@link javafx.beans.binding.StringExpression} that holds the
4775      * value of multiple {@code Objects} formatted according to a format
4776      * {@code String}.
4777      * <p>
4778      * If one of the arguments implements
4779      * {@link javafx.beans.value.ObservableValue} and the value of this
4780      * {@code ObservableValue} changes, the change is automatically reflected in
4781      * the {@code StringExpression}.
4782      * <p>
4783      * See {@code java.util.Formatter} for formatting rules.
4784      *
4785      * @param format
4786      *            the formatting {@code String}
4787      * @param args
4788      *            the {@code Objects} that should be inserted in the formatting
4789      *            {@code String}
4790      * @return the new {@code StringExpression}
4791      */
4792     public static StringExpression format(String format, Object... args) {
4793         return StringFormatter.format(format, args);
4794     }
4795 
4796     /**
4797      * Creates a {@link javafx.beans.binding.StringExpression} that holds the
4798      * value of multiple {@code Objects} formatted according to a format
4799      * {@code String} and a specified {@code Locale}
4800      * <p>
4801      * If one of the arguments implements
4802      * {@link javafx.beans.value.ObservableValue} and the value of this
4803      * {@code ObservableValue} changes, the change is automatically reflected in
4804      * the {@code StringExpression}.
4805      * <p>
4806      * See {@code java.util.Formatter} for formatting rules. See
4807      * {@code java.util.Locale} for details on {@code Locale}.
4808      *
4809      * @param locale
4810      *            the {@code Locale} to use during formatting
4811      * @param format
4812      *            the formatting {@code String}
4813      * @param args
4814      *            the {@code Objects} that should be inserted in the formatting
4815      *            {@code String}
4816      * @return the new {@code StringExpression}
4817      */
4818     public static StringExpression format(Locale locale, String format,
4819             Object... args) {
4820         return StringFormatter.format(locale, format, args);
4821     }
4822 
4823     private static String getStringSafe(String value) {
4824         return value == null ? "" : value;
4825     }
4826 
4827     private static BooleanBinding equal(final ObservableStringValue op1, final ObservableStringValue op2, final Observable... dependencies) {
4828         if ((op1 == null) || (op2 == null)) {
4829             throw new NullPointerException("Operands cannot be null.");
4830         }
4831         assert (dependencies != null) && (dependencies.length > 0);
4832 
4833         return new BooleanBinding() {
4834             {
4835                 super.bind(dependencies);
4836             }
4837 
4838             @Override
4839             public void dispose() {
4840                 super.unbind(dependencies);
4841             }
4842 
4843             @Override
4844             protected boolean computeValue() {
4845                 final String s1 = getStringSafe(op1.get());
4846                 final String s2 = getStringSafe(op2.get());
4847                 return s1.equals(s2);
4848             }
4849 
4850             @Override
4851             public ObservableList<?> getDependencies() {
4852                 return (dependencies.length == 1)?
4853                         FXCollections.singletonObservableList(dependencies[0])
4854                         : new ImmutableObservableList<Observable>(dependencies);
4855             }
4856         };
4857     }
4858 
4859     /**
4860      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
4861      * if the values of two instances of
4862      * {@link javafx.beans.value.ObservableStringValue} are equal.
4863      * <p>
4864      * Note: In this comparison a {@code String} that is {@code null} is
4865      * considered equal to an empty {@code String}.
4866      *
4867      * @param op1
4868      *            the first operand
4869      * @param op2
4870      *            the second operand
4871      * @return the new {@code BooleanBinding}
4872      * @throws NullPointerException
4873      *             if one of the operands is {@code null}
4874      */
4875     public static BooleanBinding equal(final ObservableStringValue op1, final ObservableStringValue op2) {
4876         return equal(op1, op2, op1, op2);
4877     }
4878 
4879     /**
4880      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
4881      * if the value of a {@link javafx.beans.value.ObservableStringValue} is
4882      * equal to a constant value.
4883      * <p>
4884      * Note: In this comparison a {@code String} that is {@code null} is
4885      * considered equal to an empty {@code String}.
4886      *
4887      * @param op1
4888      *            the {@code ObservableStringValue}
4889      * @param op2
4890      *            the constant value
4891      * @return the new {@code BooleanBinding}
4892      * @throws NullPointerException
4893      *             if the {@code ObservableStringValue} is {@code null}
4894      */
4895     public static BooleanBinding equal(final ObservableStringValue op1, String op2) {
4896         return equal(op1, StringConstant.valueOf(op2), op1);
4897     }
4898 
4899     /**
4900      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
4901      * if the value of a {@link javafx.beans.value.ObservableStringValue} is
4902      * equal to a constant value.
4903      * <p>
4904      * Note: In this comparison a {@code String} that is {@code null} is
4905      * considered equal to an empty {@code String}.
4906      *
4907      * @param op1
4908      *            the constant value
4909      * @param op2
4910      *            the {@code ObservableStringValue}
4911      * @return the new {@code BooleanBinding}
4912      * @throws NullPointerException
4913      *             if the {@code ObservableStringValue} is {@code null}
4914      */
4915     public static BooleanBinding equal(String op1, final ObservableStringValue op2) {
4916         return equal(StringConstant.valueOf(op1), op2, op2);
4917     }
4918 
4919     private static BooleanBinding notEqual(final ObservableStringValue op1, final ObservableStringValue op2, final Observable... dependencies) {
4920         if ((op1 == null) || (op2 == null)) {
4921             throw new NullPointerException("Operands cannot be null.");
4922         }
4923         assert (dependencies != null) && (dependencies.length > 0);
4924 
4925         return new BooleanBinding() {
4926             {
4927                 super.bind(dependencies);
4928             }
4929 
4930             @Override
4931             public void dispose() {
4932                 super.unbind(dependencies);
4933             }
4934 
4935             @Override
4936             protected boolean computeValue() {
4937                 final String s1 = getStringSafe(op1.get());
4938                 final String s2 = getStringSafe(op2.get());
4939                 return ! s1.equals(s2);
4940             }
4941 
4942             @Override
4943             public ObservableList<?> getDependencies() {
4944                 return (dependencies.length == 1)?
4945                         FXCollections.singletonObservableList(dependencies[0])
4946                         : new ImmutableObservableList<Observable>(dependencies);
4947             }
4948         };
4949     }
4950 
4951     /**
4952      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
4953      * if the values of two instances of
4954      * {@link javafx.beans.value.ObservableStringValue} are not equal.
4955      * <p>
4956      * Note: In this comparison a {@code String} that is {@code null} is
4957      * considered equal to an empty {@code String}.
4958      *
4959      * @param op1
4960      *            the first operand
4961      * @param op2
4962      *            the second operand
4963      * @return the new {@code BooleanBinding}
4964      * @throws NullPointerException
4965      *             if one of the operands is {@code null}
4966      */
4967     public static BooleanBinding notEqual(final ObservableStringValue op1, final ObservableStringValue op2) {
4968         return notEqual(op1, op2, op1, op2);
4969     }
4970 
4971     /**
4972      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
4973      * if the value of a {@link javafx.beans.value.ObservableStringValue} is not
4974      * equal to a constant value.
4975      * <p>
4976      * Note: In this comparison a {@code String} that is {@code null} is
4977      * considered equal to an empty {@code String}.
4978      *
4979      * @param op1
4980      *            the {@code ObservableStringValue}
4981      * @param op2
4982      *            the constant value
4983      * @return the new {@code BooleanBinding}
4984      * @throws NullPointerException
4985      *             if the {@code ObservableStringValue} is {@code null}
4986      */
4987     public static BooleanBinding notEqual(final ObservableStringValue op1, String op2) {
4988         return notEqual(op1, StringConstant.valueOf(op2), op1);
4989     }
4990 
4991     /**
4992      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
4993      * if the value of a {@link javafx.beans.value.ObservableStringValue} is not
4994      * equal to a constant value.
4995      * <p>
4996      * Note: In this comparison a {@code String} that is {@code null} is
4997      * considered equal to an empty {@code String}.
4998      *
4999      * @param op1
5000      *            the constant value
5001      * @param op2
5002      *            the {@code ObservableStringValue}
5003      * @return the new {@code BooleanBinding}
5004      * @throws NullPointerException
5005      *             if the {@code ObservableStringValue} is {@code null}
5006      */
5007     public static BooleanBinding notEqual(String op1, final ObservableStringValue op2) {
5008         return notEqual(StringConstant.valueOf(op1), op2, op2);
5009     }
5010 
5011     private static BooleanBinding equalIgnoreCase(final ObservableStringValue op1, final ObservableStringValue op2, final Observable... dependencies) {
5012         if ((op1 == null) || (op2 == null)) {
5013             throw new NullPointerException("Operands cannot be null.");
5014         }
5015         assert (dependencies != null) && (dependencies.length > 0);
5016 
5017         return new BooleanBinding() {
5018             {
5019                 super.bind(dependencies);
5020             }
5021 
5022             @Override
5023             public void dispose() {
5024                 super.unbind(dependencies);
5025             }
5026 
5027             @Override
5028             protected boolean computeValue() {
5029                 final String s1 = getStringSafe(op1.get());
5030                 final String s2 = getStringSafe(op2.get());
5031                 return s1.equalsIgnoreCase(s2);
5032             }
5033 
5034             @Override
5035             public ObservableList<?> getDependencies() {
5036                 return (dependencies.length == 1)?
5037                         FXCollections.singletonObservableList(dependencies[0])
5038                         : new ImmutableObservableList<Observable>(dependencies);
5039             }
5040         };
5041     }
5042 
5043     /**
5044      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5045      * if the values of two instances of
5046      * {@link javafx.beans.value.ObservableStringValue} are equal ignoring case.
5047      * <p>
5048      * Note: In this comparison a {@code String} that is {@code null} is
5049      * considered equal to an empty {@code String}.
5050      *
5051      * @param op1
5052      *            the first operand
5053      * @param op2
5054      *            the second operand
5055      * @return the new {@code BooleanBinding}
5056      * @throws NullPointerException
5057      *             if one of the operands is {@code null}
5058      */
5059     public static BooleanBinding equalIgnoreCase(final ObservableStringValue op1, final ObservableStringValue op2) {
5060         return equalIgnoreCase(op1, op2, op1, op2);
5061     }
5062 
5063     /**
5064      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5065      * if the value of a {@link javafx.beans.value.ObservableStringValue} is
5066      * equal to a constant value ignoring case.
5067      * <p>
5068      * Note: In this comparison a {@code String} that is {@code null} is
5069      * considered equal to an empty {@code String}.
5070      *
5071      * @param op1
5072      *            the {@code ObservableStringValue}
5073      * @param op2
5074      *            the constant value
5075      * @return the new {@code BooleanBinding}
5076      * @throws NullPointerException
5077      *             if the {@code ObservableStringValue} is {@code null}
5078      */
5079     public static BooleanBinding equalIgnoreCase(final ObservableStringValue op1, String op2) {
5080         return equalIgnoreCase(op1, StringConstant.valueOf(op2), op1);
5081     }
5082 
5083     /**
5084      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5085      * if the value of a {@link javafx.beans.value.ObservableStringValue} is
5086      * equal to a constant value ignoring case.
5087      * <p>
5088      * Note: In this comparison a {@code String} that is {@code null} is
5089      * considered equal to an empty {@code String}.
5090      *
5091      * @param op1
5092      *            the constant value
5093      * @param op2
5094      *            the {@code ObservableStringValue}
5095      * @return the new {@code BooleanBinding}
5096      * @throws NullPointerException
5097      *             if the {@code ObservableStringValue} is {@code null}
5098      */
5099     public static BooleanBinding equalIgnoreCase(String op1, final ObservableStringValue op2) {
5100         return equalIgnoreCase(StringConstant.valueOf(op1), op2, op2);
5101     }
5102 
5103     private static BooleanBinding notEqualIgnoreCase(final ObservableStringValue op1, final ObservableStringValue op2, final Observable... dependencies) {
5104         if ((op1 == null) || (op2 == null)) {
5105             throw new NullPointerException("Operands cannot be null.");
5106         }
5107         assert (dependencies != null) && (dependencies.length > 0);
5108 
5109         return new BooleanBinding() {
5110             {
5111                 super.bind(dependencies);
5112             }
5113 
5114             @Override
5115             public void dispose() {
5116                 super.unbind(dependencies);
5117             }
5118 
5119             @Override
5120             protected boolean computeValue() {
5121                 final String s1 = getStringSafe(op1.get());
5122                 final String s2 = getStringSafe(op2.get());
5123                 return ! s1.equalsIgnoreCase(s2);
5124             }
5125 
5126             @Override
5127             public ObservableList<?> getDependencies() {
5128                 return (dependencies.length == 1)?
5129                         FXCollections.singletonObservableList(dependencies[0])
5130                         : new ImmutableObservableList<Observable>(dependencies);
5131             }
5132         };
5133     }
5134 
5135     /**
5136      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5137      * if the values of two instances of
5138      * {@link javafx.beans.value.ObservableStringValue} are not equal ignoring
5139      * case.
5140      * <p>
5141      * Note: In this comparison a {@code String} that is {@code null} is
5142      * considered equal to an empty {@code String}.
5143      *
5144      * @param op1
5145      *            the first operand
5146      * @param op2
5147      *            the second operand
5148      * @return the new {@code BooleanBinding}
5149      * @throws NullPointerException
5150      *             if one of the operands is {@code null}
5151      */
5152     public static BooleanBinding notEqualIgnoreCase(final ObservableStringValue op1, final ObservableStringValue op2) {
5153         return notEqualIgnoreCase(op1, op2, op1, op2);
5154     }
5155 
5156     /**
5157      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5158      * if the value of a {@link javafx.beans.value.ObservableStringValue} is not
5159      * equal to a constant value ignoring case.
5160      * <p>
5161      * Note: In this comparison a {@code String} that is {@code null} is
5162      * considered equal to an empty {@code String}.
5163      *
5164      * @param op1
5165      *            the {@code ObservableStringValue}
5166      * @param op2
5167      *            the constant value
5168      * @return the new {@code BooleanBinding}
5169      * @throws NullPointerException
5170      *             if the {@code ObservableStringValue} is {@code null}
5171      */
5172     public static BooleanBinding notEqualIgnoreCase(final ObservableStringValue op1, String op2) {
5173         return notEqualIgnoreCase(op1, StringConstant.valueOf(op2), op1);
5174     }
5175 
5176     /**
5177      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5178      * if the value of a {@link javafx.beans.value.ObservableStringValue} is not
5179      * equal to a constant value ignoring case.
5180      * <p>
5181      * Note: In this comparison a {@code String} that is {@code null} is
5182      * considered equal to an empty {@code String}.
5183      *
5184      * @param op1
5185      *            the constant value
5186      * @param op2
5187      *            the {@code ObservableStringValue}
5188      * @return the new {@code BooleanBinding}
5189      * @throws NullPointerException
5190      *             if the {@code ObservableStringValue} is {@code null}
5191      */
5192     public static BooleanBinding notEqualIgnoreCase(String op1, final ObservableStringValue op2) {
5193         return notEqualIgnoreCase(StringConstant.valueOf(op1), op2, op2);
5194     }
5195 
5196     private static BooleanBinding greaterThan(final ObservableStringValue op1, final ObservableStringValue op2, final Observable... dependencies) {
5197         if ((op1 == null) || (op2 == null)) {
5198             throw new NullPointerException("Operands cannot be null.");
5199         }
5200         assert (dependencies != null) && (dependencies.length > 0);
5201 
5202         return new BooleanBinding() {
5203             {
5204                 super.bind(dependencies);
5205             }
5206 
5207             @Override
5208             public void dispose() {
5209                 super.unbind(dependencies);
5210             }
5211 
5212             @Override
5213             protected boolean computeValue() {
5214                 final String s1 = getStringSafe(op1.get());
5215                 final String s2 = getStringSafe(op2.get());
5216                 return s1.compareTo(s2) > 0;
5217             }
5218 
5219             @Override
5220             public ObservableList<?> getDependencies() {
5221                 return (dependencies.length == 1)?
5222                         FXCollections.singletonObservableList(dependencies[0])
5223                         : new ImmutableObservableList<Observable>(dependencies);
5224             }
5225         };
5226     }
5227 
5228     /**
5229      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5230      * if the value of the first
5231      * {@link javafx.beans.value.ObservableStringValue} is greater than the
5232      * value of the second.
5233      * <p>
5234      * Note: In this comparison a {@code String} that is {@code null} is
5235      * considered equal to an empty {@code String}.
5236      *
5237      * @param op1
5238      *            the first operand
5239      * @param op2
5240      *            the second operand
5241      * @return the new {@code BooleanBinding}
5242      * @throws NullPointerException
5243      *             if one of the operands is {@code null}
5244      */
5245     public static BooleanBinding greaterThan(final ObservableStringValue op1, final ObservableStringValue op2) {
5246         return greaterThan(op1, op2, op1, op2);
5247     }
5248 
5249     /**
5250      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5251      * if the value of a {@link javafx.beans.value.ObservableStringValue} is
5252      * greater than a constant value.
5253      * <p>
5254      * Note: In this comparison a {@code String} that is {@code null} is
5255      * considered equal to an empty {@code String}.
5256      *
5257      * @param op1
5258      *            the {@code ObservableStringValue}
5259      * @param op2
5260      *            the constant value
5261      * @return the new {@code BooleanBinding}
5262      * @throws NullPointerException
5263      *             if the {@code ObservableStringValue} is {@code null}
5264      */
5265     public static BooleanBinding greaterThan(final ObservableStringValue op1, String op2) {
5266         return greaterThan(op1, StringConstant.valueOf(op2), op1);
5267     }
5268 
5269     /**
5270      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5271      * if the value of a constant value is greater than the value of a
5272      * {@link javafx.beans.value.ObservableStringValue}.
5273      * <p>
5274      * Note: In this comparison a {@code String} that is {@code null} is
5275      * considered equal to an empty {@code String}.
5276      *
5277      * @param op1
5278      *            the constant value
5279      * @param op2
5280      *            the {@code ObservableStringValue}
5281      * @return the new {@code BooleanBinding}
5282      * @throws NullPointerException
5283      *             if the {@code ObservableStringValue} is {@code null}
5284      */
5285     public static BooleanBinding greaterThan(String op1, final ObservableStringValue op2) {
5286         return greaterThan(StringConstant.valueOf(op1), op2, op2);
5287     }
5288 
5289     private static BooleanBinding lessThan(final ObservableStringValue op1, final ObservableStringValue op2, final Observable... dependencies) {
5290         return greaterThan(op2, op1, dependencies);
5291     }
5292 
5293     /**
5294      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5295      * if the value of the first
5296      * {@link javafx.beans.value.ObservableStringValue} is less than the value
5297      * of the second.
5298      * <p>
5299      * Note: In this comparison a {@code String} that is {@code null} is
5300      * considered equal to an empty {@code String}.
5301      *
5302      * @param op1
5303      *            the first operand
5304      * @param op2
5305      *            the second operand
5306      * @return the new {@code BooleanBinding}
5307      * @throws NullPointerException
5308      *             if one of the operands is {@code null}
5309      */
5310     public static BooleanBinding lessThan(final ObservableStringValue op1, final ObservableStringValue op2) {
5311         return lessThan(op1, op2, op1, op2);
5312     }
5313 
5314     /**
5315      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5316      * if the value of a {@link javafx.beans.value.ObservableStringValue} is
5317      * less than a constant value.
5318      * <p>
5319      * Note: In this comparison a {@code String} that is {@code null} is
5320      * considered equal to an empty {@code String}.
5321      *
5322      * @param op1
5323      *            the {@code ObservableStringValue}
5324      * @param op2
5325      *            the constant value
5326      * @return the new {@code BooleanBinding}
5327      * @throws NullPointerException
5328      *             if the {@code ObservableStringValue} is {@code null}
5329      */
5330     public static BooleanBinding lessThan(final ObservableStringValue op1, String op2) {
5331         return lessThan(op1, StringConstant.valueOf(op2), op1);
5332     }
5333 
5334     /**
5335      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5336      * if a constant value is less than the value of a
5337      * {@link javafx.beans.value.ObservableStringValue}.
5338      * <p>
5339      * Note: In this comparison a {@code String} that is {@code null} is
5340      * considered equal to an empty {@code String}.
5341      *
5342      * @param op1
5343      *            the constant value
5344      * @param op2
5345      *            the {@code ObservableStringValue}
5346      * @return the new {@code BooleanBinding}
5347      * @throws NullPointerException
5348      *             if the {@code ObservableStringValue} is {@code null}
5349      */
5350     public static BooleanBinding lessThan(String op1, final ObservableStringValue op2) {
5351         return lessThan(StringConstant.valueOf(op1), op2, op2);
5352     }
5353 
5354     private static BooleanBinding greaterThanOrEqual(final ObservableStringValue op1, final ObservableStringValue op2, final Observable... dependencies) {
5355         if ((op1 == null) || (op2 == null)) {
5356             throw new NullPointerException("Operands cannot be null.");
5357         }
5358         assert (dependencies != null) && (dependencies.length > 0);
5359 
5360         return new BooleanBinding() {
5361             {
5362                 super.bind(dependencies);
5363             }
5364 
5365             @Override
5366             public void dispose() {
5367                 super.unbind(dependencies);
5368             }
5369 
5370             @Override
5371             protected boolean computeValue() {
5372                 final String s1 = getStringSafe(op1.get());
5373                 final String s2 = getStringSafe(op2.get());
5374                 return s1.compareTo(s2) >= 0;
5375             }
5376 
5377             @Override
5378             public ObservableList<?> getDependencies() {
5379                 return (dependencies.length == 1)?
5380                         FXCollections.singletonObservableList(dependencies[0])
5381                         : new ImmutableObservableList<Observable>(dependencies);
5382             }
5383         };
5384     }
5385 
5386     /**
5387      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5388      * if the value of the first
5389      * {@link javafx.beans.value.ObservableStringValue} is greater than or equal
5390      * to the value of the second.
5391      * <p>
5392      * Note: In this comparison a {@code String} that is {@code null} is
5393      * considered equal to an empty {@code String}.
5394      *
5395      * @param op1
5396      *            the first operand
5397      * @param op2
5398      *            the second operand
5399      * @return the new {@code BooleanBinding}
5400      * @throws NullPointerException
5401      *             if one of the operands is {@code null}
5402      */
5403     public static BooleanBinding greaterThanOrEqual(final ObservableStringValue op1, final ObservableStringValue op2) {
5404         return greaterThanOrEqual(op1, op2, op1, op2);
5405     }
5406 
5407     /**
5408      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5409      * if the value of a {@link javafx.beans.value.ObservableStringValue} is
5410      * greater than or equal to a constant value.
5411      * <p>
5412      * Note: In this comparison a {@code String} that is {@code null} is
5413      * considered equal to an empty {@code String}.
5414      *
5415      * @param op1
5416      *            the {@code ObservableStringValue}
5417      * @param op2
5418      *            the constant value
5419      * @return the new {@code BooleanBinding}
5420      * @throws NullPointerException
5421      *             if the {@code ObservableStringValue} is {@code null}
5422      */
5423     public static BooleanBinding greaterThanOrEqual(final ObservableStringValue op1, String op2) {
5424         return greaterThanOrEqual(op1, StringConstant.valueOf(op2), op1);
5425     }
5426 
5427     /**
5428      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5429      * if a constant value is greater than or equal to the value of a
5430      * {@link javafx.beans.value.ObservableStringValue}.
5431      * <p>
5432      * Note: In this comparison a {@code String} that is {@code null} is
5433      * considered equal to an empty {@code String}.
5434      *
5435      * @param op1
5436      *            the constant value
5437      * @param op2
5438      *            the {@code ObservableStringValue}
5439      * @return the new {@code BooleanBinding}
5440      * @throws NullPointerException
5441      *             if the {@code ObservableStringValue} is {@code null}
5442      */
5443     public static BooleanBinding greaterThanOrEqual(String op1, final ObservableStringValue op2) {
5444         return greaterThanOrEqual(StringConstant.valueOf(op1), op2, op2);
5445     }
5446 
5447     private static BooleanBinding lessThanOrEqual(final ObservableStringValue op1, final ObservableStringValue op2, final Observable... dependencies) {
5448         return greaterThanOrEqual(op2, op1, dependencies);
5449     }
5450 
5451     /**
5452      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5453      * if the value of the first
5454      * {@link javafx.beans.value.ObservableStringValue} is less than or equal to
5455      * the value of the second.
5456      * <p>
5457      * Note: In this comparison a {@code String} that is {@code null} is
5458      * considered equal to an empty {@code String}.
5459      *
5460      * @param op1
5461      *            the first operand
5462      * @param op2
5463      *            the second operand
5464      * @return the new {@code BooleanBinding}
5465      * @throws NullPointerException
5466      *             if one of the operands is {@code null}
5467      */
5468     public static BooleanBinding lessThanOrEqual(final ObservableStringValue op1, final ObservableStringValue op2) {
5469         return lessThanOrEqual(op1, op2, op1, op2);
5470     }
5471 
5472     /**
5473      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5474      * if the value of a {@link javafx.beans.value.ObservableStringValue} is
5475      * less than or equal to a constant value.
5476      * <p>
5477      * Note: In this comparison a {@code String} that is {@code null} is
5478      * considered equal to an empty {@code String}.
5479      *
5480      * @param op1
5481      *            the {@code ObservableStringValue}
5482      * @param op2
5483      *            the constant value
5484      * @return the new {@code BooleanBinding}
5485      * @throws NullPointerException
5486      *             if the {@code ObservableStringValue} is {@code null}
5487      */
5488     public static BooleanBinding lessThanOrEqual(final ObservableStringValue op1, String op2) {
5489         return lessThanOrEqual(op1, StringConstant.valueOf(op2), op1);
5490     }
5491 
5492     /**
5493      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5494      * if a constant value is less than or equal to the value of a
5495      * {@link javafx.beans.value.ObservableStringValue}.
5496      * <p>
5497      * Note: In this comparison a {@code String} that is {@code null} is
5498      * considered equal to an empty {@code String}.
5499      *
5500      * @param op1
5501      *            the constant value
5502      * @param op2
5503      *            the {@code ObservableStringValue}
5504      * @return the new {@code BooleanBinding}
5505      * @throws NullPointerException
5506      *             if the {@code ObservableStringValue} is {@code null}
5507      */
5508     public static BooleanBinding lessThanOrEqual(String op1, final ObservableStringValue op2) {
5509         return lessThanOrEqual(StringConstant.valueOf(op1), op2, op2);
5510     }
5511 
5512     /**
5513      * Creates a new {@link javafx.beans.binding.IntegerBinding} that holds the length of a
5514      * {@link javafx.beans.value.ObservableStringValue}.
5515      * <p>
5516      * Note: In this comparison a {@code String} that is {@code null} is
5517      * considered to have a length of {@code 0}.
5518      *
5519      * @param op
5520      *            the {@code ObservableStringValue}
5521      * @return the new {@code IntegerBinding}
5522      * @throws NullPointerException
5523      *             if the {@code ObservableStringValue} is {@code null}
5524      * @since JavaFX 8.0
5525      */
5526     public static IntegerBinding length(final ObservableStringValue op) {
5527         if (op == null) {
5528             throw new NullPointerException("Operand cannot be null");
5529         }
5530 
5531         return new IntegerBinding() {
5532             {
5533                 super.bind(op);
5534             }
5535 
5536             @Override
5537             public void dispose() {
5538                 super.unbind(op);
5539             }
5540 
5541             @Override
5542             protected int computeValue() {
5543                 return getStringSafe(op.get()).length();
5544             }
5545 
5546             @Override
5547             public ObservableList<?> getDependencies() {
5548                 return FXCollections.singletonObservableList(op);
5549             }
5550         };
5551     }
5552 
5553     /**
5554      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5555      * if the value of a {@link javafx.beans.value.ObservableStringValue} is empty.
5556      * <p>
5557      * Note: In this comparison a {@code String} that is {@code null} is
5558      * considered to be empty.
5559      *
5560      * @param op
5561      *            the {@code ObservableStringValue}
5562      * @return the new {@code BooleanBinding}
5563      * @throws NullPointerException
5564      *             if the {@code ObservableStringValue} is {@code null}
5565      * @since JavaFX 8.0
5566      */
5567     public static BooleanBinding isEmpty(final ObservableStringValue op) {
5568         if (op == null) {
5569             throw new NullPointerException("Operand cannot be null");
5570         }
5571 
5572         return new BooleanBinding() {
5573             {
5574                 super.bind(op);
5575             }
5576 
5577             @Override
5578             public void dispose() {
5579                 super.unbind(op);
5580             }
5581 
5582             @Override
5583             protected boolean computeValue() {
5584                 return getStringSafe(op.get()).isEmpty();
5585             }
5586 
5587             @Override
5588             public ObservableList<?> getDependencies() {
5589                 return FXCollections.singletonObservableList(op);
5590             }
5591         };
5592     }
5593 
5594     /**
5595      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5596      * if the value of a {@link javafx.beans.value.ObservableStringValue} is not empty.
5597      * <p>
5598      * Note: In this comparison a {@code String} that is {@code null} is
5599      * considered to be empty.
5600      *
5601      * @param op
5602      *            the {@code ObservableStringValue}
5603      * @return the new {@code BooleanBinding}
5604      * @throws NullPointerException
5605      *             if the {@code ObservableStringValue} is {@code null}
5606      * @since JavaFX 8.0
5607      */
5608     public static BooleanBinding isNotEmpty(final ObservableStringValue op) {
5609         if (op == null) {
5610             throw new NullPointerException("Operand cannot be null");
5611         }
5612 
5613         return new BooleanBinding() {
5614             {
5615                 super.bind(op);
5616             }
5617 
5618             @Override
5619             public void dispose() {
5620                 super.unbind(op);
5621             }
5622 
5623             @Override
5624             protected boolean computeValue() {
5625                 return !getStringSafe(op.get()).isEmpty();
5626             }
5627 
5628             @Override
5629             public ObservableList<?> getDependencies() {
5630                 return FXCollections.singletonObservableList(op);
5631             }
5632         };
5633     }
5634 
5635     // Object
5636     // =================================================================================================================
5637 
5638     private static BooleanBinding equal(final ObservableObjectValue<?> op1, final ObservableObjectValue<?> op2, final Observable... dependencies) {
5639         if ((op1 == null) || (op2 == null)) {
5640             throw new NullPointerException("Operands cannot be null.");
5641         }
5642         assert (dependencies != null) && (dependencies.length > 0);
5643 
5644         return new BooleanBinding() {
5645             {
5646                 super.bind(dependencies);
5647             }
5648 
5649             @Override
5650             public void dispose() {
5651                 super.unbind(dependencies);
5652             }
5653 
5654             @Override
5655             protected boolean computeValue() {
5656                 final Object obj1 = op1.get();
5657                 final Object obj2 = op2.get();
5658                 return obj1 == null ? obj2 == null : obj1.equals(obj2);
5659             }
5660 
5661             @Override
5662             public ObservableList<?> getDependencies() {
5663                 return (dependencies.length == 1)?
5664                         FXCollections.singletonObservableList(dependencies[0])
5665                         : new ImmutableObservableList<Observable>(dependencies);
5666             }
5667         };
5668     }
5669 
5670     /**
5671      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5672      * if the values of two instances of
5673      * {@link javafx.beans.value.ObservableObjectValue} are equal.
5674      *
5675      * @param op1
5676      *            the first operand
5677      * @param op2
5678      *            the second operand
5679      * @return the new {@code BooleanBinding}
5680      * @throws NullPointerException
5681      *             if one of the operands is {@code null}
5682      */
5683     public static BooleanBinding equal(final ObservableObjectValue<?> op1, final ObservableObjectValue<?> op2) {
5684         return equal(op1, op2, op1, op2);
5685     }
5686 
5687     /**
5688      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5689      * if the value of an {@link javafx.beans.value.ObservableObjectValue} is
5690      * equal to a constant value.
5691      *
5692      * @param op1
5693      *            the {@code ObservableCharacterValue}
5694      * @param op2
5695      *            the constant value
5696      * @return the new {@code BooleanBinding}
5697      * @throws NullPointerException
5698      *             if the {@code ObservableCharacterValue} is {@code null}
5699      */
5700     public static BooleanBinding equal(final ObservableObjectValue<?> op1, Object op2) {
5701         return equal(op1, ObjectConstant.valueOf(op2), op1);
5702     }
5703 
5704     /**
5705      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5706      * if the value of an {@link javafx.beans.value.ObservableObjectValue} is
5707      * equal to a constant value.
5708      *
5709      * @param op1
5710      *            the constant value
5711      * @param op2
5712      *            the {@code ObservableCharacterValue}
5713      * @return the new {@code BooleanBinding}
5714      * @throws NullPointerException
5715      *             if the {@code ObservableCharacterValue} is {@code null}
5716      */
5717     public static BooleanBinding equal(Object op1, final ObservableObjectValue<?> op2) {
5718         return equal(ObjectConstant.valueOf(op1), op2, op2);
5719     }
5720 
5721     private static BooleanBinding notEqual(final ObservableObjectValue<?> op1, final ObservableObjectValue<?> op2, final Observable... dependencies) {
5722         if ((op1 == null) || (op2 == null)) {
5723             throw new NullPointerException("Operands cannot be null.");
5724         }
5725         assert (dependencies != null) && (dependencies.length > 0);
5726 
5727         return new BooleanBinding() {
5728             {
5729                 super.bind(dependencies);
5730             }
5731 
5732             @Override
5733             public void dispose() {
5734                 super.unbind(dependencies);
5735             }
5736 
5737             @Override
5738             protected boolean computeValue() {
5739                 final Object obj1 = op1.get();
5740                 final Object obj2 = op2.get();
5741                 return obj1 == null ? obj2 != null : ! obj1.equals(obj2);
5742             }
5743 
5744             @Override
5745             public ObservableList<?> getDependencies() {
5746                 return (dependencies.length == 1)?
5747                         FXCollections.singletonObservableList(dependencies[0])
5748                         : new ImmutableObservableList<Observable>(dependencies);
5749             }
5750         };
5751     }
5752 
5753     /**
5754      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5755      * if the values of two instances of
5756      * {@link javafx.beans.value.ObservableObjectValue} are not equal.
5757      *
5758      * @param op1
5759      *            the first operand
5760      * @param op2
5761      *            the second operand
5762      * @return the new {@code BooleanBinding}
5763      * @throws NullPointerException
5764      *             if one of the operands is {@code null}
5765      */
5766     public static BooleanBinding notEqual(final ObservableObjectValue<?> op1, final ObservableObjectValue<?> op2) {
5767         return notEqual(op1, op2, op1, op2);
5768     }
5769 
5770     /**
5771      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5772      * if the value of an {@link javafx.beans.value.ObservableObjectValue} is
5773      * not equal to a constant value.
5774      *
5775      * @param op1
5776      *            the {@code ObservableObjectValue}
5777      * @param op2
5778      *            the constant value
5779      * @return the new {@code BooleanBinding}
5780      * @throws NullPointerException
5781      *             if the {@code ObservableObjectValue} is {@code null}
5782      */
5783     public static BooleanBinding notEqual(final ObservableObjectValue<?> op1, Object op2) {
5784         return notEqual(op1, ObjectConstant.valueOf(op2), op1);
5785     }
5786 
5787     /**
5788      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5789      * if the value of an {@link javafx.beans.value.ObservableObjectValue} is
5790      * not equal to a constant value.
5791      *
5792      * @param op1
5793      *            the constant value
5794      * @param op2
5795      *            the {@code ObservableObjectValue}
5796      * @return the new {@code BooleanBinding}
5797      * @throws NullPointerException
5798      *             if the {@code ObservableObjectValue} is {@code null}
5799      */
5800     public static BooleanBinding notEqual(Object op1, final ObservableObjectValue<?> op2) {
5801         return notEqual(ObjectConstant.valueOf(op1), op2, op2);
5802     }
5803 
5804     /**
5805      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5806      * if the value of an {@link javafx.beans.value.ObservableObjectValue} is
5807      * {@code null}.
5808      *
5809      * @param op
5810      *            the {@code ObservableObjectValue}
5811      * @return the new {@code BooleanBinding}
5812      * @throws NullPointerException
5813      *             if the {@code ObservableObjectValue} is {@code null}
5814      */
5815     public static BooleanBinding isNull(final ObservableObjectValue<?> op) {
5816         if (op == null) {
5817             throw new NullPointerException("Operand cannot be null.");
5818         }
5819 
5820         return new BooleanBinding() {
5821             {
5822                 super.bind(op);
5823             }
5824 
5825             @Override
5826             public void dispose() {
5827                 super.unbind(op);
5828             }
5829 
5830             @Override
5831             protected boolean computeValue() {
5832                 return op.get() == null;
5833             }
5834 
5835             @Override
5836             public ObservableList<?> getDependencies() {
5837                 return FXCollections.singletonObservableList(op);
5838             }
5839         };
5840     }
5841 
5842     /**
5843      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5844      * if the value of an {@link javafx.beans.value.ObservableObjectValue} is
5845      * not {@code null}.
5846      *
5847      * @param op
5848      *            the {@code ObservableObjectValue}
5849      * @return the new {@code BooleanBinding}
5850      * @throws NullPointerException
5851      *             if the {@code ObservableObjectValue} is {@code null}
5852      */
5853     public static BooleanBinding isNotNull(final ObservableObjectValue<?> op) {
5854         if (op == null) {
5855             throw new NullPointerException("Operand cannot be null.");
5856         }
5857 
5858         return new BooleanBinding() {
5859             {
5860                 super.bind(op);
5861             }
5862 
5863             @Override
5864             public void dispose() {
5865                 super.unbind(op);
5866             }
5867 
5868             @Override
5869             protected boolean computeValue() {
5870                 return op.get() != null;
5871             }
5872 
5873             @Override
5874             public ObservableList<?> getDependencies() {
5875                 return FXCollections.singletonObservableList(op);
5876             }
5877         };
5878     }
5879 
5880     // List
5881     // =================================================================================================================
5882 
5883     /**
5884      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the size
5885      * of an {@link javafx.collections.ObservableList}.
5886      *
5887      * @param op
5888      *            the {@code ObservableList}
5889      * @param <E> type of the {@code List} elements
5890      * @return the new {@code IntegerBinding}
5891      * @throws NullPointerException
5892      *             if the {@code ObservableList} is {@code null}
5893      * @since JavaFX 2.1
5894      */
5895     public static <E> IntegerBinding size(final ObservableList<E> op) {
5896         if (op == null) {
5897             throw new NullPointerException("List cannot be null.");
5898         }
5899 
5900         return new IntegerBinding() {
5901             {
5902                 super.bind(op);
5903             }
5904 
5905             @Override
5906             public void dispose() {
5907                 super.unbind(op);
5908             }
5909 
5910             @Override
5911             protected int computeValue() {
5912                 return op.size();
5913             }
5914 
5915             @Override
5916             public ObservableList<?> getDependencies() {
5917                 return FXCollections.singletonObservableList(op);
5918             }
5919         };
5920     }
5921 
5922     /**
5923      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5924      * if a given {@link javafx.collections.ObservableList} is empty.
5925      *
5926      * @param op
5927      *            the {@code ObservableList}
5928      * @param <E> type of the {@code List} elements
5929      * @return the new {@code BooleanBinding}
5930      * @throws NullPointerException
5931      *             if the {@code ObservableList} is {@code null}
5932      * @since JavaFX 2.1
5933      */
5934     public static <E> BooleanBinding isEmpty(final ObservableList<E> op) {
5935         if (op == null) {
5936             throw new NullPointerException("List cannot be null.");
5937         }
5938 
5939         return new BooleanBinding() {
5940             {
5941                 super.bind(op);
5942             }
5943 
5944             @Override
5945             public void dispose() {
5946                 super.unbind(op);
5947             }
5948 
5949             @Override
5950             protected boolean computeValue() {
5951                 return op.isEmpty();
5952             }
5953 
5954             @Override
5955             public ObservableList<?> getDependencies() {
5956                 return FXCollections.singletonObservableList(op);
5957             }
5958         };
5959     }
5960 
5961     /**
5962      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
5963      * if a given {@link javafx.collections.ObservableList} is not empty.
5964      *
5965      * @param op
5966      *            the {@code ObservableList}
5967      * @param <E> type of the {@code List} elements
5968      * @return the new {@code BooleanBinding}
5969      * @throws NullPointerException
5970      *             if the {@code ObservableList} is {@code null}
5971      * @since JavaFX 8.0
5972      */
5973     public static <E> BooleanBinding isNotEmpty(final ObservableList<E> op)     {
5974         if (op == null) {
5975             throw new NullPointerException("List cannot be null.");
5976         }
5977 
5978         return new BooleanBinding() {
5979             {
5980                 super.bind(op);
5981             }
5982 
5983             @Override
5984             public void dispose() {
5985                 super.unbind(op);
5986             }
5987 
5988             @Override
5989             protected boolean computeValue() {
5990                 return !op.isEmpty();
5991             }
5992 
5993             @Override
5994             public ObservableList<?> getDependencies() {
5995                 return FXCollections.singletonObservableList(op);
5996             }
5997         };
5998     }
5999 
6000     /**
6001      * Creates a new {@link javafx.beans.binding.ObjectBinding} that contains the element
6002      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code ObjectBinding}
6003      * will contain {@code null}, if the {@code index} points behind the {@code ObservableList}.
6004      *
6005      * @param op the {@code ObservableList}
6006      * @param index the position in the {@code List}
6007      * @param <E> the type of the {@code List} elements
6008      * @return the new {@code ObjectBinding}
6009      * @throws NullPointerException if the {@code ObservableList} is {@code null}
6010      * @throws IllegalArgumentException if (@code index &lt; 0)
6011      * @since JavaFX 2.1
6012      */
6013     public static <E> ObjectBinding<E> valueAt(final ObservableList<E> op, final int index) {
6014         if (op == null) {
6015             throw new NullPointerException("List cannot be null.");
6016         }
6017         if (index < 0) {
6018             throw new IllegalArgumentException("Index cannot be negative");
6019         }
6020 
6021         return new ObjectBinding<E>() {
6022             {
6023                 super.bind(op);
6024             }
6025 
6026             @Override
6027             public void dispose() {
6028                 super.unbind(op);
6029             }
6030 
6031             @Override
6032             protected E computeValue() {
6033                 try {
6034                     return op.get(index);
6035                 } catch (IndexOutOfBoundsException ex) {
6036                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6037                 }
6038                 return null;
6039             }
6040 
6041             @Override
6042             public ObservableList<?> getDependencies() {
6043                 return FXCollections.singletonObservableList(op);
6044             }
6045         };
6046     }
6047 
6048     /**
6049      * Creates a new {@link javafx.beans.binding.ObjectBinding} that contains the element
6050      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code ObjectBinding}
6051      * will contain {@code null}, if the {@code index} is outside of the {@code ObservableList}.
6052      *
6053      * @param op the {@code ObservableList}
6054      * @param index the position in the {@code List}
6055      * @param <E> the type of the {@code List} elements
6056      * @return the new {@code ObjectBinding}
6057      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6058      * @since JavaFX 2.1
6059      */
6060     public static <E> ObjectBinding<E> valueAt(final ObservableList<E> op, final ObservableIntegerValue index) {
6061         return valueAt(op, (ObservableNumberValue)index);
6062     }
6063 
6064     /**
6065      * Creates a new {@link javafx.beans.binding.ObjectBinding} that contains the element
6066      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code ObjectBinding}
6067      * will contain {@code null}, if the {@code index} is outside of the {@code ObservableList}.
6068      *
6069      * @param op the {@code ObservableList}
6070      * @param index the position in the {@code List}, converted to int
6071      * @param <E> the type of the {@code List} elements
6072      * @return the new {@code ObjectBinding}
6073      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6074      * @since JavaFX 8.0
6075      */
6076     public static <E> ObjectBinding<E> valueAt(final ObservableList<E> op, final ObservableNumberValue index) {
6077         if ((op == null) || (index == null)) {
6078             throw new NullPointerException("Operands cannot be null.");
6079         }
6080 
6081         return new ObjectBinding<E>() {
6082             {
6083                 super.bind(op, index);
6084             }
6085 
6086             @Override
6087             public void dispose() {
6088                 super.unbind(op, index);
6089             }
6090 
6091             @Override
6092             protected E computeValue() {
6093                 try {
6094                     return op.get(index.intValue());
6095                 } catch (IndexOutOfBoundsException ex) {
6096                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6097                 }
6098                 return null;
6099             }
6100 
6101             @Override
6102             public ObservableList<?> getDependencies() {
6103                 return new ImmutableObservableList<Observable>(op, index);
6104             }
6105         };
6106     }
6107 
6108     /**
6109      * Creates a new {@link javafx.beans.binding.BooleanBinding} that contains the element
6110      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code BooleanBinding}
6111      * will hold {@code false}, if the {@code index} points behind the {@code ObservableList}.
6112      *
6113      * @param op the {@code ObservableList}
6114      * @param index the position in the {@code List}
6115      * @return the new {@code BooleanBinding}
6116      * @throws NullPointerException if the {@code ObservableList} is {@code null}
6117      * @throws IllegalArgumentException if (@code index &lt; 0)
6118      * @since JavaFX 2.1
6119      */
6120     public static BooleanBinding booleanValueAt(final ObservableList<Boolean> op, final int index) {
6121         if (op == null) {
6122             throw new NullPointerException("List cannot be null.");
6123         }
6124         if (index < 0) {
6125             throw new IllegalArgumentException("Index cannot be negative");
6126         }
6127 
6128         return new BooleanBinding() {
6129             {
6130                 super.bind(op);
6131             }
6132 
6133             @Override
6134             public void dispose() {
6135                 super.unbind(op);
6136             }
6137 
6138             @Override
6139             protected boolean computeValue() {
6140                 try {
6141                     final Boolean value = op.get(index);
6142                     if (value == null) {
6143                         Logging.getLogger().fine("List element is null, returning default value instead.", new NullPointerException());
6144                     } else {
6145                         return value;
6146                     }
6147                 } catch (IndexOutOfBoundsException ex) {
6148                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6149                 }
6150                 return false;
6151             }
6152 
6153             @Override
6154             public ObservableList<?> getDependencies() {
6155                 return FXCollections.singletonObservableList(op);
6156             }
6157         };
6158     }
6159 
6160     /**
6161      * Creates a new {@link javafx.beans.binding.BooleanBinding} that contains the element
6162      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code BooleanBinding}
6163      * will hold {@code false}, if the {@code index} is outside of the {@code ObservableList}.
6164      *
6165      * @param op the {@code ObservableList}
6166      * @param index the position in the {@code List}
6167      * @return the new {@code BooleanBinding}
6168      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6169      * @since JavaFX 2.1
6170      */
6171     public static BooleanBinding booleanValueAt(final ObservableList<Boolean> op, final ObservableIntegerValue index) {
6172         return booleanValueAt(op, (ObservableNumberValue)index);
6173     }
6174 
6175     /**
6176      * Creates a new {@link javafx.beans.binding.BooleanBinding} that contains the element
6177      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code BooleanBinding}
6178      * will hold {@code false}, if the {@code index} is outside of the {@code ObservableList}.
6179      *
6180      * @param op the {@code ObservableList}
6181      * @param index the position in the {@code List}, converted to int
6182      * @return the new {@code BooleanBinding}
6183      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6184      * @since JavaFX 8.0
6185      */
6186     public static BooleanBinding booleanValueAt(final ObservableList<Boolean> op, final ObservableNumberValue index) {
6187         if ((op == null) || (index == null)) {
6188             throw new NullPointerException("Operands cannot be null.");
6189         }
6190 
6191         return new BooleanBinding() {
6192             {
6193                 super.bind(op, index);
6194             }
6195 
6196             @Override
6197             public void dispose() {
6198                 super.unbind(op, index);
6199             }
6200 
6201             @Override
6202             protected boolean computeValue() {
6203                 try {
6204                     final Boolean value = op.get(index.intValue());
6205                     if (value == null) {
6206                         Logging.getLogger().fine("List element is null, returning default value instead.", new NullPointerException());
6207                     } else {
6208                         return value;
6209                     }
6210                 } catch (IndexOutOfBoundsException ex) {
6211                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6212                 }
6213                 return false;
6214             }
6215 
6216             @Override
6217             public ObservableList<?> getDependencies() {
6218                 return new ImmutableObservableList<Observable>(op, index);
6219             }
6220         };
6221     }
6222 
6223     /**
6224      * Creates a new {@link javafx.beans.binding.DoubleBinding} that contains the element
6225      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code DoubleBinding}
6226      * will hold {@code 0.0}, if the {@code index} points behind the {@code ObservableList}.
6227      *
6228      * @param op the {@code ObservableList}
6229      * @param index the position in the {@code List}
6230      * @return the new {@code DoubleBinding}
6231      * @throws NullPointerException if the {@code ObservableList} is {@code null}
6232      * @throws IllegalArgumentException if (@code index &lt; 0)
6233      * @since JavaFX 2.1
6234      */
6235     public static DoubleBinding doubleValueAt(final ObservableList<? extends Number> op, final int index) {
6236         if (op == null) {
6237             throw new NullPointerException("List cannot be null.");
6238         }
6239         if (index < 0) {
6240             throw new IllegalArgumentException("Index cannot be negative");
6241         }
6242 
6243         return new DoubleBinding() {
6244             {
6245                 super.bind(op);
6246             }
6247 
6248             @Override
6249             public void dispose() {
6250                 super.unbind(op);
6251             }
6252 
6253             @Override
6254             protected double computeValue() {
6255                 try {
6256                     final Number value = op.get(index);
6257                     if (value == null) {
6258                         Logging.getLogger().fine("List element is null, returning default value instead.", new NullPointerException());
6259                     } else {
6260                         return value.doubleValue();
6261                     }
6262                 } catch (IndexOutOfBoundsException ex) {
6263                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6264                 }
6265                 return 0.0;
6266             }
6267 
6268             @Override
6269             public ObservableList<?> getDependencies() {
6270                 return FXCollections.singletonObservableList(op);
6271             }
6272         };
6273     }
6274 
6275     /**
6276      * Creates a new {@link javafx.beans.binding.DoubleBinding} that contains the element
6277      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code DoubleBinding}
6278      * will hold {@code 0.0}, if the {@code index} is outside of the {@code ObservableList}.
6279      *
6280      * @param op the {@code ObservableList}
6281      * @param index the position in the {@code List}
6282      * @return the new {@code DoubleBinding}
6283      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6284      * @since JavaFX 2.1
6285      */
6286     public static DoubleBinding doubleValueAt(final ObservableList<? extends Number> op, final ObservableIntegerValue index) {
6287         return doubleValueAt(op, (ObservableNumberValue)index);
6288     }
6289 
6290     /**
6291      * Creates a new {@link javafx.beans.binding.DoubleBinding} that contains the element
6292      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code DoubleBinding}
6293      * will hold {@code 0.0}, if the {@code index} is outside of the {@code ObservableList}.
6294      *
6295      * @param op the {@code ObservableList}
6296      * @param index the position in the {@code List}, converted to int
6297      * @return the new {@code DoubleBinding}
6298      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6299      * @since JavaFX 8.0
6300      */
6301     public static DoubleBinding doubleValueAt(final ObservableList<? extends Number> op, final ObservableNumberValue index) {
6302         if ((op == null) || (index == null)) {
6303             throw new NullPointerException("Operands cannot be null.");
6304         }
6305 
6306         return new DoubleBinding() {
6307             {
6308                 super.bind(op, index);
6309             }
6310 
6311             @Override
6312             public void dispose() {
6313                 super.unbind(op, index);
6314             }
6315 
6316             @Override
6317             protected double computeValue() {
6318                 try {
6319                     final Number value = op.get(index.intValue());
6320                     if (value == null) {
6321                         Logging.getLogger().fine("List element is null, returning default value instead.", new NullPointerException());
6322                     } else {
6323                         return value.doubleValue();
6324                     }
6325                 } catch (IndexOutOfBoundsException ex) {
6326                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6327                 }
6328                 return 0.0;
6329             }
6330 
6331             @Override
6332             public ObservableList<?> getDependencies() {
6333                 return new ImmutableObservableList<Observable>(op, index);
6334             }
6335         };
6336     }
6337 
6338     /**
6339      * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the element
6340      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code FloatBinding}
6341      * will hold {@code 0.0f}, if the {@code index} points behind the {@code ObservableList}.
6342      *
6343      * @param op the {@code ObservableList}
6344      * @param index the position in the {@code List}
6345      * @return the new {@code FloatBinding}
6346      * @throws NullPointerException if the {@code ObservableList} is {@code null}
6347      * @throws IllegalArgumentException if (@code index &lt; 0)
6348      * @since JavaFX 2.1
6349      */
6350     public static FloatBinding floatValueAt(final ObservableList<? extends Number> op, final int index) {
6351         if (op == null) {
6352             throw new NullPointerException("List cannot be null.");
6353         }
6354         if (index < 0) {
6355             throw new IllegalArgumentException("Index cannot be negative");
6356         }
6357 
6358         return new FloatBinding() {
6359             {
6360                 super.bind(op);
6361             }
6362 
6363             @Override
6364             public void dispose() {
6365                 super.unbind(op);
6366             }
6367 
6368             @Override
6369             protected float computeValue() {
6370                 try {
6371                     final Number value = op.get(index);
6372                     if (value == null) {
6373                         Logging.getLogger().fine("List element is null, returning default value instead.", new NullPointerException());
6374                     } else {
6375                         return value.floatValue();
6376                     }
6377                 } catch (IndexOutOfBoundsException ex) {
6378                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6379                 }
6380                 return 0.0f;
6381             }
6382 
6383             @Override
6384             public ObservableList<?> getDependencies() {
6385                 return FXCollections.singletonObservableList(op);
6386             }
6387         };
6388     }
6389 
6390     /**
6391      * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the element
6392      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code FloatBinding}
6393      * will hold {@code 0.0f}, if the {@code index} is outside of the {@code ObservableList}.
6394      *
6395      * @param op the {@code ObservableList}
6396      * @param index the position in the {@code List}
6397      * @return the new {@code FloatBinding}
6398      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6399      * @since JavaFX 2.1
6400      */
6401     public static FloatBinding floatValueAt(final ObservableList<? extends Number> op, final ObservableIntegerValue index) {
6402         return floatValueAt(op, (ObservableNumberValue)index);
6403     }
6404 
6405     /**
6406      * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the element
6407      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code FloatBinding}
6408      * will hold {@code 0.0f}, if the {@code index} is outside of the {@code ObservableList}.
6409      *
6410      * @param op the {@code ObservableList}
6411      * @param index the position in the {@code List}, converted to int
6412      * @return the new {@code FloatBinding}
6413      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6414      * @since JavaFX 8.0
6415      */
6416     public static FloatBinding floatValueAt(final ObservableList<? extends Number> op, final ObservableNumberValue index) {
6417         if ((op == null) || (index == null)) {
6418             throw new NullPointerException("Operands cannot be null.");
6419         }
6420 
6421         return new FloatBinding() {
6422             {
6423                 super.bind(op, index);
6424             }
6425 
6426             @Override
6427             public void dispose() {
6428                 super.unbind(op, index);
6429             }
6430 
6431             @Override
6432             protected float computeValue() {
6433                 try {
6434                     final Number value = op.get(index.intValue());
6435                     if (value == null) {
6436                         Logging.getLogger().fine("List element is null, returning default value instead.", new NullPointerException());
6437                     } else {
6438                         return value.floatValue();
6439                     }
6440                 } catch (IndexOutOfBoundsException ex) {
6441                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6442                 }
6443                 return 0.0f;
6444             }
6445 
6446             @Override
6447             public ObservableList<?> getDependencies() {
6448                 return new ImmutableObservableList<Observable>(op, index);
6449             }
6450         };
6451     }
6452 
6453     /**
6454      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the element
6455      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code IntegerBinding}
6456      * will hold {@code 0}, if the {@code index} points behind the {@code ObservableList}.
6457      *
6458      * @param op the {@code ObservableList}
6459      * @param index the position in the {@code List}
6460      * @return the new {@code IntegerBinding}
6461      * @throws NullPointerException if the {@code ObservableList} is {@code null}
6462      * @throws IllegalArgumentException if (@code index &lt; 0)
6463      * @since JavaFX 2.1
6464      */
6465     public static IntegerBinding integerValueAt(final ObservableList<? extends Number> op, final int index) {
6466         if (op == null) {
6467             throw new NullPointerException("List cannot be null.");
6468         }
6469         if (index < 0) {
6470             throw new IllegalArgumentException("Index cannot be negative");
6471         }
6472 
6473         return new IntegerBinding() {
6474             {
6475                 super.bind(op);
6476             }
6477 
6478             @Override
6479             public void dispose() {
6480                 super.unbind(op);
6481             }
6482 
6483             @Override
6484             protected int computeValue() {
6485                 try {
6486                     final Number value = op.get(index);
6487                     if (value == null) {
6488                         Logging.getLogger().fine("List element is null, returning default value instead.", new NullPointerException());
6489                     } else {
6490                         return value.intValue();
6491                     }
6492                 } catch (IndexOutOfBoundsException ex) {
6493                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6494                 }
6495                 return 0;
6496             }
6497 
6498             @Override
6499             public ObservableList<?> getDependencies() {
6500                 return FXCollections.singletonObservableList(op);
6501             }
6502         };
6503     }
6504 
6505     /**
6506      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the element
6507      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code IntegerBinding}
6508      * will hold {@code 0}, if the {@code index} is outside of the {@code ObservableList}.
6509      *
6510      * @param op the {@code ObservableList}
6511      * @param index the position in the {@code List}
6512      * @return the new {@code IntegerBinding}
6513      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6514      * @since JavaFX 2.1
6515      */
6516     public static IntegerBinding integerValueAt(final ObservableList<? extends Number> op, final ObservableIntegerValue index) {
6517         return integerValueAt(op, (ObservableNumberValue)index);
6518     }
6519 
6520     /**
6521      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the element
6522      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code IntegerBinding}
6523      * will hold {@code 0}, if the {@code index} is outside of the {@code ObservableList}.
6524      *
6525      * @param op the {@code ObservableList}
6526      * @param index the position in the {@code List}, converted to int
6527      * @return the new {@code IntegerBinding}
6528      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6529      * @since JavaFX 8.0
6530      */
6531     public static IntegerBinding integerValueAt(final ObservableList<? extends Number> op, final ObservableNumberValue index) {
6532         if ((op == null) || (index == null)) {
6533             throw new NullPointerException("Operands cannot be null.");
6534         }
6535 
6536         return new IntegerBinding() {
6537             {
6538                 super.bind(op, index);
6539             }
6540 
6541             @Override
6542             public void dispose() {
6543                 super.unbind(op, index);
6544             }
6545 
6546             @Override
6547             protected int computeValue() {
6548                 try {
6549                     final Number value = op.get(index.intValue());
6550                     if (value == null) {
6551                         Logging.getLogger().fine("List element is null, returning default value instead.", new NullPointerException());
6552                     } else {
6553                         return value.intValue();
6554                     }
6555                 } catch (IndexOutOfBoundsException ex) {
6556                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6557                 }
6558                 return 0;
6559             }
6560 
6561             @Override
6562             public ObservableList<?> getDependencies() {
6563                 return new ImmutableObservableList<Observable>(op, index);
6564             }
6565         };
6566     }
6567 
6568     /**
6569      * Creates a new {@link javafx.beans.binding.LongBinding} that contains the element
6570      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code LongBinding}
6571      * will hold {@code 0L}, if the {@code index} points behind the {@code ObservableList}.
6572      *
6573      * @param op the {@code ObservableList}
6574      * @param index the position in the {@code List}
6575      * @return the new {@code LongBinding}
6576      * @throws NullPointerException if the {@code ObservableList} is {@code null}
6577      * @throws IllegalArgumentException if (@code index &lt; 0)
6578      * @since JavaFX 2.1
6579      */
6580     public static LongBinding longValueAt(final ObservableList<? extends Number> op, final int index) {
6581         if (op == null) {
6582             throw new NullPointerException("List cannot be null.");
6583         }
6584         if (index < 0) {
6585             throw new IllegalArgumentException("Index cannot be negative");
6586         }
6587 
6588         return new LongBinding() {
6589             {
6590                 super.bind(op);
6591             }
6592 
6593             @Override
6594             public void dispose() {
6595                 super.unbind(op);
6596             }
6597 
6598             @Override
6599             protected long computeValue() {
6600                 try {
6601                     final Number value = op.get(index);
6602                     if (value == null) {
6603                         Logging.getLogger().fine("List element is null, returning default value instead.", new NullPointerException());
6604                     } else {
6605                         return value.longValue();
6606                     }
6607                 } catch (IndexOutOfBoundsException ex) {
6608                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6609                 }
6610                 return 0L;
6611             }
6612 
6613             @Override
6614             public ObservableList<?> getDependencies() {
6615                 return FXCollections.singletonObservableList(op);
6616             }
6617         };
6618     }
6619 
6620     /**
6621      * Creates a new {@link javafx.beans.binding.LongBinding} that contains the element
6622      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code LongBinding}
6623      * will hold {@code 0L}, if the {@code index} is outside of the {@code ObservableList}.
6624      *
6625      * @param op the {@code ObservableList}
6626      * @param index the position in the {@code List}
6627      * @return the new {@code LongBinding}
6628      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6629      * @since JavaFX 2.1
6630      */
6631     public static LongBinding longValueAt(final ObservableList<? extends Number> op, final ObservableIntegerValue index) {
6632         return longValueAt(op, (ObservableNumberValue)index);
6633     }
6634 
6635     /**
6636      * Creates a new {@link javafx.beans.binding.LongBinding} that contains the element
6637      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code LongBinding}
6638      * will hold {@code 0L}, if the {@code index} is outside of the {@code ObservableList}.
6639      *
6640      * @param op the {@code ObservableList}
6641      * @param index the position in the {@code List}, converted to int
6642      * @return the new {@code LongBinding}
6643      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6644      * @since JavaFX 8.0
6645      */
6646     public static LongBinding longValueAt(final ObservableList<? extends Number> op, final ObservableNumberValue index) {
6647         if ((op == null) || (index == null)) {
6648             throw new NullPointerException("Operands cannot be null.");
6649         }
6650 
6651         return new LongBinding() {
6652             {
6653                 super.bind(op, index);
6654             }
6655 
6656             @Override
6657             public void dispose() {
6658                 super.unbind(op, index);
6659             }
6660 
6661             @Override
6662             protected long computeValue() {
6663                 try {
6664                     final Number value = op.get(index.intValue());
6665                     if (value == null) {
6666                         Logging.getLogger().fine("List element is null, returning default value instead.", new NullPointerException());
6667                     } else {
6668                         return value.longValue();
6669                     }
6670                 } catch (IndexOutOfBoundsException ex) {
6671                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6672                 }
6673                 return 0L;
6674             }
6675 
6676             @Override
6677             public ObservableList<?> getDependencies() {
6678                 return new ImmutableObservableList<Observable>(op, index);
6679             }
6680         };
6681     }
6682 
6683     /**
6684      * Creates a new {@link javafx.beans.binding.StringBinding} that contains the element
6685      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code StringBinding}
6686      * will hold {@code null}, if the {@code index} points behind the {@code ObservableList}.
6687      *
6688      * @param op the {@code ObservableList}
6689      * @param index the position in the {@code List}
6690      * @return the new {@code StringBinding}
6691      * @throws NullPointerException if the {@code ObservableList} is {@code null}
6692      * @throws IllegalArgumentException if (@code index &lt; 0)
6693      * @since JavaFX 2.1
6694      */
6695     public static StringBinding stringValueAt(final ObservableList<String> op, final int index) {
6696         if (op == null) {
6697             throw new NullPointerException("List cannot be null.");
6698         }
6699         if (index < 0) {
6700             throw new IllegalArgumentException("Index cannot be negative");
6701         }
6702 
6703         return new StringBinding() {
6704             {
6705                 super.bind(op);
6706             }
6707 
6708             @Override
6709             public void dispose() {
6710                 super.unbind(op);
6711             }
6712 
6713             @Override
6714             protected String computeValue() {
6715                 try {
6716                     return op.get(index);
6717                 } catch (IndexOutOfBoundsException ex) {
6718                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6719                 }
6720                 return null;
6721             }
6722 
6723             @Override
6724             public ObservableList<?> getDependencies() {
6725                 return FXCollections.singletonObservableList(op);
6726             }
6727         };
6728     }
6729 
6730     /**
6731      * Creates a new {@link javafx.beans.binding.StringBinding} that contains the element
6732      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code StringBinding}
6733      * will hold {@code ""}, if the {@code index} is outside of the {@code ObservableList}.
6734      *
6735      * @param op the {@code ObservableList}
6736      * @param index the position in the {@code List}
6737      * @return the new {@code StringBinding}
6738      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6739      * @since JavaFX 2.1
6740      */
6741     public static StringBinding stringValueAt(final ObservableList<String> op, final ObservableIntegerValue index) {
6742         return stringValueAt(op, (ObservableNumberValue)index);
6743     }
6744 
6745     /**
6746      * Creates a new {@link javafx.beans.binding.StringBinding} that contains the element
6747      * of an {@link javafx.collections.ObservableList} at the specified position. The {@code StringBinding}
6748      * will hold {@code ""}, if the {@code index} is outside of the {@code ObservableList}.
6749      *
6750      * @param op the {@code ObservableList}
6751      * @param index the position in the {@code List}, converted to int
6752      * @return the new {@code StringBinding}
6753      * @throws NullPointerException if the {@code ObservableList} or {@code index} is {@code null}
6754      * @since JavaFX 8.0
6755      */
6756     public static StringBinding stringValueAt(final ObservableList<String> op, final ObservableNumberValue index) {
6757         if ((op == null) || (index == null)) {
6758             throw new NullPointerException("Operands cannot be null.");
6759         }
6760 
6761         return new StringBinding() {
6762             {
6763                 super.bind(op, index);
6764             }
6765 
6766             @Override
6767             public void dispose() {
6768                 super.unbind(op, index);
6769             }
6770 
6771             @Override
6772             protected String computeValue() {
6773                 try {
6774                     return op.get(index.intValue());
6775                 } catch (IndexOutOfBoundsException ex) {
6776                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6777                 }
6778                 return null;
6779             }
6780 
6781             @Override
6782             public ObservableList<?> getDependencies() {
6783                 return new ImmutableObservableList<Observable>(op, index);
6784             }
6785         };
6786     }
6787 
6788     // Set
6789     // =================================================================================================================
6790 
6791     /**
6792      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the size
6793      * of an {@link javafx.collections.ObservableSet}.
6794      *
6795      * @param op
6796      *            the {@code ObservableSet}
6797      * @param <E> the type of the {@code Set} elements
6798      * @return the new {@code IntegerBinding}
6799      * @throws NullPointerException
6800      *             if the {@code ObservableSet} is {@code null}
6801      * @since JavaFX 2.1
6802      */
6803     public static <E> IntegerBinding size(final ObservableSet<E> op) {
6804         if (op == null) {
6805             throw new NullPointerException("Set cannot be null.");
6806         }
6807 
6808         return new IntegerBinding() {
6809             {
6810                 super.bind(op);
6811             }
6812 
6813             @Override
6814             public void dispose() {
6815                 super.unbind(op);
6816             }
6817 
6818             @Override
6819             protected int computeValue() {
6820                 return op.size();
6821             }
6822 
6823             @Override
6824             public ObservableList<?> getDependencies() {
6825                 return FXCollections.singletonObservableList(op);
6826             }
6827         };
6828     }
6829 
6830     /**
6831      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
6832      * if a given {@link javafx.collections.ObservableSet} is empty.
6833      *
6834      * @param op
6835      *            the {@code ObservableSet}
6836      * @param <E> the type of the {@code Set} elements
6837      * @return the new {@code BooleanBinding}
6838      * @throws NullPointerException
6839      *             if the {@code ObservableSet} is {@code null}
6840      * @since JavaFX 2.1
6841      */
6842     public static <E> BooleanBinding isEmpty(final ObservableSet<E> op) {
6843         if (op == null) {
6844             throw new NullPointerException("Set cannot be null.");
6845         }
6846 
6847         return new BooleanBinding() {
6848             {
6849                 super.bind(op);
6850             }
6851 
6852             @Override
6853             public void dispose() {
6854                 super.unbind(op);
6855             }
6856 
6857             @Override
6858             protected boolean computeValue() {
6859                 return op.isEmpty();
6860             }
6861 
6862             @Override
6863             public ObservableList<?> getDependencies() {
6864                 return FXCollections.singletonObservableList(op);
6865             }
6866         };
6867     }
6868 
6869     /**
6870      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
6871      * if a given {@link javafx.collections.ObservableSet} is not empty.
6872      *
6873      * @param op
6874      *            the {@code ObservableSet}
6875      * @param <E> the type of the {@code Set} elements
6876      * @return the new {@code BooleanBinding}
6877      * @throws NullPointerException
6878      *             if the {@code ObservableSet} is {@code null}
6879      * @since JavaFX 8.0
6880      */
6881     public static <E> BooleanBinding isNotEmpty(final ObservableSet<E> op)     {
6882         if (op == null) {
6883             throw new NullPointerException("List cannot be null.");
6884         }
6885 
6886         return new BooleanBinding() {
6887             {
6888                 super.bind(op);
6889             }
6890 
6891             @Override
6892             public void dispose() {
6893                 super.unbind(op);
6894             }
6895 
6896             @Override
6897             protected boolean computeValue() {
6898                 return !op.isEmpty();
6899             }
6900 
6901             @Override
6902             public ObservableList<?> getDependencies() {
6903                 return FXCollections.singletonObservableList(op);
6904             }
6905         };
6906     }
6907 
6908     // Array
6909     // =================================================================================================================
6910 
6911     /**
6912      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the size
6913      * of an {@link javafx.collections.ObservableArray}.
6914      *
6915      * @param op the {@code ObservableArray}
6916      * @return the new {@code IntegerBinding}
6917      * @throws NullPointerException
6918      *             if the {@code ObservableArray} is {@code null}
6919      * @since JavaFX 8.0
6920      */
6921     public static IntegerBinding size(final ObservableArray op) {
6922         if (op == null) {
6923             throw new NullPointerException("Array cannot be null.");
6924         }
6925 
6926         return new IntegerBinding() {
6927             {
6928                 super.bind(op);
6929             }
6930 
6931             @Override
6932             public void dispose() {
6933                 super.unbind(op);
6934             }
6935 
6936             @Override
6937             protected int computeValue() {
6938                 return op.size();
6939             }
6940 
6941             @Override
6942             public ObservableList<?> getDependencies() {
6943                 return FXCollections.singletonObservableList(op);
6944             }
6945         };
6946     }
6947 
6948     /**
6949      * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the element
6950      * of an {@link javafx.collections.ObservableArray} at the specified position. The {@code FloatBinding}
6951      * will hold {@code 0.0f}, if the {@code index} points behind the {@code ObservableArray}.
6952      *
6953      * @param op the {@code ObservableArray}
6954      * @param index the position in the {@code ObservableArray}
6955      * @return the new {@code FloatBinding}
6956      * @throws NullPointerException if the {@code ObservableArray} is {@code null}
6957      * @throws IllegalArgumentException if (@code index &lt; 0)
6958      * @since JavaFX 8.0
6959      */
6960     public static FloatBinding floatValueAt(final ObservableFloatArray op, final int index) {
6961         if (op == null) {
6962             throw new NullPointerException("Array cannot be null.");
6963         }
6964         if (index < 0) {
6965             throw new IllegalArgumentException("Index cannot be negative");
6966         }
6967 
6968         return new FloatBinding() {
6969             {
6970                 super.bind(op);
6971             }
6972 
6973             @Override
6974             public void dispose() {
6975                 super.unbind(op);
6976             }
6977 
6978             @Override
6979             protected float computeValue() {
6980                 try {
6981                     return op.get(index);
6982                 } catch (IndexOutOfBoundsException ex) {
6983                     Logging.getLogger().fine("Exception while evaluating binding", ex);
6984                 }
6985                 return 0.0f;
6986             }
6987 
6988             @Override
6989             public ObservableList<?> getDependencies() {
6990                 return FXCollections.singletonObservableList(op);
6991             }
6992         };
6993     }
6994 
6995     /**
6996      * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the element
6997      * of an {@link javafx.collections.ObservableArray} at the specified position. The {@code FloatBinding}
6998      * will hold {@code 0.0f}, if the {@code index} is outside of the {@code ObservableArray}.
6999      *
7000      * @param op the {@code ObservableArray}
7001      * @param index the position in the {@code ObservableArray}
7002      * @return the new {@code FloatBinding}
7003      * @throws NullPointerException if the {@code ObservableArray} or {@code index} is {@code null}
7004      * @since JavaFX 8.0
7005      */
7006     public static FloatBinding floatValueAt(final ObservableFloatArray op, final ObservableIntegerValue index) {
7007         return floatValueAt(op, (ObservableNumberValue)index);
7008     }
7009 
7010     /**
7011      * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the element
7012      * of an {@link javafx.collections.ObservableArray} at the specified position. The {@code FloatBinding}
7013      * will hold {@code 0.0f}, if the {@code index} is outside of the {@code ObservableArray}.
7014      *
7015      * @param op the {@code ObservableArray}
7016      * @param index the position in the {@code ObservableArray}, converted to int
7017      * @return the new {@code FloatBinding}
7018      * @throws NullPointerException if the {@code ObservableArray} or {@code index} is {@code null}
7019      * @since JavaFX 8.0
7020      */
7021     public static FloatBinding floatValueAt(final ObservableFloatArray op, final ObservableNumberValue index) {
7022         if ((op == null) || (index == null)) {
7023             throw new NullPointerException("Operands cannot be null.");
7024         }
7025 
7026         return new FloatBinding() {
7027             {
7028                 super.bind(op, index);
7029             }
7030 
7031             @Override
7032             public void dispose() {
7033                 super.unbind(op, index);
7034             }
7035 
7036             @Override
7037             protected float computeValue() {
7038                 try {
7039                     return op.get(index.intValue());
7040                 } catch (IndexOutOfBoundsException ex) {
7041                     Logging.getLogger().fine("Exception while evaluating binding", ex);
7042                 }
7043                 return 0.0f;
7044             }
7045 
7046             @Override
7047             public ObservableList<?> getDependencies() {
7048                 return new ImmutableObservableList<>(op, index);
7049             }
7050         };
7051     }
7052 
7053     /**
7054      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the element
7055      * of an {@link javafx.collections.ObservableArray} at the specified position. The {@code IntegerBinding}
7056      * will hold {@code 0}, if the {@code index} points behind the {@code ObservableArray}.
7057      *
7058      * @param op the {@code ObservableArray}
7059      * @param index the position in the {@code ObservableArray}
7060      * @return the new {@code IntegerBinding}
7061      * @throws NullPointerException if the {@code ObservableArray} is {@code null}
7062      * @throws IllegalArgumentException if (@code index &lt; 0)
7063      * @since JavaFX 8.0
7064      */
7065     public static IntegerBinding integerValueAt(final ObservableIntegerArray op, final int index) {
7066         if (op == null) {
7067             throw new NullPointerException("Array cannot be null.");
7068         }
7069         if (index < 0) {
7070             throw new IllegalArgumentException("Index cannot be negative");
7071         }
7072 
7073         return new IntegerBinding() {
7074             {
7075                 super.bind(op);
7076             }
7077 
7078             @Override
7079             public void dispose() {
7080                 super.unbind(op);
7081             }
7082 
7083             @Override
7084             protected int computeValue() {
7085                 try {
7086                     return op.get(index);
7087                 } catch (IndexOutOfBoundsException ex) {
7088                     Logging.getLogger().fine("Exception while evaluating binding", ex);
7089                 }
7090                 return 0;
7091             }
7092 
7093             @Override
7094             public ObservableList<?> getDependencies() {
7095                 return FXCollections.singletonObservableList(op);
7096             }
7097         };
7098     }
7099 
7100     /**
7101      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the element
7102      * of an {@link javafx.collections.ObservableArray} at the specified position. The {@code IntegerBinding}
7103      * will hold {@code 0}, if the {@code index} is outside of the {@code ObservableArray}.
7104      *
7105      * @param op the {@code ObservableArray}
7106      * @param index the position in the {@code ObservableArray}
7107      * @return the new {@code IntegerBinding}
7108      * @throws NullPointerException if the {@code ObservableArray} or {@code index} is {@code null}
7109      * @since JavaFX 8.0
7110      */
7111     public static IntegerBinding integerValueAt(final ObservableIntegerArray op, final ObservableIntegerValue index) {
7112         return integerValueAt(op, (ObservableNumberValue)index);
7113     }
7114 
7115     /**
7116      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the element
7117      * of an {@link javafx.collections.ObservableArray} at the specified position. The {@code IntegerBinding}
7118      * will hold {@code 0}, if the {@code index} is outside of the {@code ObservableArray}.
7119      *
7120      * @param op the {@code ObservableArray}
7121      * @param index the position in the {@code ObservableArray}, converted to int
7122      * @return the new {@code IntegerBinding}
7123      * @throws NullPointerException if the {@code ObservableArray} or {@code index} is {@code null}
7124      * @since JavaFX 8.0
7125      */
7126     public static IntegerBinding integerValueAt(final ObservableIntegerArray op, final ObservableNumberValue index) {
7127         if ((op == null) || (index == null)) {
7128             throw new NullPointerException("Operands cannot be null.");
7129         }
7130 
7131         return new IntegerBinding() {
7132             {
7133                 super.bind(op, index);
7134             }
7135 
7136             @Override
7137             public void dispose() {
7138                 super.unbind(op, index);
7139             }
7140 
7141             @Override
7142             protected int computeValue() {
7143                 try {
7144                     return op.get(index.intValue());
7145                 } catch (IndexOutOfBoundsException ex) {
7146                     Logging.getLogger().fine("Exception while evaluating binding", ex);
7147                 }
7148                 return 0;
7149             }
7150 
7151             @Override
7152             public ObservableList<?> getDependencies() {
7153                 return new ImmutableObservableList<>(op, index);
7154             }
7155         };
7156     }
7157 
7158     // Map
7159     // =================================================================================================================
7160 
7161     /**
7162      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the size
7163      * of an {@link javafx.collections.ObservableMap}.
7164      *
7165      * @param op
7166      *            the {@code ObservableMap}
7167      * @param <K> type of the key elements of the {@code Map}
7168      * @param <V> type of the value elements of the {@code Map}
7169      * @return the new {@code IntegerBinding}
7170      * @throws NullPointerException
7171      *             if the {@code ObservableMap} is {@code null}
7172      *
7173      * @since JavaFX 2.1
7174      */
7175     public static <K, V> IntegerBinding size(final ObservableMap<K, V> op) {
7176         if (op == null) {
7177             throw new NullPointerException("Map cannot be null.");
7178         }
7179 
7180         return new IntegerBinding() {
7181             {
7182                 super.bind(op);
7183             }
7184 
7185             @Override
7186             public void dispose() {
7187                 super.unbind(op);
7188             }
7189 
7190             @Override
7191             protected int computeValue() {
7192                 return op.size();
7193             }
7194 
7195             @Override
7196             public ObservableList<?> getDependencies() {
7197                 return FXCollections.singletonObservableList(op);
7198             }
7199         };
7200     }
7201 
7202     /**
7203      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
7204      * if a given {@link javafx.collections.ObservableMap} is empty.
7205      *
7206      * @param op
7207      *            the {@code ObservableMap}
7208      * @param <K> type of the key elements of the {@code Map}
7209      * @param <V> type of the value elements of the {@code Map}
7210      * @return the new {@code BooleanBinding}
7211      * @throws NullPointerException
7212      *             if the {@code ObservableMap} is {@code null}
7213      * @since JavaFX 2.1
7214      */
7215     public static <K, V> BooleanBinding isEmpty(final ObservableMap<K, V> op) {
7216         if (op == null) {
7217             throw new NullPointerException("Map cannot be null.");
7218         }
7219 
7220         return new BooleanBinding() {
7221             {
7222                 super.bind(op);
7223             }
7224 
7225             @Override
7226             public void dispose() {
7227                 super.unbind(op);
7228             }
7229 
7230             @Override
7231             protected boolean computeValue() {
7232                 return op.isEmpty();
7233             }
7234 
7235             @Override
7236             public ObservableList<?> getDependencies() {
7237                 return FXCollections.singletonObservableList(op);
7238             }
7239         };
7240     }
7241 
7242     /**
7243      * Creates a new {@link javafx.beans.binding.BooleanBinding} that holds {@code true}
7244      * if a given {@link javafx.collections.ObservableMap} is not empty.
7245      *
7246      * @param op
7247      *            the {@code ObservableMap}
7248      * @param <K> type of the key elements of the {@code Map}
7249      * @param <V> type of the value elements of the {@code Map}
7250      * @return the new {@code BooleanBinding}
7251      * @throws NullPointerException
7252      *             if the {@code ObservableMap} is {@code null}
7253      * @since JavaFX 8.0
7254      */
7255     public static <K, V> BooleanBinding isNotEmpty(final ObservableMap<K, V> op)     {
7256         if (op == null) {
7257             throw new NullPointerException("List cannot be null.");
7258         }
7259 
7260         return new BooleanBinding() {
7261             {
7262                 super.bind(op);
7263             }
7264 
7265             @Override
7266             public void dispose() {
7267                 super.unbind(op);
7268             }
7269 
7270             @Override
7271             protected boolean computeValue() {
7272                 return !op.isEmpty();
7273             }
7274 
7275             @Override
7276             public ObservableList<?> getDependencies() {
7277                 return FXCollections.singletonObservableList(op);
7278             }
7279         };
7280     }
7281 
7282     /**
7283      * Creates a new {@link javafx.beans.binding.ObjectBinding} that contains the mapping of a specific key
7284      * in an {@link javafx.collections.ObservableMap}.
7285      *
7286      * @param op the {@code ObservableMap}
7287      * @param key the key in the {@code Map}
7288      * @param <K> type of the key elements of the {@code Map}
7289      * @param <V> type of the value elements of the {@code Map}
7290      * @return the new {@code ObjectBinding}
7291      * @throws NullPointerException if the {@code ObservableMap} is {@code null}
7292      * @since JavaFX 2.1
7293      */
7294     public static <K, V> ObjectBinding<V> valueAt(final ObservableMap<K, V> op, final K key) {
7295         if (op == null) {
7296             throw new NullPointerException("Map cannot be null.");
7297         }
7298 
7299         return new ObjectBinding<V>() {
7300             {
7301                 super.bind(op);
7302             }
7303 
7304             @Override
7305             public void dispose() {
7306                 super.unbind(op);
7307             }
7308 
7309             @Override
7310             protected V computeValue() {
7311                 try {
7312                     return op.get(key);
7313                 } catch (ClassCastException ex) {
7314                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7315                     // ignore
7316                 } catch (NullPointerException ex) {
7317                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7318                     // ignore
7319                 }
7320                 return null;
7321             }
7322 
7323             @Override
7324             public ObservableList<?> getDependencies() {
7325                 return FXCollections.singletonObservableList(op);
7326             }
7327         };
7328     }
7329 
7330     /**
7331      * Creates a new {@link javafx.beans.binding.ObjectBinding} that contains the mapping of a specific key
7332      * in an {@link javafx.collections.ObservableMap}.
7333      *
7334      * @param op the {@code ObservableMap}
7335      * @param key the key in the {@code Map}
7336      * @param <K> type of the key elements of the {@code Map}
7337      * @param <V> type of the value elements of the {@code Map}
7338      * @return the new {@code ObjectBinding}
7339      * @throws NullPointerException if the {@code ObservableMap} or {@code key} is {@code null}
7340      * @since JavaFX 2.1
7341      */
7342     public static <K, V> ObjectBinding<V> valueAt(final ObservableMap<K, V> op, final ObservableValue<? extends K> key) {
7343         if ((op == null) || (key == null)) {
7344             throw new NullPointerException("Operands cannot be null.");
7345         }
7346 
7347         return new ObjectBinding<V>() {
7348             {
7349                 super.bind(op, key);
7350             }
7351 
7352             @Override
7353             public void dispose() {
7354                 super.unbind(op);
7355             }
7356 
7357             @Override
7358             protected V computeValue() {
7359                 try {
7360                     return op.get(key.getValue());
7361                 } catch (ClassCastException ex) {
7362                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7363                     // ignore
7364                 } catch (NullPointerException ex) {
7365                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7366                     // ignore
7367                 }
7368                 return null;
7369             }
7370 
7371             @Override
7372             public ObservableList<?> getDependencies() {
7373                 return new ImmutableObservableList<Observable>(op, key);
7374             }
7375         };
7376     }
7377 
7378     /**
7379      * Creates a new {@link javafx.beans.binding.BooleanBinding} that contains the mapping of a specific key
7380      * in an {@link javafx.collections.ObservableMap}. The {@code BooleanBinding}
7381      * will hold {@code false}, if the {@code key} cannot be found in the {@code ObservableMap}.
7382      *
7383      * @param op the {@code ObservableMap}
7384      * @param key the key in the {@code Map}
7385      * @param <K> type of the key elements of the {@code Map}
7386      * @return the new {@code BooleanBinding}
7387      * @throws NullPointerException if the {@code ObservableMap} is {@code null}
7388      * @since JavaFX 2.1
7389      */
7390     public static <K> BooleanBinding booleanValueAt(final ObservableMap<K, Boolean> op, final K key) {
7391         if (op == null) {
7392             throw new NullPointerException("Map cannot be null.");
7393         }
7394 
7395         return new BooleanBinding() {
7396             {
7397                 super.bind(op);
7398             }
7399 
7400             @Override
7401             public void dispose() {
7402                 super.unbind(op);
7403             }
7404 
7405             @Override
7406             protected boolean computeValue() {
7407                 try {
7408                     final Boolean value = op.get(key);
7409                     if (value == null) {
7410                         Logging.getLogger().fine("Element not found in map, returning default value instead.", new NullPointerException());
7411                     } else {
7412                         return value;
7413                     }
7414                 } catch (ClassCastException ex) {
7415                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7416                     // ignore
7417                 } catch (NullPointerException ex) {
7418                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7419                     // ignore
7420                 }
7421                 return false;
7422             }
7423 
7424             @Override
7425             public ObservableList<?> getDependencies() {
7426                 return FXCollections.singletonObservableList(op);
7427             }
7428         };
7429     }
7430 
7431     /**
7432      * Creates a new {@link javafx.beans.binding.BooleanBinding} that contains the mapping of a specific key
7433      * in an {@link javafx.collections.ObservableMap}. The {@code BooleanBinding}
7434      * will hold {@code false}, if the {@code key} cannot be found in the {@code ObservableMap}.
7435      *
7436      * @param op the {@code ObservableMap}
7437      * @param key the key in the {@code Map}
7438      * @param <K> type of the key elements of the {@code Map}
7439      * @return the new {@code BooleanBinding}
7440      * @throws NullPointerException if the {@code ObservableMap} or {@code key} is {@code null}
7441      * @since JavaFX 2.1
7442      */
7443     public static <K> BooleanBinding booleanValueAt(final ObservableMap<K, Boolean> op, final ObservableValue<? extends K> key) {
7444         if ((op == null) || (key == null)) {
7445             throw new NullPointerException("Operands cannot be null.");
7446         }
7447 
7448         return new BooleanBinding() {
7449             {
7450                 super.bind(op, key);
7451             }
7452 
7453             @Override
7454             public void dispose() {
7455                 super.unbind(op, key);
7456             }
7457 
7458             @Override
7459             protected boolean computeValue() {
7460                 try {
7461                     final Boolean value = op.get(key.getValue());
7462                     if (value == null) {
7463                         Logging.getLogger().fine("Element not found in map, returning default value instead.", new NullPointerException());
7464                     } else {
7465                         return value;
7466                     }
7467                 } catch (ClassCastException ex) {
7468                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7469                     // ignore
7470                 } catch (NullPointerException ex) {
7471                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7472                     // ignore
7473                 }
7474                 return false;
7475             }
7476 
7477             @Override
7478             public ObservableList<?> getDependencies() {
7479                 return new ImmutableObservableList<Observable>(op, key);
7480             }
7481         };
7482     }
7483 
7484     /**
7485      * Creates a new {@link javafx.beans.binding.DoubleBinding} that contains the mapping of a specific key
7486      * in an {@link javafx.collections.ObservableMap}. The {@code DoubleBinding}
7487      * will hold {@code 0.0}, if the {@code key} cannot be found in the {@code ObservableMap}.
7488      *
7489      * @param op the {@code ObservableMap}
7490      * @param key the key in the {@code Map}
7491      * @param <K> type of the key elements of the {@code Map}
7492      * @return the new {@code DoubleBinding}
7493      * @throws NullPointerException if the {@code ObservableMap} is {@code null}
7494      * @since JavaFX 2.1
7495      */
7496     public static <K> DoubleBinding doubleValueAt(final ObservableMap<K, ? extends Number> op, final K key) {
7497         if (op == null) {
7498             throw new NullPointerException("Map cannot be null.");
7499         }
7500 
7501         return new DoubleBinding() {
7502             {
7503                 super.bind(op);
7504             }
7505 
7506             @Override
7507             public void dispose() {
7508                 super.unbind(op);
7509             }
7510 
7511             @Override
7512             protected double computeValue() {
7513                 try {
7514                     final Number value = op.get(key);
7515                     if (value == null) {
7516                         Logging.getLogger().fine("Element not found in map, returning default value instead.", new NullPointerException());
7517                     } else {
7518                         return value.doubleValue();
7519                     }
7520                 } catch (ClassCastException ex) {
7521                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7522                     // ignore
7523                 } catch (NullPointerException ex) {
7524                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7525                     // ignore
7526                 }
7527                 return 0.0;
7528             }
7529 
7530             @Override
7531             public ObservableList<?> getDependencies() {
7532                 return FXCollections.singletonObservableList(op);
7533             }
7534         };
7535     }
7536 
7537     /**
7538      * Creates a new {@link javafx.beans.binding.DoubleBinding} that contains the mapping of a specific key
7539      * in an {@link javafx.collections.ObservableMap}. The {@code DoubleBinding}
7540      * will hold {@code 0.0}, if the {@code key} cannot be found in the {@code ObservableMap}.
7541      *
7542      * @param op the {@code ObservableMap}
7543      * @param key the key in the {@code Map}
7544      * @param <K> type of the key elements of the {@code Map}
7545      * @return the new {@code DoubleBinding}
7546      * @throws NullPointerException if the {@code ObservableMap} or {@code key} is {@code null}
7547      * @since JavaFX 2.1
7548      */
7549     public static <K> DoubleBinding doubleValueAt(final ObservableMap<K, ? extends Number> op, final ObservableValue<? extends K> key) {
7550         if ((op == null) || (key == null)) {
7551             throw new NullPointerException("Operands cannot be null.");
7552         }
7553 
7554         return new DoubleBinding() {
7555             {
7556                 super.bind(op, key);
7557             }
7558 
7559             @Override
7560             public void dispose() {
7561                 super.unbind(op, key);
7562             }
7563 
7564             @Override
7565             protected double computeValue() {
7566                 try {
7567                     final Number value = op.get(key.getValue());
7568                     if (value == null) {
7569                         Logging.getLogger().fine("Element not found in map, returning default value instead.", new NullPointerException());
7570                     } else {
7571                         return value.doubleValue();
7572                     }
7573                 } catch (ClassCastException ex) {
7574                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7575                     // ignore
7576                 } catch (NullPointerException ex) {
7577                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7578                     // ignore
7579                 }
7580                 return 0.0;
7581             }
7582 
7583             @Override
7584             public ObservableList<?> getDependencies() {
7585                 return new ImmutableObservableList<Observable>(op, key);
7586             }
7587         };
7588     }
7589 
7590     /**
7591      * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the mapping of a specific key
7592      * in an {@link javafx.collections.ObservableMap}. The {@code FloatBinding}
7593      * will hold {@code 0.0f}, if the {@code key} cannot be found in the {@code ObservableMap}.
7594      *
7595      * @param op the {@code ObservableMap}
7596      * @param key the key in the {@code Map}
7597      * @param <K> type of the key elements of the {@code Map}
7598      * @return the new {@code FloatBinding}
7599      * @throws NullPointerException if the {@code ObservableMap} is {@code null}
7600      * @since JavaFX 2.1
7601      */
7602     public static <K> FloatBinding floatValueAt(final ObservableMap<K, ? extends Number> op, final K key) {
7603         if (op == null) {
7604             throw new NullPointerException("Map cannot be null.");
7605         }
7606 
7607         return new FloatBinding() {
7608             {
7609                 super.bind(op);
7610             }
7611 
7612             @Override
7613             public void dispose() {
7614                 super.unbind(op);
7615             }
7616 
7617             @Override
7618             protected float computeValue() {
7619                 try {
7620                     final Number value = op.get(key);
7621                     if (value == null) {
7622                         Logging.getLogger().fine("Element not found in map, returning default value instead.", new NullPointerException());
7623                     } else {
7624                         return value.floatValue();
7625                     }
7626                 } catch (ClassCastException ex) {
7627                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7628                     // ignore
7629                 } catch (NullPointerException ex) {
7630                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7631                     // ignore
7632                 }
7633                 return 0.0f;
7634             }
7635 
7636             @Override
7637             public ObservableList<?> getDependencies() {
7638                 return FXCollections.singletonObservableList(op);
7639             }
7640         };
7641     }
7642 
7643     /**
7644      * Creates a new {@link javafx.beans.binding.FloatBinding} that contains the mapping of a specific key
7645      * in an {@link javafx.collections.ObservableMap}. The {@code FloatBinding}
7646      * will hold {@code 0.0f}, if the {@code key} cannot be found in the {@code ObservableMap}.
7647      *
7648      * @param op the {@code ObservableMap}
7649      * @param key the key in the {@code Map}
7650      * @param <K> type of the key elements of the {@code Map}
7651      * @return the new {@code FloatBinding}
7652      * @throws NullPointerException if the {@code ObservableMap} or {@code key} is {@code null}
7653      * @since JavaFX 2.1
7654      */
7655     public static <K> FloatBinding floatValueAt(final ObservableMap<K, ? extends Number> op, final ObservableValue<? extends K> key) {
7656         if ((op == null) || (key == null)) {
7657             throw new NullPointerException("Operands cannot be null.");
7658         }
7659 
7660         return new FloatBinding() {
7661             {
7662                 super.bind(op, key);
7663             }
7664 
7665             @Override
7666             public void dispose() {
7667                 super.unbind(op, key);
7668             }
7669 
7670             @Override
7671             protected float computeValue() {
7672                 try {
7673                     final Number value = op.get(key.getValue());
7674                     if (value == null) {
7675                         Logging.getLogger().fine("Element not found in map, returning default value instead.", new NullPointerException());
7676                     } else {
7677                         return value.floatValue();
7678                     }
7679                 } catch (ClassCastException ex) {
7680                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7681                     // ignore
7682                 } catch (NullPointerException ex) {
7683                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7684                     // ignore
7685                 }
7686                 return 0.0f;
7687             }
7688 
7689             @Override
7690             public ObservableList<?> getDependencies() {
7691                 return new ImmutableObservableList<Observable>(op, key);
7692             }
7693         };
7694     }
7695 
7696     /**
7697      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the mapping of a specific key
7698      * in an {@link javafx.collections.ObservableMap}. The {@code IntegerBinding}
7699      * will hold {@code 0}, if the {@code key} cannot be found in the {@code ObservableMap}.
7700      *
7701      * @param op the {@code ObservableMap}
7702      * @param key the key in the {@code Map}
7703      * @param <K> type of the key elements of the {@code Map}
7704      * @return the new {@code IntegerBinding}
7705      * @throws NullPointerException if the {@code ObservableMap} is {@code null}
7706      * @since JavaFX 2.1
7707      */
7708     public static <K> IntegerBinding integerValueAt(final ObservableMap<K, ? extends Number> op, final K key) {
7709         if (op == null) {
7710             throw new NullPointerException("Map cannot be null.");
7711         }
7712 
7713         return new IntegerBinding() {
7714             {
7715                 super.bind(op);
7716             }
7717 
7718             @Override
7719             public void dispose() {
7720                 super.unbind(op);
7721             }
7722 
7723             @Override
7724             protected int computeValue() {
7725                 try {
7726                     final Number value = op.get(key);
7727                     if (value == null) {
7728                         Logging.getLogger().fine("Element not found in map, returning default value instead.", new NullPointerException());
7729                     } else {
7730                         return value.intValue();
7731                     }
7732                 } catch (ClassCastException ex) {
7733                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7734                     // ignore
7735                 } catch (NullPointerException ex) {
7736                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7737                     // ignore
7738                 }
7739                 return 0;
7740             }
7741 
7742             @Override
7743             public ObservableList<?> getDependencies() {
7744                 return FXCollections.singletonObservableList(op);
7745             }
7746         };
7747     }
7748 
7749     /**
7750      * Creates a new {@link javafx.beans.binding.IntegerBinding} that contains the mapping of a specific key
7751      * in an {@link javafx.collections.ObservableMap}. The {@code IntegerBinding}
7752      * will hold {@code 0}, if the {@code key} cannot be found in the {@code ObservableMap}.
7753      *
7754      * @param op the {@code ObservableMap}
7755      * @param key the key in the {@code Map}
7756      * @param <K> type of the key elements of the {@code Map}
7757      * @return the new {@code IntegerBinding}
7758      * @throws NullPointerException if the {@code ObservableMap} or {@code key} is {@code null}
7759      * @since JavaFX 2.1
7760      */
7761     public static <K> IntegerBinding integerValueAt(final ObservableMap<K, ? extends Number> op, final ObservableValue<? extends K> key) {
7762         if ((op == null) || (key == null)) {
7763             throw new NullPointerException("Operands cannot be null.");
7764         }
7765 
7766         return new IntegerBinding() {
7767             {
7768                 super.bind(op, key);
7769             }
7770 
7771             @Override
7772             public void dispose() {
7773                 super.unbind(op, key);
7774             }
7775 
7776             @Override
7777             protected int computeValue() {
7778                 try {
7779                     final Number value = op.get(key.getValue());
7780                     if (value == null) {
7781                         Logging.getLogger().fine("Element not found in map, returning default value instead.", new NullPointerException());
7782                     } else {
7783                         return value.intValue();
7784                     }
7785                 } catch (ClassCastException ex) {
7786                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7787                     // ignore
7788                 } catch (NullPointerException ex) {
7789                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7790                     // ignore
7791                 }
7792                 return 0;
7793             }
7794 
7795             @Override
7796             public ObservableList<?> getDependencies() {
7797                 return new ImmutableObservableList<Observable>(op, key);
7798             }
7799         };
7800     }
7801 
7802     /**
7803      * Creates a new {@link javafx.beans.binding.LongBinding} that contains the mapping of a specific key
7804      * in an {@link javafx.collections.ObservableMap}. The {@code LongBinding}
7805      * will hold {@code 0L}, if the {@code key} cannot be found in the {@code ObservableMap}.
7806      *
7807      * @param op the {@code ObservableMap}
7808      * @param key the key in the {@code Map}
7809      * @param <K> type of the key elements of the {@code Map}
7810      * @return the new {@code LongBinding}
7811      * @throws NullPointerException if the {@code ObservableMap} is {@code null}
7812      * @since JavaFX 2.1
7813      */
7814     public static <K> LongBinding longValueAt(final ObservableMap<K, ? extends Number> op, final K key) {
7815         if (op == null) {
7816             throw new NullPointerException("Map cannot be null.");
7817         }
7818 
7819         return new LongBinding() {
7820             {
7821                 super.bind(op);
7822             }
7823 
7824             @Override
7825             public void dispose() {
7826                 super.unbind(op);
7827             }
7828 
7829             @Override
7830             protected long computeValue() {
7831                 try {
7832                     final Number value = op.get(key);
7833                     if (value == null) {
7834                         Logging.getLogger().fine("Element not found in map, returning default value instead.", new NullPointerException());
7835                     } else {
7836                         return value.longValue();
7837                     }
7838                 } catch (ClassCastException ex) {
7839                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7840                     // ignore
7841                 } catch (NullPointerException ex) {
7842                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7843                     // ignore
7844                 }
7845                 return 0L;
7846             }
7847 
7848             @Override
7849             public ObservableList<?> getDependencies() {
7850                 return FXCollections.singletonObservableList(op);
7851             }
7852         };
7853     }
7854 
7855     /**
7856      * Creates a new {@link javafx.beans.binding.LongBinding} that contains the mapping of a specific key
7857      * in an {@link javafx.collections.ObservableMap}. The {@code LongBinding}
7858      * will hold {@code 0L}, if the {@code key} cannot be found in the {@code ObservableMap}.
7859      *
7860      * @param op the {@code ObservableMap}
7861      * @param key the key in the {@code Map}
7862      * @param <K> type of the key elements of the {@code Map}
7863      * @return the new {@code LongBinding}
7864      * @throws NullPointerException if the {@code ObservableMap} or {@code key} is {@code null}
7865      * @since JavaFX 2.1
7866      */
7867     public static <K> LongBinding longValueAt(final ObservableMap<K, ? extends Number> op, final ObservableValue<? extends K> key) {
7868         if ((op == null) || (key == null)) {
7869             throw new NullPointerException("Operands cannot be null.");
7870         }
7871 
7872         return new LongBinding() {
7873             {
7874                 super.bind(op, key);
7875             }
7876 
7877             @Override
7878             public void dispose() {
7879                 super.unbind(op, key);
7880             }
7881 
7882             @Override
7883             protected long computeValue() {
7884                 try {
7885                     final Number value = op.get(key.getValue());
7886                     if (value == null) {
7887                         Logging.getLogger().fine("Element not found in map, returning default value instead.", new NullPointerException());
7888                     } else {
7889                         return value.longValue();
7890                     }
7891                 } catch (ClassCastException ex) {
7892                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7893                     // ignore
7894                 } catch (NullPointerException ex) {
7895                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7896                     // ignore
7897                 }
7898                 return 0L;
7899             }
7900 
7901             @Override
7902             public ObservableList<?> getDependencies() {
7903                 return new ImmutableObservableList<Observable>(op, key);
7904             }
7905         };
7906     }
7907 
7908     /**
7909      * Creates a new {@link javafx.beans.binding.StringBinding} that contains the mapping of a specific key
7910      * in an {@link javafx.collections.ObservableMap}. The {@code StringBinding}
7911      * will hold {@code null}, if the {@code key} cannot be found in the {@code ObservableMap}.
7912      *
7913      * @param op the {@code ObservableMap}
7914      * @param key the key in the {@code Map}
7915      * @param <K> type of the key elements of the {@code Map}
7916      * @return the new {@code StringBinding}
7917      * @throws NullPointerException if the {@code ObservableMap} is {@code null}
7918      * @since JavaFX 2.1
7919      */
7920     public static <K> StringBinding stringValueAt(final ObservableMap<K, String> op, final K key) {
7921         if (op == null) {
7922             throw new NullPointerException("Map cannot be null.");
7923         }
7924 
7925         return new StringBinding() {
7926             {
7927                 super.bind(op);
7928             }
7929 
7930             @Override
7931             public void dispose() {
7932                 super.unbind(op);
7933             }
7934 
7935             @Override
7936             protected String computeValue() {
7937                 try {
7938                     return op.get(key);
7939                 } catch (ClassCastException ex) {
7940                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7941                     // ignore
7942                 } catch (NullPointerException ex) {
7943                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7944                     // ignore
7945                 }
7946                 return null;
7947             }
7948 
7949             @Override
7950             public ObservableList<?> getDependencies() {
7951                 return FXCollections.singletonObservableList(op);
7952             }
7953         };
7954     }
7955 
7956     /**
7957      * Creates a new {@link javafx.beans.binding.StringBinding} that contains the mapping of a specific key
7958      * in an {@link javafx.collections.ObservableMap}. The {@code StringBinding}
7959      * will hold {@code ""}, if the {@code key} cannot be found in the {@code ObservableMap}.
7960      *
7961      * @param op the {@code ObservableMap}
7962      * @param key the key in the {@code Map}
7963      * @param <K> type of the key elements of the {@code Map}
7964      * @return the new {@code StringBinding}
7965      * @throws NullPointerException if the {@code ObservableMap} or {@code key} is {@code null}
7966      * @since JavaFX 2.1
7967      */
7968     public static <K> StringBinding stringValueAt(final ObservableMap<K, String> op, final ObservableValue<? extends K> key) {
7969         if ((op == null) || (key == null)) {
7970             throw new NullPointerException("Operands cannot be null.");
7971         }
7972 
7973         return new StringBinding() {
7974             {
7975                 super.bind(op, key);
7976             }
7977 
7978             @Override
7979             public void dispose() {
7980                 super.unbind(op, key);
7981             }
7982 
7983             @Override
7984             protected String computeValue() {
7985                 try {
7986                     return op.get(key.getValue());
7987                 } catch (ClassCastException ex) {
7988                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7989                     // ignore
7990                 } catch (NullPointerException ex) {
7991                     Logging.getLogger().warning("Exception while evaluating binding", ex);
7992                     // ignore
7993                 }
7994                 return null;
7995             }
7996 
7997             @Override
7998             public ObservableList<?> getDependencies() {
7999                 return new ImmutableObservableList<Observable>(op, key);
8000             }
8001         };
8002     }
8003 
8004 
8005 }