MappingBindings.java
0001 /*
0002  * Copyright 2008-2016 the original author or authors.
0003  *
0004  * Licensed under the Apache License, Version 2.0 (the "License");
0005  * you may not use this file except in compliance with the License.
0006  * You may obtain a copy of the License at
0007  *
0008  *     http://www.apache.org/licenses/LICENSE-2.0
0009  *
0010  * Unless required by applicable law or agreed to in writing, software
0011  * distributed under the License is distributed on an "AS IS" BASIS,
0012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013  * See the License for the specific language governing permissions and
0014  * limitations under the License.
0015  */
0016 package griffon.javafx.support;
0017 
0018 import javafx.beans.binding.BooleanBinding;
0019 import javafx.beans.binding.DoubleBinding;
0020 import javafx.beans.binding.FloatBinding;
0021 import javafx.beans.binding.IntegerBinding;
0022 import javafx.beans.binding.LongBinding;
0023 import javafx.beans.binding.ObjectBinding;
0024 import javafx.beans.binding.StringBinding;
0025 import javafx.beans.value.ObservableBooleanValue;
0026 import javafx.beans.value.ObservableDoubleValue;
0027 import javafx.beans.value.ObservableFloatValue;
0028 import javafx.beans.value.ObservableIntegerValue;
0029 import javafx.beans.value.ObservableLongValue;
0030 import javafx.beans.value.ObservableObjectValue;
0031 import javafx.beans.value.ObservableStringValue;
0032 import javafx.beans.value.ObservableValue;
0033 import javafx.collections.ObservableList;
0034 
0035 import javax.annotation.Nonnull;
0036 import javax.annotation.Nullable;
0037 import java.util.function.BiFunction;
0038 import java.util.function.Function;
0039 import java.util.function.Supplier;
0040 
0041 import static java.util.Objects.requireNonNull;
0042 import static javafx.beans.binding.Bindings.createBooleanBinding;
0043 import static javafx.beans.binding.Bindings.createDoubleBinding;
0044 import static javafx.beans.binding.Bindings.createFloatBinding;
0045 import static javafx.beans.binding.Bindings.createIntegerBinding;
0046 import static javafx.beans.binding.Bindings.createLongBinding;
0047 import static javafx.beans.binding.Bindings.createObjectBinding;
0048 import static javafx.beans.binding.Bindings.createStringBinding;
0049 
0050 /**
0051  @author Andres Almiray
0052  @since 2.9.0
0053  */
0054 public final class MappingBindings {
0055     private static final String ERROR_MAPPER_NULL = "Argument 'mapper' must not be null";
0056     private static final String ERROR_SUPPLIER_NULL = "Argument 'supplier' must not be null";
0057     private static final String ERROR_OBSERVABLE_NULL = "Argument 'observable' must not be null";
0058     private static final String ERROR_OBSERVABLE1_NULL = "Argument 'observable1' must not be null";
0059     private static final String ERROR_OBSERVABLE2_NULL = "Argument 'observable2' must not be null";
0060     private static final String ERROR_DEFAULT_VALUE_NULL = "Argument 'defaultValue' must not be null";
0061 
0062     private MappingBindings() {
0063         // prevent instantiation
0064     }
0065 
0066     /**
0067      * Converts a string object observable value into an object binding.
0068      *
0069      @param observable the observable to be converted.
0070      *
0071      @return an object binding.
0072      */
0073     @Nonnull
0074     public static ObjectBinding<String> mapToObject(@Nonnull final ObservableStringValue observable) {
0075         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0076         return createObjectBinding(observable::get, observable);
0077     }
0078 
0079     /**
0080      * Converts a boolean object observable value into an object binding.
0081      *
0082      @param observable the observable to be converted.
0083      *
0084      @return an object binding.
0085      */
0086     @Nonnull
0087     public static ObjectBinding<Boolean> mapToObject(@Nonnull final ObservableBooleanValue observable) {
0088         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0089         return createObjectBinding(observable::get, observable);
0090     }
0091 
0092     /**
0093      * Converts a integer object observable value into an object binding.
0094      *
0095      @param observable the observable to be converted.
0096      *
0097      @return an object binding.
0098      */
0099     @Nonnull
0100     public static ObjectBinding<Integer> mapToObject(@Nonnull final ObservableIntegerValue observable) {
0101         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0102         return createObjectBinding(observable::get, observable);
0103     }
0104 
0105     /**
0106      * Converts a long object observable value into an object binding.
0107      *
0108      @param observable the observable to be converted.
0109      *
0110      @return an object binding.
0111      */
0112     @Nonnull
0113     public static ObjectBinding<Long> mapToObject(@Nonnull final ObservableLongValue observable) {
0114         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0115         return createObjectBinding(observable::get, observable);
0116     }
0117 
0118     /**
0119      * Converts a float object observable value into an object binding.
0120      *
0121      @param observable the observable to be converted.
0122      *
0123      @return an object binding.
0124      */
0125     @Nonnull
0126     public static ObjectBinding<Float> mapToObject(@Nonnull final ObservableFloatValue observable) {
0127         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0128         return createObjectBinding(observable::get, observable);
0129     }
0130 
0131     /**
0132      * Converts a double object observable value into an object binding.
0133      *
0134      @param observable the observable to be converted.
0135      *
0136      @return an object binding.
0137      */
0138     @Nonnull
0139     public static ObjectBinding<Double> mapToObject(@Nonnull final ObservableDoubleValue observable) {
0140         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0141         return createObjectBinding(observable::get, observable);
0142     }
0143 
0144     /**
0145      * Converts a boolean object observable value into a boolean binding.
0146      *
0147      @param observable the observable to be converted.
0148      *
0149      @return a boolean binding.
0150      */
0151     @Nonnull
0152     public static BooleanBinding mapToBoolean(@Nonnull final ObservableObjectValue<Boolean> observable) {
0153         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0154         return createBooleanBinding(observable::get, observable);
0155     }
0156 
0157     /**
0158      * Converts a integer object observable value into a integer binding.
0159      *
0160      @param observable the observable to be converted.
0161      *
0162      @return a integer binding.
0163      */
0164     @Nonnull
0165     public static IntegerBinding mapToInteger(@Nonnull final ObservableObjectValue<Integer> observable) {
0166         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0167         return createIntegerBinding(observable::get, observable);
0168     }
0169 
0170     /**
0171      * Converts a long object observable value into a long binding.
0172      *
0173      @param observable the observable to be converted.
0174      *
0175      @return a long binding.
0176      */
0177     @Nonnull
0178     public static LongBinding mapToLong(@Nonnull final ObservableObjectValue<Long> observable) {
0179         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0180         return createLongBinding(observable::get, observable);
0181     }
0182 
0183     /**
0184      * Converts a float object observable value into a float binding.
0185      *
0186      @param observable the observable to be converted.
0187      *
0188      @return a float binding.
0189      */
0190     @Nonnull
0191     public static FloatBinding mapToFloat(@Nonnull final ObservableObjectValue<Float> observable) {
0192         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0193         return createFloatBinding(observable::get, observable);
0194     }
0195 
0196     /**
0197      * Converts a double object observable value into a double binding.
0198      *
0199      @param observable the observable to be converted.
0200      *
0201      @return a double binding.
0202      */
0203     @Nonnull
0204     public static DoubleBinding mapToDouble(@Nonnull final ObservableObjectValue<Double> observable) {
0205         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0206         return createDoubleBinding(observable::get, observable);
0207     }
0208 
0209     /**
0210      * Converts a literal object observable value into a string binding.
0211      *
0212      @param observable the observable to be converted.
0213      *
0214      @return a string binding.
0215      */
0216     @Nonnull
0217     public static StringBinding mapToString(@Nonnull final ObservableObjectValue<String> observable) {
0218         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0219         return createStringBinding(observable::get, observable);
0220     }
0221 
0222     /**
0223      * Creates an observable list where all elements of the source list are mapped by the supplied function.
0224      *
0225      @param source the source list.
0226      @param mapper a non-interfering, stateless function to apply to the reduced value.
0227      *
0228      @return an observable list.
0229      */
0230     @Nonnull
0231     public static <S, T> ObservableList<T> mapList(@Nonnull final ObservableList<? super S> source, @Nonnull final Function<S, T> mapper) {
0232         return new MappingObservableList<>((ObservableList<? extends S>source, mapper);
0233     }
0234 
0235     /**
0236      * Creates an observable list where all elements of the source list are mapped by the supplied function.
0237      *
0238      @param source the source list.
0239      @param mapper a non-interfering, stateless function to apply to the reduced value.
0240      *
0241      @return an observable list.
0242      */
0243     @Nonnull
0244     public static <S, T> ObservableList<T> mapList(@Nonnull final ObservableList<S> source, @Nonnull final ObservableValue<Function<S, T>> mapper) {
0245         return new MappingObservableList<>(source, mapper);
0246     }
0247 
0248     /**
0249      * Creates an object binding containing the value of the mapper function applied to the source observable.
0250      *
0251      @param observable the source observable.
0252      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0253      *
0254      @return an object binding.
0255      */
0256     @Nonnull
0257     public static <T, R> ObjectBinding<R> mapObject(@Nonnull final ObservableValue<T> observable, @Nonnull final Function<? super T, ? extends R> mapper) {
0258         return mapObject(observable, mapper, (Rnull);
0259     }
0260 
0261     /**
0262      * Creates an object binding containing the value of the mapper function applied to the source observable.
0263      *
0264      @param observable   the source observable.
0265      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0266      @param defaultValue the value to be returned if there is no value present, may be null.
0267      *
0268      @return an object binding.
0269      */
0270     @Nonnull
0271     public static <T, R> ObjectBinding<R> mapObject(@Nonnull final ObservableValue<T> observable, @Nonnull final Function<? super T, ? extends R> mapper, @Nullable final R defaultValue) {
0272         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0273         requireNonNull(mapper, ERROR_MAPPER_NULL);
0274         return createObjectBinding(() -> {
0275             T sourceValue = observable.getValue();
0276             return sourceValue == null ? defaultValue : mapper.apply(sourceValue);
0277         }, observable);
0278     }
0279 
0280     /**
0281      * Creates an object binding containing the value of the mapper function applied to the source observable.
0282      *
0283      @param observable the source observable.
0284      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0285      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0286      *
0287      @return an object binding.
0288      */
0289     @Nonnull
0290     public static <T, R> ObjectBinding<R> mapObject(@Nonnull final ObservableValue<T> observable, @Nonnull final Function<? super T, ? extends R> mapper, @Nonnull final Supplier<R> supplier) {
0291         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0292         requireNonNull(mapper, ERROR_MAPPER_NULL);
0293         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0294         return createObjectBinding(() -> {
0295             T sourceValue = observable.getValue();
0296             return sourceValue == null ? supplier.get() : mapper.apply(sourceValue);
0297         }, observable);
0298     }
0299 
0300     /**
0301      * Creates an object binding containing the value of the mapper function applied to the source observable.
0302      *
0303      @param observable the source observable.
0304      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0305      *
0306      @return an object binding.
0307      */
0308     @Nonnull
0309     public static <T, R> ObjectBinding<R> mapObject(@Nonnull final ObservableValue<T> observable, @Nonnull final ObservableValue<Function<? super T, ? extends R>> mapper) {
0310         return mapObject(observable, mapper, (Rnull);
0311     }
0312 
0313     /**
0314      * Creates an object binding containing the value of the mapper function applied to the source observable.
0315      *
0316      @param observable   the source observable.
0317      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0318      @param defaultValue the value to be returned if there is no value present, may be null.
0319      *
0320      @return an object binding.
0321      */
0322     @Nonnull
0323     public static <T, R> ObjectBinding<R> mapObject(@Nonnull final ObservableValue<T> observable, @Nonnull final ObservableValue<Function<? super T, ? extends R>> mapper, @Nullable final R defaultValue) {
0324         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0325         requireNonNull(mapper, ERROR_MAPPER_NULL);
0326         return createObjectBinding(() -> {
0327             T sourceValue = observable.getValue();
0328             Function<? super T, ? extends R> mapperValue = mapper.getValue();
0329             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0330             return sourceValue == null ? defaultValue : mapperValue.apply(sourceValue);
0331         }, observable, mapper);
0332     }
0333 
0334     /**
0335      * Creates an object binding containing the value of the mapper function applied to the source observable.
0336      *
0337      @param observable the source observable.
0338      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0339      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0340      *
0341      @return an object binding.
0342      */
0343     @Nonnull
0344     public static <T, R> ObjectBinding<R> mapObject(@Nonnull final ObservableValue<T> observable, @Nonnull final ObservableValue<Function<? super T, ? extends R>> mapper, @Nonnull final Supplier<R> supplier) {
0345         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0346         requireNonNull(mapper, ERROR_MAPPER_NULL);
0347         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0348         return createObjectBinding(() -> {
0349             T sourceValue = observable.getValue();
0350             Function<? super T, ? extends R> mapperValue = mapper.getValue();
0351             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0352             return sourceValue == null ? supplier.get() : mapperValue.apply(sourceValue);
0353         }, observable, mapper);
0354     }
0355 
0356     /**
0357      * Creates a boolean binding containing the value of the mapper function applied to the source observable.
0358      *
0359      @param observable the source observable.
0360      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0361      *
0362      @return a boolean binding.
0363      */
0364     @Nonnull
0365     public static BooleanBinding mapBoolean(@Nonnull final ObservableValue<Boolean> observable, @Nonnull final Function<Boolean, Boolean> mapper) {
0366         return mapBoolean(observable, mapper, false);
0367     }
0368 
0369     /**
0370      * Creates a boolean binding containing the value of the mapper function applied to the source observable.
0371      *
0372      @param observable   the source observable.
0373      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0374      @param defaultValue the value to be returned if there is no value present, may be null.
0375      *
0376      @return a boolean binding.
0377      */
0378     @Nonnull
0379     public static BooleanBinding mapBoolean(@Nonnull final ObservableValue<Boolean> observable, @Nonnull final Function<Boolean, Boolean> mapper, @Nonnull final Boolean defaultValue) {
0380         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0381         requireNonNull(mapper, ERROR_MAPPER_NULL);
0382         return createBooleanBinding(() -> {
0383             Boolean sourceValue = observable.getValue();
0384             return sourceValue == null ? defaultValue : mapper.apply(sourceValue);
0385         }, observable);
0386     }
0387 
0388     /**
0389      * Creates a boolean binding containing the value of the mapper function applied to the source observable.
0390      *
0391      @param observable the source observable.
0392      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0393      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0394      *
0395      @return a boolean binding.
0396      */
0397     @Nonnull
0398     public static BooleanBinding mapBoolean(@Nonnull final ObservableValue<Boolean> observable, @Nonnull final Function<Boolean, Boolean> mapper, @Nonnull final Supplier<Boolean> supplier) {
0399         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0400         requireNonNull(mapper, ERROR_MAPPER_NULL);
0401         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0402         return createBooleanBinding(() -> {
0403             Boolean sourceValue = observable.getValue();
0404             return sourceValue == null ? supplier.get() : mapper.apply(sourceValue);
0405         }, observable);
0406     }
0407 
0408     /**
0409      * Creates a boolean binding containing the value of the mapper function applied to the source observable.
0410      *
0411      @param observable the source observable.
0412      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0413      *
0414      @return a boolean binding.
0415      */
0416     @Nonnull
0417     public static BooleanBinding mapBoolean(@Nonnull final ObservableValue<Boolean> observable, @Nonnull final ObservableValue<Function<Boolean, Boolean>> mapper) {
0418         return mapBoolean(observable, mapper, false);
0419     }
0420 
0421     /**
0422      * Creates a boolean binding containing the value of the mapper function applied to the source observable.
0423      *
0424      @param observable   the source observable.
0425      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0426      @param defaultValue the value to be returned if there is no value present, may be null.
0427      *
0428      @return a boolean binding.
0429      */
0430     @Nonnull
0431     public static BooleanBinding mapBoolean(@Nonnull final ObservableValue<Boolean> observable, @Nonnull final ObservableValue<Function<Boolean, Boolean>> mapper, @Nonnull final Boolean defaultValue) {
0432         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0433         requireNonNull(mapper, ERROR_MAPPER_NULL);
0434         return createBooleanBinding(() -> {
0435             Boolean sourceValue = observable.getValue();
0436             Function<Boolean, Boolean> mapperValue = mapper.getValue();
0437             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0438             return sourceValue == null ? defaultValue : mapperValue.apply(sourceValue);
0439         }, observable, mapper);
0440     }
0441 
0442     /**
0443      * Creates a boolean binding containing the value of the mapper function applied to the source observable.
0444      *
0445      @param observable the source observable.
0446      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0447      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0448      *
0449      @return a boolean binding.
0450      */
0451     @Nonnull
0452     public static BooleanBinding mapBoolean(@Nonnull final ObservableValue<Boolean> observable, @Nonnull final ObservableValue<Function<Boolean, Boolean>> mapper, @Nonnull final Supplier<Boolean> supplier) {
0453         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0454         requireNonNull(mapper, ERROR_MAPPER_NULL);
0455         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0456         return createBooleanBinding(() -> {
0457             Boolean sourceValue = observable.getValue();
0458             Function<Boolean, Boolean> mapperValue = mapper.getValue();
0459             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0460             return sourceValue == null ? supplier.get() : mapperValue.apply(sourceValue);
0461         }, observable, mapper);
0462     }
0463 
0464     /**
0465      * Creates an integer binding containing the value of the mapper function applied to the source observable.
0466      *
0467      @param observable the source observable.
0468      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0469      *
0470      @return an integer binding.
0471      */
0472     @Nonnull
0473     public static IntegerBinding mapInteger(@Nonnull final ObservableValue<Integer> observable, @Nonnull final Function<Integer, Integer> mapper) {
0474         return mapInteger(observable, mapper, 0);
0475     }
0476 
0477     /**
0478      * Creates an integer binding containing the value of the mapper function applied to the source observable.
0479      *
0480      @param observable   the source observable.
0481      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0482      @param defaultValue the value to be returned if there is no value present, may be null.
0483      *
0484      @return an integer binding.
0485      */
0486     @Nonnull
0487     public static IntegerBinding mapInteger(@Nonnull final ObservableValue<Integer> observable, @Nonnull final Function<Integer, Integer> mapper, @Nonnull final Integer defaultValue) {
0488         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0489         requireNonNull(mapper, ERROR_MAPPER_NULL);
0490         return createIntegerBinding(() -> {
0491             Integer sourceValue = observable.getValue();
0492             return sourceValue == null ? defaultValue : mapper.apply(sourceValue);
0493         }, observable);
0494     }
0495 
0496 
0497     /**
0498      * Creates an integer binding containing the value of the mapper function applied to the source observable.
0499      *
0500      @param observable the source observable.
0501      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0502      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0503      *
0504      @return an integer binding.
0505      */
0506     @Nonnull
0507     public static IntegerBinding mapInteger(@Nonnull final ObservableValue<Integer> observable, @Nonnull final Function<Integer, Integer> mapper, @Nonnull final Supplier<Integer> supplier) {
0508         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0509         requireNonNull(mapper, ERROR_MAPPER_NULL);
0510         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0511         return createIntegerBinding(() -> {
0512             Integer sourceValue = observable.getValue();
0513             return sourceValue == null ? supplier.get() : mapper.apply(sourceValue);
0514         }, observable);
0515     }
0516 
0517     /**
0518      * Creates an integer binding containing the value of the mapper function applied to the source observable.
0519      *
0520      @param observable the source observable.
0521      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0522      *
0523      @return an integer binding.
0524      */
0525     @Nonnull
0526     public static IntegerBinding mapInteger(@Nonnull final ObservableValue<Integer> observable, @Nonnull final ObservableValue<Function<Integer, Integer>> mapper) {
0527         return mapInteger(observable, mapper, 0);
0528     }
0529 
0530     /**
0531      * Creates an integer binding containing the value of the mapper function applied to the source observable.
0532      *
0533      @param observable   the source observable.
0534      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0535      @param defaultValue the value to be returned if there is no value present, may be null.
0536      *
0537      @return an integer binding.
0538      */
0539     @Nonnull
0540     public static IntegerBinding mapInteger(@Nonnull final ObservableValue<Integer> observable, @Nonnull final ObservableValue<Function<Integer, Integer>> mapper, @Nonnull final Integer defaultValue) {
0541         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0542         requireNonNull(mapper, ERROR_MAPPER_NULL);
0543         return createIntegerBinding(() -> {
0544             Integer sourceValue = observable.getValue();
0545             Function<Integer, Integer> mapperValue = mapper.getValue();
0546             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0547             return sourceValue == null ? defaultValue : mapperValue.apply(sourceValue);
0548         }, observable, mapper);
0549     }
0550 
0551     /**
0552      * Creates an integer binding containing the value of the mapper function applied to the source observable.
0553      *
0554      @param observable the source observable.
0555      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0556      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0557      *
0558      @return an integer binding.
0559      */
0560     @Nonnull
0561     public static IntegerBinding mapInteger(@Nonnull final ObservableValue<Integer> observable, @Nonnull final ObservableValue<Function<Integer, Integer>> mapper, @Nonnull final Supplier<Integer> supplier) {
0562         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0563         requireNonNull(mapper, ERROR_MAPPER_NULL);
0564         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0565         return createIntegerBinding(() -> {
0566             Integer sourceValue = observable.getValue();
0567             Function<Integer, Integer> mapperValue = mapper.getValue();
0568             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0569             return sourceValue == null ? supplier.get() : mapperValue.apply(sourceValue);
0570         }, observable, mapper);
0571     }
0572 
0573     /**
0574      * Creates a long binding containing the value of the mapper function applied to the source observable.
0575      *
0576      @param observable the source observable.
0577      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0578      *
0579      @return a long binding.
0580      */
0581     @Nonnull
0582     public static LongBinding mapLong(@Nonnull final ObservableValue<Long> observable, @Nonnull final Function<Long, Long> mapper) {
0583         return mapLong(observable, mapper, 0L);
0584     }
0585 
0586     /**
0587      * Creates a long binding containing the value of the mapper function applied to the source observable.
0588      *
0589      @param observable   the source observable.
0590      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0591      @param defaultValue the value to be returned if there is no value present, may be null.
0592      *
0593      @return a long binding.
0594      */
0595     @Nonnull
0596     public static LongBinding mapLong(@Nonnull final ObservableValue<Long> observable, @Nonnull final Function<Long, Long> mapper, @Nonnull final Long defaultValue) {
0597         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0598         requireNonNull(mapper, ERROR_MAPPER_NULL);
0599         return createLongBinding(() -> {
0600             Long sourceValue = observable.getValue();
0601             return sourceValue == null ? defaultValue : mapper.apply(sourceValue);
0602         }, observable);
0603     }
0604 
0605 
0606     /**
0607      * Creates a long binding containing the value of the mapper function applied to the source observable.
0608      *
0609      @param observable the source observable.
0610      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0611      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0612      *
0613      @return a long binding.
0614      */
0615     @Nonnull
0616     public static LongBinding mapLong(@Nonnull final ObservableValue<Long> observable, @Nonnull final Function<Long, Long> mapper, @Nonnull final Supplier<Long> supplier) {
0617         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0618         requireNonNull(mapper, ERROR_MAPPER_NULL);
0619         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0620         return createLongBinding(() -> {
0621             Long sourceValue = observable.getValue();
0622             return sourceValue == null ? supplier.get() : mapper.apply(sourceValue);
0623         }, observable);
0624     }
0625 
0626     /**
0627      * Creates a long binding containing the value of the mapper function applied to the source observable.
0628      *
0629      @param observable the source observable.
0630      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0631      *
0632      @return a long binding.
0633      */
0634     @Nonnull
0635     public static LongBinding mapLong(@Nonnull final ObservableValue<Long> observable, @Nonnull final ObservableValue<Function<Long, Long>> mapper) {
0636         return mapLong(observable, mapper, 0L);
0637     }
0638 
0639     /**
0640      * Creates a long binding containing the value of the mapper function applied to the source observable.
0641      *
0642      @param observable   the source observable.
0643      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0644      @param defaultValue the value to be returned if there is no value present, may be null.
0645      *
0646      @return a long binding.
0647      */
0648     @Nonnull
0649     public static LongBinding mapLong(@Nonnull final ObservableValue<Long> observable, @Nonnull final ObservableValue<Function<Long, Long>> mapper, @Nonnull final Long defaultValue) {
0650         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0651         requireNonNull(mapper, ERROR_MAPPER_NULL);
0652         return createLongBinding(() -> {
0653             Long sourceValue = observable.getValue();
0654             Function<Long, Long> mapperValue = mapper.getValue();
0655             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0656             return sourceValue == null ? defaultValue : mapperValue.apply(sourceValue);
0657         }, observable, mapper);
0658     }
0659 
0660     /**
0661      * Creates a long binding containing the value of the mapper function applied to the source observable.
0662      *
0663      @param observable the source observable.
0664      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0665      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0666      *
0667      @return a long binding.
0668      */
0669     @Nonnull
0670     public static LongBinding mapLong(@Nonnull final ObservableValue<Long> observable, @Nonnull final ObservableValue<Function<Long, Long>> mapper, @Nonnull final Supplier<Long> supplier) {
0671         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0672         requireNonNull(mapper, ERROR_MAPPER_NULL);
0673         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0674         return createLongBinding(() -> {
0675             Long sourceValue = observable.getValue();
0676             Function<Long, Long> mapperValue = mapper.getValue();
0677             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0678             return sourceValue == null ? supplier.get() : mapperValue.apply(sourceValue);
0679         }, observable, mapper);
0680     }
0681 
0682     /**
0683      * Creates a float binding containing the value of the mapper function applied to the source observable.
0684      *
0685      @param observable the source observable.
0686      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0687      *
0688      @return a float binding.
0689      */
0690     @Nonnull
0691     public static FloatBinding mapFloat(@Nonnull final ObservableValue<Float> observable, @Nonnull final Function<Float, Float> mapper) {
0692         return mapFloat(observable, mapper, 0f);
0693     }
0694 
0695     /**
0696      * Creates a float binding containing the value of the mapper function applied to the source observable.
0697      *
0698      @param observable   the source observable.
0699      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0700      @param defaultValue the value to be returned if there is no value present, may be null.
0701      *
0702      @return a float binding.
0703      */
0704     @Nonnull
0705     public static FloatBinding mapFloat(@Nonnull final ObservableValue<Float> observable, @Nonnull final Function<Float, Float> mapper, @Nonnull final Float defaultValue) {
0706         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0707         requireNonNull(mapper, ERROR_MAPPER_NULL);
0708         return createFloatBinding(() -> {
0709             Float sourceValue = observable.getValue();
0710             return sourceValue == null ? defaultValue : mapper.apply(sourceValue);
0711         }, observable);
0712     }
0713 
0714     /**
0715      * Creates a float binding containing the value of the mapper function applied to the source observable.
0716      *
0717      @param observable the source observable.
0718      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0719      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0720      *
0721      @return a float binding.
0722      */
0723     @Nonnull
0724     public static FloatBinding mapFloat(@Nonnull final ObservableValue<Float> observable, @Nonnull final Function<Float, Float> mapper, @Nonnull final Supplier<Float> supplier) {
0725         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0726         requireNonNull(mapper, ERROR_MAPPER_NULL);
0727         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0728         return createFloatBinding(() -> {
0729             Float sourceValue = observable.getValue();
0730             return sourceValue == null ? supplier.get() : mapper.apply(sourceValue);
0731         }, observable);
0732     }
0733 
0734     /**
0735      * Creates a float binding containing the value of the mapper function applied to the source observable.
0736      *
0737      @param observable the source observable.
0738      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0739      *
0740      @return a float binding.
0741      */
0742     @Nonnull
0743     public static FloatBinding mapFloat(@Nonnull final ObservableValue<Float> observable, @Nonnull final ObservableValue<Function<Float, Float>> mapper) {
0744         return mapFloat(observable, mapper, 0f);
0745     }
0746 
0747     /**
0748      * Creates a float binding containing the value of the mapper function applied to the source observable.
0749      *
0750      @param observable   the source observable.
0751      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0752      @param defaultValue the value to be returned if there is no value present, may be null.
0753      *
0754      @return a float binding.
0755      */
0756     @Nonnull
0757     public static FloatBinding mapFloat(@Nonnull final ObservableValue<Float> observable, @Nonnull final ObservableValue<Function<Float, Float>> mapper, @Nullable final Float defaultValue) {
0758         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0759         requireNonNull(mapper, ERROR_MAPPER_NULL);
0760         return createFloatBinding(() -> {
0761             Float sourceValue = observable.getValue();
0762             Function<Float, Float> mapperValue = mapper.getValue();
0763             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0764             return sourceValue == null ? defaultValue : mapperValue.apply(sourceValue);
0765         }, observable, mapper);
0766     }
0767 
0768     /**
0769      * Creates a float binding containing the value of the mapper function applied to the source observable.
0770      *
0771      @param observable the source observable.
0772      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0773      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0774      *
0775      @return a float binding.
0776      */
0777     @Nonnull
0778     public static FloatBinding mapFloat(@Nonnull final ObservableValue<Float> observable, @Nonnull final ObservableValue<Function<Float, Float>> mapper, @Nonnull final Supplier<Float> supplier) {
0779         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0780         requireNonNull(mapper, ERROR_MAPPER_NULL);
0781         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0782         return createFloatBinding(() -> {
0783             Float sourceValue = observable.getValue();
0784             Function<Float, Float> mapperValue = mapper.getValue();
0785             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0786             return sourceValue == null ? supplier.get() : mapperValue.apply(sourceValue);
0787         }, observable, mapper);
0788     }
0789 
0790     /**
0791      * Creates a double binding containing the value of the mapper function applied to the source observable.
0792      *
0793      @param observable the source observable.
0794      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0795      *
0796      @return a double binding.
0797      */
0798     @Nonnull
0799     public static DoubleBinding mapDouble(@Nonnull final ObservableValue<Double> observable, @Nonnull final Function<Double, Double> mapper) {
0800         return mapDouble(observable, mapper, 0d);
0801     }
0802 
0803     /**
0804      * Creates a double binding containing the value of the mapper function applied to the source observable.
0805      *
0806      @param observable   the source observable.
0807      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0808      @param defaultValue the value to be returned if there is no value present, may be null.
0809      *
0810      @return a double binding.
0811      */
0812     @Nonnull
0813     public static DoubleBinding mapDouble(@Nonnull final ObservableValue<Double> observable, @Nonnull final Function<Double, Double> mapper, @Nullable final Double defaultValue) {
0814         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0815         requireNonNull(mapper, ERROR_MAPPER_NULL);
0816         return createDoubleBinding(() -> {
0817             Double sourceValue = observable.getValue();
0818             return sourceValue == null ? defaultValue : mapper.apply(sourceValue);
0819         }, observable);
0820     }
0821 
0822     /**
0823      * Creates a double binding containing the value of the mapper function applied to the source observable.
0824      *
0825      @param observable the source observable.
0826      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0827      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0828      *
0829      @return a double binding.
0830      */
0831     @Nonnull
0832     public static DoubleBinding mapDouble(@Nonnull final ObservableValue<Double> observable, @Nonnull final Function<Double, Double> mapper, @Nonnull final Supplier<Double> supplier) {
0833         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0834         requireNonNull(mapper, ERROR_MAPPER_NULL);
0835         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0836         return createDoubleBinding(() -> {
0837             Double sourceValue = observable.getValue();
0838             return sourceValue == null ? supplier.get() : mapper.apply(sourceValue);
0839         }, observable);
0840     }
0841 
0842     /**
0843      * Creates a double binding containing the value of the mapper function applied to the source observable.
0844      *
0845      @param observable the source observable.
0846      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0847      *
0848      @return a double binding.
0849      */
0850     @Nonnull
0851     public static DoubleBinding mapDouble(@Nonnull final ObservableValue<Double> observable, @Nonnull final ObservableValue<Function<Double, Double>> mapper) {
0852         return mapDouble(observable, mapper, 0d);
0853     }
0854 
0855     /**
0856      * Creates a double binding containing the value of the mapper function applied to the source observable.
0857      *
0858      @param observable   the source observable.
0859      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0860      @param defaultValue the value to be returned if there is no value present, may be null.
0861      *
0862      @return a double binding.
0863      */
0864     @Nonnull
0865     public static DoubleBinding mapDouble(@Nonnull final ObservableValue<Double> observable, @Nonnull final ObservableValue<Function<Double, Double>> mapper, @Nonnull final Double defaultValue) {
0866         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0867         requireNonNull(mapper, ERROR_MAPPER_NULL);
0868         return createDoubleBinding(() -> {
0869             Double sourceValue = observable.getValue();
0870             Function<Double, Double> mapperValue = mapper.getValue();
0871             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0872             return sourceValue == null ? defaultValue : mapperValue.apply(sourceValue);
0873         }, observable, mapper);
0874     }
0875 
0876     /**
0877      * Creates a double binding containing the value of the mapper function applied to the source observable.
0878      *
0879      @param observable the source observable.
0880      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0881      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0882      *
0883      @return a double binding.
0884      */
0885     @Nonnull
0886     public static DoubleBinding mapDouble(@Nonnull final ObservableValue<Double> observable, @Nonnull final ObservableValue<Function<Double, Double>> mapper, @Nonnull final Supplier<Double> supplier) {
0887         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0888         requireNonNull(mapper, ERROR_MAPPER_NULL);
0889         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0890         return createDoubleBinding(() -> {
0891             Double sourceValue = observable.getValue();
0892             Function<Double, Double> mapperValue = mapper.getValue();
0893             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0894             return sourceValue == null ? supplier.get() : mapperValue.apply(sourceValue);
0895         }, observable, mapper);
0896     }
0897 
0898     /**
0899      * Creates a string binding containing the value of the mapper function applied to the source observable.
0900      *
0901      @param observable the source observable.
0902      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0903      *
0904      @return a string binding.
0905      */
0906     @Nonnull
0907     public static StringBinding mapString(@Nonnull final ObservableValue<String> observable, @Nonnull final Function<String, String> mapper) {
0908         return mapString(observable, mapper, "");
0909     }
0910 
0911     /**
0912      * Creates a string binding containing the value of the mapper function applied to the source observable.
0913      *
0914      @param observable   the source observable.
0915      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0916      @param defaultValue the value to be returned if there is no value present, may be null.
0917      *
0918      @return a string binding.
0919      */
0920     @Nonnull
0921     public static StringBinding mapString(@Nonnull final ObservableValue<String> observable, @Nonnull final Function<String, String> mapper, @Nonnull final String defaultValue) {
0922         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0923         requireNonNull(mapper, ERROR_MAPPER_NULL);
0924         return createStringBinding(() -> {
0925             String sourceValue = observable.getValue();
0926             return sourceValue == null ? defaultValue : mapper.apply(sourceValue);
0927         }, observable);
0928     }
0929 
0930     /**
0931      * Creates a string binding containing the value of the mapper function applied to the source observable.
0932      *
0933      @param observable the source observable.
0934      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0935      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0936      *
0937      @return a string binding.
0938      */
0939     @Nonnull
0940     public static StringBinding mapString(@Nonnull final ObservableValue<String> observable, @Nonnull final Function<String, String> mapper, @Nonnull final Supplier<String> supplier) {
0941         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0942         requireNonNull(mapper, ERROR_MAPPER_NULL);
0943         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0944         return createStringBinding(() -> {
0945             String sourceValue = observable.getValue();
0946             return sourceValue == null ? supplier.get() : mapper.apply(sourceValue);
0947         }, observable);
0948     }
0949 
0950     /**
0951      * Creates a string binding containing the value of the mapper function applied to the source observable.
0952      *
0953      @param observable the source observable.
0954      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0955      *
0956      @return a string binding.
0957      */
0958     @Nonnull
0959     public static StringBinding mapString(@Nonnull final ObservableValue<String> observable, @Nonnull final ObservableValue<Function<String, String>> mapper) {
0960         return mapString(observable, mapper, "");
0961     }
0962 
0963     /**
0964      * Creates a string binding containing the value of the mapper function applied to the source observable.
0965      *
0966      @param observable   the source observable.
0967      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0968      @param defaultValue the value to be returned if there is no value present, may be null.
0969      *
0970      @return a string binding.
0971      */
0972     @Nonnull
0973     public static StringBinding mapString(@Nonnull final ObservableValue<String> observable, @Nonnull final ObservableValue<Function<String, String>> mapper, @Nonnull final String defaultValue) {
0974         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0975         requireNonNull(mapper, ERROR_MAPPER_NULL);
0976         return createStringBinding(() -> {
0977             String sourceValue = observable.getValue();
0978             Function<String, String> mapperValue = mapper.getValue();
0979             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0980             return sourceValue == null ? defaultValue : mapperValue.apply(sourceValue);
0981         }, observable, mapper);
0982     }
0983 
0984     /**
0985      * Creates a string binding containing the value of the mapper function applied to the source observable.
0986      *
0987      @param observable the source observable.
0988      @param mapper     a non-interfering, stateless function to apply to the reduced value.
0989      @param supplier   a {@code Supplier} whose result is returned if no value is present.
0990      *
0991      @return a string binding.
0992      */
0993     @Nonnull
0994     public static StringBinding mapString(@Nonnull final ObservableValue<String> observable, @Nonnull final ObservableValue<Function<String, String>> mapper, @Nonnull final Supplier<String> supplier) {
0995         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
0996         requireNonNull(mapper, ERROR_MAPPER_NULL);
0997         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0998         return createStringBinding(() -> {
0999             String sourceValue = observable.getValue();
1000             Function<String, String> mapperValue = mapper.getValue();
1001             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1002             return sourceValue == null ? supplier.get() : mapperValue.apply(sourceValue);
1003         }, observable, mapper);
1004     }
1005 
1006     /**
1007      * Returns a boolean binding whose value is the combination of two observable values.
1008      *
1009      @param observable1  the first observable value.
1010      @param observable2  the second observable value.
1011      @param defaultValue the value to be returned if there are no values present.
1012      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1013      *
1014      @return a boolean binding
1015      */
1016     @Nonnull
1017     public static BooleanBinding mapBooleans(@Nonnull final ObservableValue<Boolean> observable1, @Nonnull final ObservableValue<Boolean> observable2, @Nonnull final Boolean defaultValue, @Nonnull final BiFunction<Boolean, Boolean, Boolean> mapper) {
1018         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1019         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1020         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
1021         requireNonNull(mapper, ERROR_MAPPER_NULL);
1022         return createBooleanBinding(() -> {
1023             Boolean value1 = observable1.getValue();
1024             Boolean value2 = observable2.getValue();
1025             if (value1 != null && value2 != null) {
1026                 return mapper.apply(value1, value2);
1027             }
1028             return defaultValue;
1029         }, observable1, observable2);
1030     }
1031 
1032     /**
1033      * Returns a boolean binding whose value is the combination of two observable values.
1034      *
1035      @param observable1 the first observable value.
1036      @param observable2 the second observable value.
1037      @param supplier    a {@code Supplier} whose result is returned if no values are present.
1038      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1039      *
1040      @return a boolean binding
1041      */
1042     @Nonnull
1043     public static BooleanBinding mapBooleans(@Nonnull final ObservableValue<Boolean> observable1, @Nonnull final ObservableValue<Boolean> observable2, @Nonnull final Supplier<Boolean> supplier, @Nonnull final BiFunction<Boolean, Boolean, Boolean> mapper) {
1044         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1045         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1046         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1047         requireNonNull(mapper, ERROR_MAPPER_NULL);
1048         return createBooleanBinding(() -> {
1049             Boolean value1 = observable1.getValue();
1050             Boolean value2 = observable2.getValue();
1051             if (value1 != null && value2 != null) {
1052                 return mapper.apply(value1, value2);
1053             }
1054             return requireNonNull(supplier.get(), ERROR_DEFAULT_VALUE_NULL);
1055         }, observable1, observable2);
1056     }
1057 
1058     /**
1059      * Returns a boolean binding whose value is the combination of two observable values.
1060      *
1061      @param observable1  the first observable value.
1062      @param observable2  the second observable value.
1063      @param defaultValue the value to be returned if there is no value present.
1064      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1065      *
1066      @return a boolean binding
1067      */
1068     @Nonnull
1069     public static BooleanBinding mapBooleans(@Nonnull final ObservableValue<Boolean> observable1, @Nonnull final ObservableValue<Boolean> observable2, @Nonnull final Boolean defaultValue, @Nonnull final ObservableValue<BiFunction<Boolean, Boolean, Boolean>> mapper) {
1070         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1071         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1072         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
1073         requireNonNull(mapper, ERROR_MAPPER_NULL);
1074         return createBooleanBinding(() -> {
1075             Boolean value1 = observable1.getValue();
1076             Boolean value2 = observable2.getValue();
1077             if (value1 != null && value2 != null) {
1078                 BiFunction<Boolean, Boolean, Boolean> function = mapper.getValue();
1079                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1080             }
1081             return defaultValue;
1082         }, observable1, observable2, mapper);
1083     }
1084 
1085     /**
1086      * Returns a boolean binding whose value is the combination of two observable values.
1087      *
1088      @param observable1 the first observable value.
1089      @param observable2 the second observable value.
1090      @param supplier    a {@code Supplier} whose result is returned if no value is present.
1091      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1092      *
1093      @return a boolean binding
1094      */
1095     @Nonnull
1096     public static BooleanBinding mapBooleans(@Nonnull final ObservableValue<Boolean> observable1, @Nonnull final ObservableValue<Boolean> observable2, @Nonnull final Supplier<Boolean> supplier, @Nonnull final ObservableValue<BiFunction<Boolean, Boolean, Boolean>> mapper) {
1097         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1098         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1099         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1100         requireNonNull(mapper, ERROR_MAPPER_NULL);
1101         return createBooleanBinding(() -> {
1102             Boolean value1 = observable1.getValue();
1103             Boolean value2 = observable2.getValue();
1104             if (value1 != null && value2 != null) {
1105                 BiFunction<Boolean, Boolean, Boolean> function = mapper.getValue();
1106                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1107             }
1108             return requireNonNull(supplier.get(), ERROR_DEFAULT_VALUE_NULL);
1109         }, observable1, observable2, mapper);
1110     }
1111 
1112     /**
1113      * Returns an integer binding whose value is the combination of two observable values.
1114      *
1115      @param observable1  the first observable value.
1116      @param observable2  the second observable value.
1117      @param defaultValue the value to be returned if there are no values present.
1118      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1119      *
1120      @return an integer binding
1121      */
1122     @Nonnull
1123     public static IntegerBinding mapIntegers(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Integer defaultValue, @Nonnull final BiFunction<? super Number, ? super Number, Integer> mapper) {
1124         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1125         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1126         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
1127         requireNonNull(mapper, ERROR_MAPPER_NULL);
1128         return createIntegerBinding(() -> {
1129             Number value1 = observable1.getValue();
1130             Number value2 = observable2.getValue();
1131             if (value1 != null && value2 != null) {
1132                 return mapper.apply(value1, value2);
1133             }
1134             return defaultValue;
1135         }, observable1, observable2);
1136     }
1137 
1138     /**
1139      * Returns an integer binding whose value is the combination of two observable values.
1140      *
1141      @param observable1 the first observable value.
1142      @param observable2 the second observable value.
1143      @param supplier    a {@code Supplier} whose result is returned if no values are present.
1144      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1145      *
1146      @return an integer binding
1147      */
1148     @Nonnull
1149     public static IntegerBinding mapIntegers(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Supplier<Integer> supplier, @Nonnull final BiFunction<? super Number, ? super Number, Integer> mapper) {
1150         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1151         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1152         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1153         requireNonNull(mapper, ERROR_MAPPER_NULL);
1154         return createIntegerBinding(() -> {
1155             Number value1 = observable1.getValue();
1156             Number value2 = observable2.getValue();
1157             if (value1 != null && value2 != null) {
1158                 return mapper.apply(value1, value2);
1159             }
1160             return requireNonNull(supplier.get(), ERROR_DEFAULT_VALUE_NULL);
1161         }, observable1, observable2);
1162     }
1163 
1164     /**
1165      * Returns an integer binding whose value is the combination of two observable values.
1166      *
1167      @param observable1  the first observable value.
1168      @param observable2  the second observable value.
1169      @param defaultValue the value to be returned if there is no value present.
1170      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1171      *
1172      @return an integer binding
1173      */
1174     @Nonnull
1175     public static IntegerBinding mapIntegers(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Integer defaultValue, @Nonnull final ObservableValue<BiFunction<? super Number, ? super Number, Integer>> mapper) {
1176         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1177         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1178         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
1179         requireNonNull(mapper, ERROR_MAPPER_NULL);
1180         return createIntegerBinding(() -> {
1181             Number value1 = observable1.getValue();
1182             Number value2 = observable2.getValue();
1183             if (value1 != null && value2 != null) {
1184                 BiFunction<? super Number, ? super Number, Integer> function = mapper.getValue();
1185                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1186             }
1187             return defaultValue;
1188         }, observable1, observable2, mapper);
1189     }
1190 
1191     /**
1192      * Returns an integer binding whose value is the combination of two observable values.
1193      *
1194      @param observable1 the first observable value.
1195      @param observable2 the second observable value.
1196      @param supplier    a {@code Supplier} whose result is returned if no value is present.
1197      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1198      *
1199      @return an integer binding
1200      */
1201     @Nonnull
1202     public static IntegerBinding mapIntegers(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Supplier<Integer> supplier, @Nonnull final ObservableValue<BiFunction<? super Number, ? super Number, Integer>> mapper) {
1203         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1204         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1205         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1206         requireNonNull(mapper, ERROR_MAPPER_NULL);
1207         return createIntegerBinding(() -> {
1208             Number value1 = observable1.getValue();
1209             Number value2 = observable2.getValue();
1210             if (value1 != null && value2 != null) {
1211                 BiFunction<? super Number, ? super Number, Integer> function = mapper.getValue();
1212                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1213             }
1214             return requireNonNull(supplier.get(), ERROR_DEFAULT_VALUE_NULL);
1215         }, observable1, observable2, mapper);
1216     }
1217 
1218     /**
1219      * Returns a long binding whose value is the combination of two observable values.
1220      *
1221      @param observable1  the first observable value.
1222      @param observable2  the second observable value.
1223      @param defaultValue the value to be returned if there are no values present.
1224      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1225      *
1226      @return a long binding
1227      */
1228     @Nonnull
1229     public static LongBinding mapLongs(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Long defaultValue, @Nonnull final BiFunction<? super Number, ? super Number, Long> mapper) {
1230         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1231         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1232         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
1233         requireNonNull(mapper, ERROR_MAPPER_NULL);
1234         return createLongBinding(() -> {
1235             Number value1 = observable1.getValue();
1236             Number value2 = observable2.getValue();
1237             if (value1 != null && value2 != null) {
1238                 return mapper.apply(value1, value2);
1239             }
1240             return defaultValue;
1241         }, observable1, observable2);
1242     }
1243 
1244     /**
1245      * Returns a long binding whose value is the combination of two observable values.
1246      *
1247      @param observable1 the first observable value.
1248      @param observable2 the second observable value.
1249      @param supplier    a {@code Supplier} whose result is returned if no values are present.
1250      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1251      *
1252      @return a long binding
1253      */
1254     @Nonnull
1255     public static LongBinding mapLongs(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Supplier<Long> supplier, @Nonnull final BiFunction<? super Number, ? super Number, Long> mapper) {
1256         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1257         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1258         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1259         requireNonNull(mapper, ERROR_MAPPER_NULL);
1260         return createLongBinding(() -> {
1261             Number value1 = observable1.getValue();
1262             Number value2 = observable2.getValue();
1263             if (value1 != null && value2 != null) {
1264                 return mapper.apply(value1, value2);
1265             }
1266             return requireNonNull(supplier.get(), ERROR_DEFAULT_VALUE_NULL);
1267         }, observable1, observable2);
1268     }
1269 
1270     /**
1271      * Returns a long binding whose value is the combination of two observable values.
1272      *
1273      @param observable1  the first observable value.
1274      @param observable2  the second observable value.
1275      @param defaultValue the value to be returned if there is no value present.
1276      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1277      *
1278      @return a long binding
1279      */
1280     @Nonnull
1281     public static LongBinding mapLongs(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Long defaultValue, @Nonnull final ObservableValue<BiFunction<? super Number, ? super Number, Long>> mapper) {
1282         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1283         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1284         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
1285         requireNonNull(mapper, ERROR_MAPPER_NULL);
1286         return createLongBinding(() -> {
1287             Number value1 = observable1.getValue();
1288             Number value2 = observable2.getValue();
1289             if (value1 != null && value2 != null) {
1290                 BiFunction<? super Number, ? super Number, Long> function = mapper.getValue();
1291                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1292             }
1293             return defaultValue;
1294         }, observable1, observable2, mapper);
1295     }
1296 
1297     /**
1298      * Returns a long binding whose value is the combination of two observable values.
1299      *
1300      @param observable1 the first observable value.
1301      @param observable2 the second observable value.
1302      @param supplier    a {@code Supplier} whose result is returned if no value is present.
1303      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1304      *
1305      @return a long binding
1306      */
1307     @Nonnull
1308     public static LongBinding mapLongs(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Supplier<Long> supplier, @Nonnull final ObservableValue<BiFunction<? super Number, ? super Number, Long>> mapper) {
1309         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1310         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1311         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1312         requireNonNull(mapper, ERROR_MAPPER_NULL);
1313         return createLongBinding(() -> {
1314             Number value1 = observable1.getValue();
1315             Number value2 = observable2.getValue();
1316             if (value1 != null && value2 != null) {
1317                 BiFunction<? super Number, ? super Number, Long> function = mapper.getValue();
1318                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1319             }
1320             return requireNonNull(supplier.get(), ERROR_DEFAULT_VALUE_NULL);
1321         }, observable1, observable2, mapper);
1322     }
1323 
1324     /**
1325      * Returns a float binding whose value is the combination of two observable values.
1326      *
1327      @param observable1  the first observable value.
1328      @param observable2  the second observable value.
1329      @param defaultValue the value to be returned if there are no values present.
1330      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1331      *
1332      @return a float binding
1333      */
1334     @Nonnull
1335     public static FloatBinding mapFloats(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Float defaultValue, @Nonnull final BiFunction<? super Number, ? super Number, Float> mapper) {
1336         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1337         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1338         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
1339         requireNonNull(mapper, ERROR_MAPPER_NULL);
1340         return createFloatBinding(() -> {
1341             Number value1 = observable1.getValue();
1342             Number value2 = observable2.getValue();
1343             if (value1 != null && value2 != null) {
1344                 return mapper.apply(value1, value2);
1345             }
1346             return defaultValue;
1347         }, observable1, observable2);
1348     }
1349 
1350     /**
1351      * Returns a float binding whose value is the combination of two observable values.
1352      *
1353      @param observable1 the first observable value.
1354      @param observable2 the second observable value.
1355      @param supplier    a {@code Supplier} whose result is returned if no values are present.
1356      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1357      *
1358      @return a float binding
1359      */
1360     @Nonnull
1361     public static FloatBinding mapFloats(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Supplier<Float> supplier, @Nonnull final BiFunction<? super Number, ? super Number, Float> mapper) {
1362         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1363         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1364         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1365         requireNonNull(mapper, ERROR_MAPPER_NULL);
1366         return createFloatBinding(() -> {
1367             Number value1 = observable1.getValue();
1368             Number value2 = observable2.getValue();
1369             if (value1 != null && value2 != null) {
1370                 return mapper.apply(value1, value2);
1371             }
1372             return requireNonNull(supplier.get(), ERROR_DEFAULT_VALUE_NULL);
1373         }, observable1, observable2);
1374     }
1375 
1376     /**
1377      * Returns a float binding whose value is the combination of two observable values.
1378      *
1379      @param observable1  the first observable value.
1380      @param observable2  the second observable value.
1381      @param defaultValue the value to be returned if there is no value present.
1382      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1383      *
1384      @return a float binding
1385      */
1386     @Nonnull
1387     public static FloatBinding mapFloats(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Float defaultValue, @Nonnull final ObservableValue<BiFunction<? super Number, ? super Number, Float>> mapper) {
1388         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1389         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1390         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
1391         requireNonNull(mapper, ERROR_MAPPER_NULL);
1392         return createFloatBinding(() -> {
1393             Number value1 = observable1.getValue();
1394             Number value2 = observable2.getValue();
1395             if (value1 != null && value2 != null) {
1396                 BiFunction<? super Number, ? super Number, Float> function = mapper.getValue();
1397                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1398             }
1399             return defaultValue;
1400         }, observable1, observable2, mapper);
1401     }
1402 
1403     /**
1404      * Returns a float binding whose value is the combination of two observable values.
1405      *
1406      @param observable1 the first observable value.
1407      @param observable2 the second observable value.
1408      @param supplier    a {@code Supplier} whose result is returned if no value is present.
1409      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1410      *
1411      @return a float binding
1412      */
1413     @Nonnull
1414     public static FloatBinding mapFloats(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Supplier<Float> supplier, @Nonnull final ObservableValue<BiFunction<? super Number, ? super Number, Float>> mapper) {
1415         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1416         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1417         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1418         requireNonNull(mapper, ERROR_MAPPER_NULL);
1419         return createFloatBinding(() -> {
1420             Number value1 = observable1.getValue();
1421             Number value2 = observable2.getValue();
1422             if (value1 != null && value2 != null) {
1423                 BiFunction<? super Number, ? super Number, Float> function = mapper.getValue();
1424                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1425             }
1426             return requireNonNull(supplier.get(), ERROR_DEFAULT_VALUE_NULL);
1427         }, observable1, observable2, mapper);
1428     }
1429 
1430     /**
1431      * Returns a double binding whose value is the combination of two observable values.
1432      *
1433      @param observable1  the first observable value.
1434      @param observable2  the second observable value.
1435      @param defaultValue the value to be returned if there are no values present.
1436      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1437      *
1438      @return a double binding
1439      */
1440     @Nonnull
1441     public static DoubleBinding mapDoubles(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Double defaultValue, @Nonnull final BiFunction<? super Number, ? super Number, Double> mapper) {
1442         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1443         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1444         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
1445         requireNonNull(mapper, ERROR_MAPPER_NULL);
1446         return createDoubleBinding(() -> {
1447             Number value1 = observable1.getValue();
1448             Number value2 = observable2.getValue();
1449             if (value1 != null && value2 != null) {
1450                 return mapper.apply(value1, value2);
1451             }
1452             return defaultValue;
1453         }, observable1, observable2);
1454     }
1455 
1456     /**
1457      * Returns a double binding whose value is the combination of two observable values.
1458      *
1459      @param observable1 the first observable value.
1460      @param observable2 the second observable value.
1461      @param supplier    a {@code Supplier} whose result is returned if no values are present.
1462      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1463      *
1464      @return a double binding
1465      */
1466     @Nonnull
1467     public static DoubleBinding mapDoubles(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Supplier<Double> supplier, @Nonnull final BiFunction<? super Number, ? super Number, Double> mapper) {
1468         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1469         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1470         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1471         requireNonNull(mapper, ERROR_MAPPER_NULL);
1472         return createDoubleBinding(() -> {
1473             Number value1 = observable1.getValue();
1474             Number value2 = observable2.getValue();
1475             if (value1 != null && value2 != null) {
1476                 return mapper.apply(value1, value2);
1477             }
1478             return requireNonNull(supplier.get(), ERROR_DEFAULT_VALUE_NULL);
1479         }, observable1, observable2);
1480     }
1481 
1482     /**
1483      * Returns a double binding whose value is the combination of two observable values.
1484      *
1485      @param observable1  the first observable value.
1486      @param observable2  the second observable value.
1487      @param defaultValue the value to be returned if there is no value present.
1488      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1489      *
1490      @return a double binding
1491      */
1492     @Nonnull
1493     public static DoubleBinding mapDoubles(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Double defaultValue, @Nonnull final ObservableValue<BiFunction<? super Number, ? super Number, Double>> mapper) {
1494         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1495         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1496         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
1497         requireNonNull(mapper, ERROR_MAPPER_NULL);
1498         return createDoubleBinding(() -> {
1499             Number value1 = observable1.getValue();
1500             Number value2 = observable2.getValue();
1501             if (value1 != null && value2 != null) {
1502                 BiFunction<? super Number, ? super Number, Double> function = mapper.getValue();
1503                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1504             }
1505             return defaultValue;
1506         }, observable1, observable2, mapper);
1507     }
1508 
1509     /**
1510      * Returns a double binding whose value is the combination of two observable values.
1511      *
1512      @param observable1 the first observable value.
1513      @param observable2 the second observable value.
1514      @param supplier    a {@code Supplier} whose result is returned if no value is present.
1515      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1516      *
1517      @return a double binding
1518      */
1519     @Nonnull
1520     public static DoubleBinding mapDoubles(@Nonnull final ObservableValue<? extends Number> observable1, @Nonnull final ObservableValue<? extends Number> observable2, @Nonnull final Supplier<Double> supplier, @Nonnull final ObservableValue<BiFunction<? super Number, ? super Number, Double>> mapper) {
1521         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1522         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1523         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1524         requireNonNull(mapper, ERROR_MAPPER_NULL);
1525         return createDoubleBinding(() -> {
1526             Number value1 = observable1.getValue();
1527             Number value2 = observable2.getValue();
1528             if (value1 != null && value2 != null) {
1529                 BiFunction<? super Number, ? super Number, Double> function = mapper.getValue();
1530                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1531             }
1532             return requireNonNull(supplier.get(), ERROR_DEFAULT_VALUE_NULL);
1533         }, observable1, observable2, mapper);
1534     }
1535 
1536     /**
1537      * Returns an object binding whose value is the combination of two observable values.
1538      *
1539      @param observable1  the first observable value.
1540      @param observable2  the second observable value.
1541      @param defaultValue the value to be returned if there are no values present, may be null.
1542      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1543      *
1544      @return an object binding
1545      */
1546     @Nonnull
1547     public static <A, B, R> ObjectBinding<R> mapObjects(@Nonnull final ObservableValue<A> observable1, @Nonnull final ObservableValue<B> observable2, @Nullable final R defaultValue, @Nonnull final BiFunction<? super A, ? super B, R> mapper) {
1548         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1549         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1550         requireNonNull(mapper, ERROR_MAPPER_NULL);
1551         return createObjectBinding(() -> {
1552             A value1 = observable1.getValue();
1553             B value2 = observable2.getValue();
1554             if (value1 != null && value2 != null) {
1555                 return mapper.apply(value1, value2);
1556             }
1557             return defaultValue;
1558         }, observable1, observable2);
1559     }
1560 
1561     /**
1562      * Returns an object binding whose value is the combination of two observable values.
1563      *
1564      @param observable1 the first observable value.
1565      @param observable2 the second observable value.
1566      @param supplier    a {@code Supplier} whose result is returnedif no values are present.
1567      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1568      *
1569      @return an object binding
1570      */
1571     @Nonnull
1572     public static <A, B, R> ObjectBinding<R> mapObjects(@Nonnull final ObservableValue<A> observable1, @Nonnull final ObservableValue<B> observable2, @Nonnull final Supplier<R> supplier, @Nonnull final BiFunction<? super A, ? super B, R> mapper) {
1573         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1574         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1575         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1576         requireNonNull(mapper, ERROR_MAPPER_NULL);
1577         return createObjectBinding(() -> {
1578             A value1 = observable1.getValue();
1579             B value2 = observable2.getValue();
1580             if (value1 != null && value2 != null) {
1581                 return mapper.apply(value1, value2);
1582             }
1583             return supplier.get();
1584         }, observable1, observable2);
1585     }
1586 
1587     /**
1588      * Returns an object binding whose value is the combination of two observable values.
1589      *
1590      @param observable1  the first observable value.
1591      @param observable2  the second observable value.
1592      @param defaultValue the value to be returned if there is no value present, may be null.
1593      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1594      *
1595      @return an object binding
1596      */
1597     @Nonnull
1598     public static <A, B, R> ObjectBinding<R> mapObjects(@Nonnull final ObservableValue<A> observable1, @Nonnull final ObservableValue<B> observable2, @Nullable final R defaultValue, @Nonnull final ObservableValue<BiFunction<? super A, ? super B, R>> mapper) {
1599         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1600         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1601         requireNonNull(mapper, ERROR_MAPPER_NULL);
1602         return createObjectBinding(() -> {
1603             A value1 = observable1.getValue();
1604             B value2 = observable2.getValue();
1605             if (value1 != null && value2 != null) {
1606                 BiFunction<? super A, ? super B, R> function = mapper.getValue();
1607                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1608             }
1609             return defaultValue;
1610         }, observable1, observable2, mapper);
1611     }
1612 
1613     /**
1614      * Returns an object binding whose value is the combination of two observable values.
1615      *
1616      @param observable1 the first observable value.
1617      @param observable2 the second observable value.
1618      @param supplier    a {@code Supplier} whose result is returned if no values are present.
1619      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1620      *
1621      @return an object binding
1622      */
1623     @Nonnull
1624     public static <A, B, R> ObjectBinding<R> mapObjects(@Nonnull final ObservableValue<A> observable1, @Nonnull final ObservableValue<B> observable2, @Nonnull final Supplier<R> supplier, @Nonnull final ObservableValue<BiFunction<? super A, ? super B, R>> mapper) {
1625         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1626         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1627         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1628         requireNonNull(mapper, ERROR_MAPPER_NULL);
1629         return createObjectBinding(() -> {
1630             A value1 = observable1.getValue();
1631             B value2 = observable2.getValue();
1632             if (value1 != null && value2 != null) {
1633                 BiFunction<? super A, ? super B, R> function = mapper.getValue();
1634                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1635             }
1636             return supplier.get();
1637         }, observable1, observable2, mapper);
1638     }
1639 
1640     /**
1641      * Returns a string binding whose value is the combination of two observable values.
1642      *
1643      @param observable1  the first observable value.
1644      @param observable2  the second observable value.
1645      @param defaultValue the value to be returned if there are no values present.
1646      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1647      *
1648      @return a string binding
1649      */
1650     @Nonnull
1651     public static StringBinding mapStrings(@Nonnull final ObservableValue<String> observable1, @Nonnull final ObservableValue<String> observable2, @Nullable final String defaultValue, @Nonnull final BiFunction<String, String, String> mapper) {
1652         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1653         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1654         requireNonNull(mapper, ERROR_MAPPER_NULL);
1655         return createStringBinding(() -> {
1656             String value1 = observable1.getValue();
1657             String value2 = observable2.getValue();
1658             if (value1 != null && value2 != null) {
1659                 return mapper.apply(value1, value2);
1660             }
1661             return defaultValue;
1662         }, observable1, observable2);
1663     }
1664 
1665     /**
1666      * Returns a string binding whose value is the combination of two observable values.
1667      *
1668      @param observable1 the first observable value.
1669      @param observable2 the second observable value.
1670      @param supplier    a {@code Supplier} whose result is returned if no values are present.
1671      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1672      *
1673      @return a string binding
1674      */
1675     @Nonnull
1676     public static StringBinding mapStrings(@Nonnull final ObservableValue<String> observable1, @Nonnull final ObservableValue<String> observable2, @Nonnull final Supplier<String> supplier, @Nonnull final BiFunction<String, String, String> mapper) {
1677         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1678         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1679         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1680         requireNonNull(mapper, ERROR_MAPPER_NULL);
1681         return createStringBinding(() -> {
1682             String value1 = observable1.getValue();
1683             String value2 = observable2.getValue();
1684             if (value1 != null && value2 != null) {
1685                 return mapper.apply(value1, value2);
1686             }
1687             return supplier.get();
1688         }, observable1, observable2);
1689     }
1690 
1691     /**
1692      * Returns a string binding whose value is the combination of two observable values.
1693      *
1694      @param observable1  the first observable value.
1695      @param observable2  the second observable value.
1696      @param defaultValue the value to be returned if there is no value present, may be null.
1697      @param mapper       a non-interfering, stateless function to apply to the supplied values.
1698      *
1699      @return a string binding
1700      */
1701     @Nonnull
1702     public static StringBinding mapStrings(@Nonnull final ObservableValue<String> observable1, @Nonnull final ObservableValue<String> observable2, @Nullable final String defaultValue, @Nonnull final ObservableValue<BiFunction<String, String, String>> mapper) {
1703         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1704         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1705         requireNonNull(mapper, ERROR_MAPPER_NULL);
1706         return createStringBinding(() -> {
1707             String value1 = observable1.getValue();
1708             String value2 = observable2.getValue();
1709             if (value1 != null && value2 != null) {
1710                 BiFunction<String, String, String> function = mapper.getValue();
1711                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1712             }
1713             return defaultValue;
1714         }, observable1, observable2, mapper);
1715     }
1716 
1717     /**
1718      * Returns a string binding whose value is the combination of two observable values.
1719      *
1720      @param observable1 the first observable value.
1721      @param observable2 the second observable value.
1722      @param supplier    a {@code Supplier} whose result is returned if no values are present.
1723      @param mapper      a non-interfering, stateless function to apply to the supplied values.
1724      *
1725      @return a string binding
1726      */
1727     @Nonnull
1728     public static StringBinding mapStrings(@Nonnull final ObservableValue<String> observable1, @Nonnull final ObservableValue<String> observable2, @Nonnull final Supplier<String> supplier, @Nonnull final ObservableValue<BiFunction<String, String, String>> mapper) {
1729         requireNonNull(observable1, ERROR_OBSERVABLE1_NULL);
1730         requireNonNull(observable2, ERROR_OBSERVABLE2_NULL);
1731         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1732         requireNonNull(mapper, ERROR_MAPPER_NULL);
1733         return createStringBinding(() -> {
1734             String value1 = observable1.getValue();
1735             String value2 = observable2.getValue();
1736             if (value1 != null && value2 != null) {
1737                 BiFunction<String, String, String> function = mapper.getValue();
1738                 return requireNonNull(function, ERROR_MAPPER_NULL).apply(value1, value2);
1739             }
1740             return supplier.get();
1741         }, observable1, observable2, mapper);
1742     }
1743 
1744     /**
1745      * Creates an integer binding containing the value of the mapper function applied to the source observable.
1746      *
1747      @param observable the source observable.
1748      *
1749      @return an integer binding.
1750      */
1751     @Nonnull
1752     public static IntegerBinding mapInteger(@Nonnull final ObservableValue<? extends Number> observable) {
1753         return mapInteger(observable, 0);
1754     }
1755 
1756     /**
1757      * Creates an integer binding containing the value of the mapper function applied to the source observable.
1758      *
1759      @param observable   the source observable.
1760      @param defaultValue the value to be returned if there is no value present, may be null.
1761      *
1762      @return an integer binding.
1763      */
1764     @Nonnull
1765     public static IntegerBinding mapInteger(@Nonnull final ObservableValue<? extends Number> observable, @Nullable final Integer defaultValue) {
1766         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
1767         if (observable instanceof IntegerBinding) {
1768             return (IntegerBindingobservable;
1769         }
1770         return createIntegerBinding(() -> {
1771             Number value = observable.getValue();
1772             return value != null ? value.intValue() : defaultValue;
1773         }, observable);
1774     }
1775 
1776     /**
1777      * Creates an integer binding containing the value of the mapper function applied to the source observable.
1778      *
1779      @param observable the source observable.
1780      @param supplier   a {@code Supplier} whose result is returned if no value is present.
1781      *
1782      @return an integer binding.
1783      */
1784     @Nonnull
1785     public static IntegerBinding mapInteger(@Nonnull final ObservableValue<? extends Number> observable, @Nullable final Supplier<Integer> supplier) {
1786         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
1787         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1788         if (observable instanceof IntegerBinding) {
1789             return (IntegerBindingobservable;
1790         }
1791         return createIntegerBinding(() -> {
1792             Number value = observable.getValue();
1793             return value != null ? value.intValue() : supplier.get();
1794         }, observable);
1795     }
1796 
1797     /**
1798      * Creates a long binding containing the value of the mapper function applied to the source observable.
1799      *
1800      @param observable the source observable.
1801      *
1802      @return a long binding.
1803      */
1804     @Nonnull
1805     public static LongBinding mapLong(@Nonnull final ObservableValue<? extends Number> observable) {
1806         return mapLong(observable, 0L);
1807     }
1808 
1809     /**
1810      * Creates a long binding containing the value of the mapper function applied to the source observable.
1811      *
1812      @param observable   the source observable.
1813      @param defaultValue the value to be returned if there is no value present, may be null.
1814      *
1815      @return a long binding.
1816      */
1817     @Nonnull
1818     public static LongBinding mapLong(@Nonnull final ObservableValue<? extends Number> observable, @Nullable final Long defaultValue) {
1819         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
1820         if (observable instanceof LongBinding) {
1821             return (LongBindingobservable;
1822         }
1823         return createLongBinding(() -> {
1824             Number value = observable.getValue();
1825             return value != null ? value.longValue() : defaultValue;
1826         }, observable);
1827     }
1828 
1829     /**
1830      * Creates a long binding containing the value of the mapper function applied to the source observable.
1831      *
1832      @param observable the source observable.
1833      @param supplier   a {@code Supplier} whose result is returned if no value is present.
1834      *
1835      @return a long binding.
1836      */
1837     @Nonnull
1838     public static LongBinding mapLong(@Nonnull final ObservableValue<? extends Number> observable, @Nullable final Supplier<Long> supplier) {
1839         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
1840         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1841         if (observable instanceof LongBinding) {
1842             return (LongBindingobservable;
1843         }
1844         return createLongBinding(() -> {
1845             Number value = observable.getValue();
1846             return value != null ? value.longValue() : supplier.get();
1847         }, observable);
1848     }
1849 
1850     /**
1851      * Creates a float binding containing the value of the mapper function applied to the source observable.
1852      *
1853      @param observable the source observable.
1854      *
1855      @return a float binding.
1856      */
1857     @Nonnull
1858     public static FloatBinding mapFloat(@Nonnull final ObservableValue<? extends Number> observable) {
1859         return mapFloat(observable, 0f);
1860     }
1861 
1862     /**
1863      * Creates a float binding containing the value of the mapper function applied to the source observable.
1864      *
1865      @param observable   the source observable.
1866      @param defaultValue the value to be returned if there is no value present, may be null.
1867      *
1868      @return a float binding.
1869      */
1870     @Nonnull
1871     public static FloatBinding mapFloat(@Nonnull final ObservableValue<? extends Number> observable, @Nullable final Float defaultValue) {
1872         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
1873         if (observable instanceof FloatBinding) {
1874             return (FloatBindingobservable;
1875         }
1876         return createFloatBinding(() -> {
1877             Number value = observable.getValue();
1878             return value != null ? value.floatValue() : defaultValue;
1879         }, observable);
1880     }
1881 
1882     /**
1883      * Creates a float binding containing the value of the mapper function applied to the source observable.
1884      *
1885      @param observable the source observable.
1886      @param supplier   a {@code Supplier} whose result is returned if no value is present.
1887      *
1888      @return a float binding.
1889      */
1890     @Nonnull
1891     public static FloatBinding mapFloat(@Nonnull final ObservableValue<? extends Number> observable, @Nullable final Supplier<Float> supplier) {
1892         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
1893         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1894         if (observable instanceof FloatBinding) {
1895             return (FloatBindingobservable;
1896         }
1897         return createFloatBinding(() -> {
1898             Number value = observable.getValue();
1899             return value != null ? value.floatValue() : supplier.get();
1900         }, observable);
1901     }
1902 
1903     /**
1904      * Creates a double binding containing the value of the mapper function applied to the source observable.
1905      *
1906      @param observable the source observable.
1907      *
1908      @return a double binding.
1909      */
1910     @Nonnull
1911     public static DoubleBinding mapDouble(@Nonnull final ObservableValue<? extends Number> observable) {
1912         return mapDouble(observable, 0d);
1913     }
1914 
1915     /**
1916      * Creates a double binding containing the value of the mapper function applied to the source observable.
1917      *
1918      @param observable   the source observable.
1919      @param defaultValue the value to be returned if there is no value present, may be null.
1920      *
1921      @return a double binding.
1922      */
1923     @Nonnull
1924     public static DoubleBinding mapDouble(@Nonnull final ObservableValue<? extends Number> observable, @Nullable final Double defaultValue) {
1925         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
1926         if (observable instanceof DoubleBinding) {
1927             return (DoubleBindingobservable;
1928         }
1929         return createDoubleBinding(() -> {
1930             Number value = observable.getValue();
1931             return value != null ? value.doubleValue() : defaultValue;
1932         }, observable);
1933     }
1934 
1935     /**
1936      * Creates a double binding containing the value of the mapper function applied to the source observable.
1937      *
1938      @param observable the source observable.
1939      @param supplier   a {@code Supplier} whose result is returned if no value is present.
1940      *
1941      @return a double binding.
1942      */
1943     @Nonnull
1944     public static DoubleBinding mapDouble(@Nonnull final ObservableValue<? extends Number> observable, @Nullable final Supplier<Double> supplier) {
1945         requireNonNull(observable, ERROR_OBSERVABLE_NULL);
1946         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1947         if (observable instanceof DoubleBinding) {
1948             return (DoubleBindingobservable;
1949         }
1950         return createDoubleBinding(() -> {
1951             Number value = observable.getValue();
1952             return value != null ? value.doubleValue() : supplier.get();
1953         }, observable);
1954     }
1955 }