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