| 
0001 /*0002  * Copyright 2008-2017 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.beans.binding;
 0017
 0018 import javafx.beans.binding.NumberBinding;
 0019 import javafx.beans.binding.StringBinding;
 0020 import javafx.beans.value.ObservableValue;
 0021 import javafx.collections.ObservableList;
 0022 import javafx.collections.ObservableMap;
 0023 import javafx.collections.ObservableSet;
 0024
 0025 import javax.annotation.Nonnull;
 0026 import javax.annotation.Nullable;
 0027 import java.util.Map;
 0028 import java.util.function.DoubleSupplier;
 0029 import java.util.function.Function;
 0030 import java.util.function.Supplier;
 0031 import java.util.function.ToDoubleFunction;
 0032
 0033 import static java.util.Objects.requireNonNull;
 0034 import static java.util.stream.Collectors.joining;
 0035 import static javafx.beans.binding.Bindings.createDoubleBinding;
 0036 import static javafx.beans.binding.Bindings.createStringBinding;
 0037
 0038 /**
 0039  * @author Andres Almiray
 0040  * @since 2.10.0
 0041  */
 0042 public final class CollectionBindings {
 0043     private static final String ERROR_ITEMS_NULL = "Argument 'items' must not be null";
 0044     private static final String ERROR_MAPPER_NULL = "Argument 'mapper' must not be null";
 0045     private static final String ERROR_SUPPLIER_NULL = "Argument 'supplier' must not be null";
 0046     private static final String ERROR_DELIMITER_NULL = "Argument 'delimiter' must not be null";
 0047     private static final String ERROR_DEFAULT_VALUE_NULL = "Argument 'defaultValue' must not be null";
 0048
 0049     private CollectionBindings() {
 0050         // prevent instantiation
 0051     }
 0052
 0053     /**
 0054      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0055      *
 0056      * @param items     the observable list of items.
 0057      * @param delimiter the sequence of characters to be used between each element.
 0058      *
 0059      * @return a string binding.
 0060      */
 0061     @Nonnull
 0062     public static StringBinding joinList(@Nonnull final ObservableList<?> items, @Nullable final String delimiter) {
 0063         return joinList(items, delimiter, String::valueOf);
 0064     }
 0065
 0066     /**
 0067      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0068      *
 0069      * @param items     the observable list of items.
 0070      * @param delimiter the sequence of characters to be used between each element.
 0071      * @param mapper    a non-interfering, stateless function to apply to the each element.
 0072      *
 0073      * @return a string binding.
 0074      */
 0075     @Nonnull
 0076     public static <T> StringBinding joinList(@Nonnull final ObservableList<T> items, @Nullable final String delimiter, @Nonnull final Function<? super T, String> mapper) {
 0077         requireNonNull(items, ERROR_ITEMS_NULL);
 0078         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0079         final String value = delimiter == null ? "" : delimiter;
 0080         return createStringBinding(() -> items.stream().map(mapper).collect(joining(value)), items);
 0081     }
 0082
 0083     /**
 0084      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0085      *
 0086      * @param items     the observable list of items.
 0087      * @param delimiter the sequence of characters to be used between each element.
 0088      *
 0089      * @return a string binding.
 0090      */
 0091     @Nonnull
 0092     public static StringBinding joinList(@Nonnull final ObservableList<?> items, @Nonnull final ObservableValue<String> delimiter) {
 0093         requireNonNull(items, ERROR_ITEMS_NULL);
 0094         requireNonNull(delimiter, ERROR_DELIMITER_NULL);
 0095         return createStringBinding(() -> {
 0096             String value = delimiter.getValue();
 0097             value = value == null ? "" : value;
 0098             return items.stream().map(String::valueOf).collect(joining(value));
 0099         }, items, delimiter);
 0100     }
 0101
 0102     /**
 0103      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0104      *
 0105      * @param items     the observable list of items.
 0106      * @param delimiter the sequence of characters to be used between each element.
 0107      * @param mapper    a non-interfering, stateless function to apply to the each element.
 0108      *
 0109      * @return a string binding.
 0110      */
 0111     @Nonnull
 0112     public static <T> StringBinding joinList(@Nonnull final ObservableList<T> items, @Nonnull final ObservableValue<String> delimiter, @Nonnull final ObservableValue<Function<? super T, String>> mapper) {
 0113         requireNonNull(items, ERROR_ITEMS_NULL);
 0114         requireNonNull(delimiter, ERROR_DELIMITER_NULL);
 0115         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0116         return createStringBinding(() -> {
 0117             String value = delimiter.getValue();
 0118             value = value == null ? "" : value;
 0119             final Function<? super T, String> mapperValue = mapper.getValue() != null ? mapper.getValue() : String::valueOf;
 0120             return items.stream().map(mapperValue).collect(joining(value));
 0121         }, items, delimiter, mapper);
 0122     }
 0123
 0124     /**
 0125      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0126      *
 0127      * @param items     the observable set of items.
 0128      * @param delimiter the sequence of characters to be used between each element.
 0129      *
 0130      * @return a string binding.
 0131      */
 0132     @Nonnull
 0133     public static StringBinding joinSet(@Nonnull final ObservableSet<?> items, @Nullable final String delimiter) {
 0134         return joinSet(items, delimiter, String::valueOf);
 0135     }
 0136
 0137     /**
 0138      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0139      *
 0140      * @param items     the observable set of items.
 0141      * @param delimiter the sequence of characters to be used between each element.
 0142      * @param mapper    a non-interfering, stateless function to apply to the each element.
 0143      *
 0144      * @return a string binding.
 0145      */
 0146     @Nonnull
 0147     public static <T> StringBinding joinSet(@Nonnull final ObservableSet<T> items, @Nullable final String delimiter, @Nonnull final Function<? super T, String> mapper) {
 0148         requireNonNull(items, ERROR_ITEMS_NULL);
 0149         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0150         final String value = delimiter == null ? "" : delimiter;
 0151         return createStringBinding(() -> items.stream().map(mapper).collect(joining(value)), items);
 0152     }
 0153
 0154     /**
 0155      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0156      *
 0157      * @param items     the observable set of items.
 0158      * @param delimiter the sequence of characters to be used between each element.
 0159      *
 0160      * @return a string binding.
 0161      */
 0162     @Nonnull
 0163     public static StringBinding joinSet(@Nonnull final ObservableSet<?> items, @Nonnull final ObservableValue<String> delimiter) {
 0164         requireNonNull(items, ERROR_ITEMS_NULL);
 0165         requireNonNull(delimiter, ERROR_DELIMITER_NULL);
 0166         return createStringBinding(() -> {
 0167             String value = delimiter.getValue();
 0168             value = value == null ? "" : value;
 0169             return items.stream().map(String::valueOf).collect(joining(value));
 0170         }, items, delimiter);
 0171     }
 0172
 0173     /**
 0174      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0175      *
 0176      * @param items     the observable set of items.
 0177      * @param delimiter the sequence of characters to be used between each element.
 0178      * @param mapper    a non-interfering, stateless function to apply to the each element.
 0179      *
 0180      * @return a string binding.
 0181      */
 0182     @Nonnull
 0183     public static <T> StringBinding joinSet(@Nonnull final ObservableSet<T> items, @Nonnull final ObservableValue<String> delimiter, @Nonnull final ObservableValue<Function<? super T, String>> mapper) {
 0184         requireNonNull(items, ERROR_ITEMS_NULL);
 0185         requireNonNull(delimiter, ERROR_DELIMITER_NULL);
 0186         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0187         return createStringBinding(() -> {
 0188             String value = delimiter.getValue();
 0189             value = value == null ? "" : value;
 0190             final Function<? super T, String> mapperValue = mapper.getValue() != null ? mapper.getValue() : String::valueOf;
 0191             return items.stream().map(mapperValue).collect(joining(value));
 0192         }, items, delimiter, mapper);
 0193     }
 0194
 0195     /**
 0196      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0197      *
 0198      * @param items     the observable map of items.
 0199      * @param delimiter the sequence of characters to be used between each entry.
 0200      *
 0201      * @return a string binding.
 0202      */
 0203     @Nonnull
 0204     public static <K, V> StringBinding joinMap(@Nonnull final ObservableMap<K, V> items, @Nullable final String delimiter) {
 0205         return joinMap(items, delimiter, entry -> String.valueOf(entry.getKey()) + "=" + String.valueOf(entry.getValue()));
 0206     }
 0207
 0208     /**
 0209      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0210      *
 0211      * @param items     the observable map of items.
 0212      * @param delimiter the sequence of characters to be used between each element.
 0213      * @param mapper    a non-interfering, stateless function to apply to the each entry.
 0214      *
 0215      * @return a string binding.
 0216      */
 0217     @Nonnull
 0218     public static <K, V> StringBinding joinMap(@Nonnull final ObservableMap<K, V> items, @Nullable final String delimiter, @Nonnull final Function<Map.Entry<K, V>, String> mapper) {
 0219         requireNonNull(items, ERROR_ITEMS_NULL);
 0220         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0221         final String value = delimiter == null ? "," : delimiter;
 0222         return createStringBinding(() -> items.entrySet().stream().map(mapper).collect(joining(value)), items);
 0223     }
 0224
 0225     /**
 0226      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0227      *
 0228      * @param items     the observable map of items.
 0229      * @param delimiter the sequence of characters to be used between each entry.
 0230      *
 0231      * @return a string binding.
 0232      */
 0233     @Nonnull
 0234     public static <K, V> StringBinding joinMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final ObservableValue<String> delimiter) {
 0235         requireNonNull(items, ERROR_ITEMS_NULL);
 0236         requireNonNull(delimiter, ERROR_DELIMITER_NULL);
 0237         final Function<Map.Entry<K, V>, String> mapper = entry -> String.valueOf(entry.getKey()) + "=" + String.valueOf(entry.getValue());
 0238         return createStringBinding(() -> {
 0239             String value = delimiter.getValue();
 0240             value = value == null ? "" : value;
 0241             return items.entrySet().stream().map(mapper).collect(joining(value));
 0242         }, items, delimiter);
 0243     }
 0244
 0245     /**
 0246      * Creates a string binding that constructs a sequence of characters separated by a delimiter.
 0247      *
 0248      * @param items     the observable map of items.
 0249      * @param delimiter the sequence of characters to be used between each element.
 0250      * @param mapper    a non-interfering, stateless function to apply to the each entry.
 0251      *
 0252      * @return a string binding.
 0253      */
 0254     @Nonnull
 0255     public static <K, V> StringBinding joinMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final ObservableValue<String> delimiter, @Nonnull final ObservableValue<Function<Map.Entry<K, V>, String>> mapper) {
 0256         requireNonNull(items, ERROR_ITEMS_NULL);
 0257         requireNonNull(delimiter, ERROR_DELIMITER_NULL);
 0258         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0259         final Function<Map.Entry<K, V>, String> mv = entry -> String.valueOf(entry.getKey()) + "=" + String.valueOf(entry.getValue());
 0260         return createStringBinding(() -> {
 0261             String value = delimiter.getValue();
 0262             value = value == null ? "" : value;
 0263             final Function<Map.Entry<K, V>, String> mapperValue = mapper.getValue() != null ? mapper.getValue() : mv;
 0264             return items.entrySet().stream().map(mapperValue).collect(joining(value));
 0265         }, items, delimiter, mapper);
 0266     }
 0267
 0268     /**
 0269      * Creates a number binding that computes the minimum value amongst elements.
 0270      *
 0271      * @param items        the observable list of items.
 0272      * @param defaultValue the value to be returned if there is no value present.
 0273      *
 0274      * @return a number binding
 0275      */
 0276     @Nonnull
 0277     public static NumberBinding minInList(@Nonnull final ObservableList<? extends Number> items, @Nonnull final Number defaultValue) {
 0278         requireNonNull(items, ERROR_ITEMS_NULL);
 0279         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0280         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).min().orElse(defaultValue.doubleValue()), items);
 0281     }
 0282
 0283     /**
 0284      * Creates a number binding that computes the minimum value amongst elements.
 0285      *
 0286      * @param items    the observable list of items.
 0287      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0288      *
 0289      * @return a number binding
 0290      */
 0291     @Nonnull
 0292     public static NumberBinding minInList(@Nonnull final ObservableList<? extends Number> items, @Nonnull final Supplier<? extends Number> supplier) {
 0293         requireNonNull(items, ERROR_ITEMS_NULL);
 0294         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0295         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).min().orElseGet(resolveDoubleSupplier(supplier)), items);
 0296     }
 0297
 0298     /**
 0299      * Creates a number binding that computes the maximum value amongst elements.
 0300      *
 0301      * @param items        the observable list of items.
 0302      * @param defaultValue the value to be returned if there is no value present.
 0303      *
 0304      * @return a number binding
 0305      */
 0306     @Nonnull
 0307     public static NumberBinding maxInList(@Nonnull final ObservableList<? extends Number> items, @Nonnull final Number defaultValue) {
 0308         requireNonNull(items, ERROR_ITEMS_NULL);
 0309         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0310         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).max().orElse(defaultValue.doubleValue()), items);
 0311     }
 0312
 0313     /**
 0314      * Creates a number binding that computes the maximum value amongst elements.
 0315      *
 0316      * @param items    the observable list of items.
 0317      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0318      *
 0319      * @return a number binding
 0320      */
 0321     @Nonnull
 0322     public static NumberBinding maxInList(@Nonnull final ObservableList<? extends Number> items, @Nonnull final Supplier<? extends Number> supplier) {
 0323         requireNonNull(items, ERROR_ITEMS_NULL);
 0324         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0325         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).max().orElseGet(resolveDoubleSupplier(supplier)), items);
 0326     }
 0327
 0328     /**
 0329      * Creates a number binding that computes the average value amongst elements.
 0330      *
 0331      * @param items        the observable list of items.
 0332      * @param defaultValue the value to be returned if there is no value present.
 0333      *
 0334      * @return a number binding
 0335      */
 0336     @Nonnull
 0337     public static NumberBinding averageInList(@Nonnull final ObservableList<? extends Number> items, @Nonnull final Number defaultValue) {
 0338         requireNonNull(items, ERROR_ITEMS_NULL);
 0339         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0340         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).average().orElse(defaultValue.doubleValue()), items);
 0341     }
 0342
 0343     /**
 0344      * Creates a number binding that computes the average value amongst elements.
 0345      *
 0346      * @param items    the observable list of items.
 0347      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0348      *
 0349      * @return a number binding
 0350      */
 0351     @Nonnull
 0352     public static NumberBinding averageInList(@Nonnull final ObservableList<? extends Number> items, @Nonnull final Supplier<? extends Number> supplier) {
 0353         requireNonNull(items, ERROR_ITEMS_NULL);
 0354         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0355         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).average().orElseGet(resolveDoubleSupplier(supplier)), items);
 0356     }
 0357
 0358     /**
 0359      * Creates a number binding that contains the sum of the items of the given observable list.
 0360      *
 0361      * @param items the observable list of items.
 0362      *
 0363      * @return a number binding.
 0364      */
 0365     @Nonnull
 0366     public static NumberBinding sumOfList(@Nonnull final ObservableList<? extends Number> items) {
 0367         requireNonNull(items, ERROR_ITEMS_NULL);
 0368         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).sum(), items);
 0369     }
 0370
 0371     /**
 0372      * Creates a number binding that computes the minimum value amongst elements.
 0373      *
 0374      * @param items        the observable list of items.
 0375      * @param defaultValue the value to be returned if there is no value present.
 0376      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0377      *
 0378      * @return a number binding
 0379      */
 0380     @Nonnull
 0381     public static <T> NumberBinding minInList(@Nonnull final ObservableList<T> items, @Nonnull final Number defaultValue, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0382         requireNonNull(items, ERROR_ITEMS_NULL);
 0383         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0384         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0385         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).min().orElse(defaultValue.doubleValue()), items);
 0386     }
 0387
 0388     /**
 0389      * Creates a number binding that computes the minimum value amongst elements.
 0390      *
 0391      * @param items    the observable list of items.
 0392      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0393      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0394      *
 0395      * @return a number binding
 0396      */
 0397     @Nonnull
 0398     public static <T> NumberBinding minInList(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0399         requireNonNull(items, ERROR_ITEMS_NULL);
 0400         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0401         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0402         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).min().orElseGet(resolveDoubleSupplier(supplier)), items);
 0403     }
 0404
 0405     /**
 0406      * Creates a number binding that computes the maximum value amongst elements.
 0407      *
 0408      * @param items        the observable list of items.
 0409      * @param defaultValue the value to be returned if there is no value present.
 0410      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0411      *
 0412      * @return a number binding
 0413      */
 0414     @Nonnull
 0415     public static <T> NumberBinding maxInList(@Nonnull final ObservableList<T> items, @Nonnull final Number defaultValue, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0416         requireNonNull(items, ERROR_ITEMS_NULL);
 0417         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0418         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0419         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).max().orElse(defaultValue.doubleValue()), items);
 0420     }
 0421
 0422     /**
 0423      * Creates a number binding that computes the maximum value amongst elements.
 0424      *
 0425      * @param items    the observable list of items.
 0426      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0427      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0428      *
 0429      * @return a number binding
 0430      */
 0431     @Nonnull
 0432     public static <T> NumberBinding maxInList(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0433         requireNonNull(items, ERROR_ITEMS_NULL);
 0434         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0435         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0436         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).max().orElseGet(resolveDoubleSupplier(supplier)), items);
 0437     }
 0438
 0439     /**
 0440      * Creates a number binding that computes the average value amongst elements.
 0441      *
 0442      * @param items        the observable list of items.
 0443      * @param defaultValue the value to be returned if there is no value present.
 0444      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0445      *
 0446      * @return a number binding
 0447      */
 0448     @Nonnull
 0449     public static <T> NumberBinding averageInList(@Nonnull final ObservableList<T> items, @Nonnull final Number defaultValue, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0450         requireNonNull(items, ERROR_ITEMS_NULL);
 0451         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0452         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0453         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).average().orElse(defaultValue.doubleValue()), items);
 0454     }
 0455
 0456     /**
 0457      * Creates a number binding that computes the average value amongst elements.
 0458      *
 0459      * @param items    the observable list of items.
 0460      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0461      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0462      *
 0463      * @return a number binding
 0464      */
 0465     @Nonnull
 0466     public static <T> NumberBinding averageInList(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0467         requireNonNull(items, ERROR_ITEMS_NULL);
 0468         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0469         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0470         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).average().orElseGet(resolveDoubleSupplier(supplier)), items);
 0471     }
 0472
 0473     /**
 0474      * Creates a number binding that contains the sum of the items of the given observable list.
 0475      *
 0476      * @param items  the observable list of items.
 0477      * @param mapper a non-interfering, stateless function to apply to the each element.
 0478      *
 0479      * @return a number binding.
 0480      */
 0481     @Nonnull
 0482     public static <T> NumberBinding sumOfList(@Nonnull final ObservableList<T> items, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0483         requireNonNull(items, ERROR_ITEMS_NULL);
 0484         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0485         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).sum(), items);
 0486     }
 0487
 0488     /**
 0489      * Creates a number binding that computes the minimum value amongst elements.
 0490      *
 0491      * @param items        the observable list of items.
 0492      * @param defaultValue the value to be returned if there is no value present.
 0493      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0494      *
 0495      * @return a number binding
 0496      */
 0497     @Nonnull
 0498     public static <T> NumberBinding minInList(@Nonnull final ObservableList<T> items, @Nonnull final Number defaultValue, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0499         requireNonNull(items, ERROR_ITEMS_NULL);
 0500         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0501         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0502         return createDoubleBinding(() -> {
 0503             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0504             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0505             return items.stream().mapToDouble(mapperValue).min().orElse(defaultValue.doubleValue());
 0506         }, items, mapper);
 0507     }
 0508
 0509     /**
 0510      * Creates a number binding that computes the minimum value amongst elements.
 0511      *
 0512      * @param items    the observable list of items.
 0513      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0514      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0515      *
 0516      * @return a number binding
 0517      */
 0518     @Nonnull
 0519     public static <T> NumberBinding minInList(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0520         requireNonNull(items, ERROR_ITEMS_NULL);
 0521         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0522         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0523         return createDoubleBinding(() -> {
 0524             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0525             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0526             return items.stream().mapToDouble(mapperValue).min().orElseGet(resolveDoubleSupplier(supplier));
 0527         }, items, mapper);
 0528     }
 0529
 0530     /**
 0531      * Creates a number binding that computes the maximum value amongst elements.
 0532      *
 0533      * @param items        the observable list of items.
 0534      * @param defaultValue the value to be returned if there is no value present.
 0535      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0536      *
 0537      * @return a number binding
 0538      */
 0539     @Nonnull
 0540     public static <T> NumberBinding maxInList(@Nonnull final ObservableList<T> items, @Nonnull final Number defaultValue, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0541         requireNonNull(items, ERROR_ITEMS_NULL);
 0542         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0543         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0544         return createDoubleBinding(() -> {
 0545             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0546             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0547             return items.stream().mapToDouble(mapperValue).max().orElse(defaultValue.doubleValue());
 0548         }, items, mapper);
 0549     }
 0550
 0551     /**
 0552      * Creates a number binding that computes the maximum value amongst elements.
 0553      *
 0554      * @param items    the observable list of items.
 0555      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0556      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0557      *
 0558      * @return a number binding
 0559      */
 0560     @Nonnull
 0561     public static <T> NumberBinding maxInList(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0562         requireNonNull(items, ERROR_ITEMS_NULL);
 0563         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0564         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0565         return createDoubleBinding(() -> {
 0566             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0567             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0568             return items.stream().mapToDouble(mapperValue).max().orElseGet(resolveDoubleSupplier(supplier));
 0569         }, items, mapper);
 0570     }
 0571
 0572     /**
 0573      * Creates a number binding that computes the average value amongst elements.
 0574      *
 0575      * @param items        the observable list of items.
 0576      * @param defaultValue the value to be returned if there is no value present.
 0577      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0578      *
 0579      * @return a number binding
 0580      */
 0581     @Nonnull
 0582     public static <T> NumberBinding averageInList(@Nonnull final ObservableList<T> items, @Nonnull final Number defaultValue, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0583         requireNonNull(items, ERROR_ITEMS_NULL);
 0584         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0585         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0586         return createDoubleBinding(() -> {
 0587             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0588             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0589             return items.stream().mapToDouble(mapperValue).average().orElse(defaultValue.doubleValue());
 0590         }, items, mapper);
 0591     }
 0592
 0593     /**
 0594      * Creates a number binding that computes the average value amongst elements.
 0595      *
 0596      * @param items    the observable list of items.
 0597      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0598      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0599      *
 0600      * @return a number binding
 0601      */
 0602     @Nonnull
 0603     public static <T> NumberBinding averageInList(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0604         requireNonNull(items, ERROR_ITEMS_NULL);
 0605         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0606         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0607         return createDoubleBinding(() -> {
 0608             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0609             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0610             return items.stream().mapToDouble(mapperValue).average().orElseGet(resolveDoubleSupplier(supplier));
 0611         }, items, mapper);
 0612     }
 0613
 0614     /**
 0615      * Creates a number binding that contains the sum of the items of the given observable list.
 0616      *
 0617      * @param items  the observable list of items.
 0618      * @param mapper a non-interfering, stateless function to apply to the each element.
 0619      *
 0620      * @return a number binding.
 0621      */
 0622     @Nonnull
 0623     public static <T> NumberBinding sumOfList(@Nonnull final ObservableList<T> items, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0624         requireNonNull(items, ERROR_ITEMS_NULL);
 0625         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0626         return createDoubleBinding(() -> {
 0627             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0628             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0629             return items.stream().mapToDouble(mapperValue).sum();
 0630         }, items, mapper);
 0631     }
 0632
 0633     /**
 0634      * Creates a number binding that computes the minimum value amongst elements.
 0635      *
 0636      * @param items        the observable set of items.
 0637      * @param defaultValue the value to be returned if there is no value present.
 0638      *
 0639      * @return a number binding
 0640      */
 0641     @Nonnull
 0642     public static NumberBinding minInSet(@Nonnull final ObservableSet<? extends Number> items, @Nonnull final Number defaultValue) {
 0643         requireNonNull(items, ERROR_ITEMS_NULL);
 0644         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0645         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).min().orElse(defaultValue.doubleValue()), items);
 0646     }
 0647
 0648     /**
 0649      * Creates a number binding that computes the minimum value amongst elements.
 0650      *
 0651      * @param items    the observable set of items.
 0652      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0653      *
 0654      * @return a number binding
 0655      */
 0656     @Nonnull
 0657     public static NumberBinding minInSet(@Nonnull final ObservableSet<? extends Number> items, @Nonnull final Supplier<? extends Number> supplier) {
 0658         requireNonNull(items, ERROR_ITEMS_NULL);
 0659         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0660         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).min().orElseGet(resolveDoubleSupplier(supplier)), items);
 0661     }
 0662
 0663     /**
 0664      * Creates a number binding that computes the maximum value amongst elements.
 0665      *
 0666      * @param items        the observable set of items.
 0667      * @param defaultValue the value to be returned if there is no value present.
 0668      *
 0669      * @return a number binding
 0670      */
 0671     @Nonnull
 0672     public static NumberBinding maxInSet(@Nonnull final ObservableSet<? extends Number> items, @Nonnull final Number defaultValue) {
 0673         requireNonNull(items, ERROR_ITEMS_NULL);
 0674         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0675         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).max().orElse(defaultValue.doubleValue()), items);
 0676     }
 0677
 0678     /**
 0679      * Creates a number binding that computes the maximum value amongst elements.
 0680      *
 0681      * @param items    the observable set of items.
 0682      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0683      *
 0684      * @return a number binding
 0685      */
 0686     @Nonnull
 0687     public static NumberBinding maxInSet(@Nonnull final ObservableSet<? extends Number> items, @Nonnull final Supplier<? extends Number> supplier) {
 0688         requireNonNull(items, ERROR_ITEMS_NULL);
 0689         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0690         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).max().orElseGet(resolveDoubleSupplier(supplier)), items);
 0691     }
 0692
 0693     /**
 0694      * Creates a number binding that computes the average value amongst elements.
 0695      *
 0696      * @param items        the observable set of items.
 0697      * @param defaultValue the value to be returned if there is no value present.
 0698      *
 0699      * @return a number binding
 0700      */
 0701     @Nonnull
 0702     public static NumberBinding averageInSet(@Nonnull final ObservableSet<? extends Number> items, @Nonnull final Number defaultValue) {
 0703         requireNonNull(items, ERROR_ITEMS_NULL);
 0704         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0705         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).average().orElse(defaultValue.doubleValue()), items);
 0706     }
 0707
 0708     /**
 0709      * Creates a number binding that computes the average value amongst elements.
 0710      *
 0711      * @param items    the observable set of items.
 0712      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0713      *
 0714      * @return a number binding
 0715      */
 0716     @Nonnull
 0717     public static NumberBinding averageInSet(@Nonnull final ObservableSet<? extends Number> items, @Nonnull final Supplier<? extends Number> supplier) {
 0718         requireNonNull(items, ERROR_ITEMS_NULL);
 0719         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0720         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).average().orElseGet(resolveDoubleSupplier(supplier)), items);
 0721     }
 0722
 0723     /**
 0724      * Creates a number binding that contains the sum of the items of the given observable set.
 0725      *
 0726      * @param items the observable set of items.
 0727      *
 0728      * @return a number binding.
 0729      */
 0730     @Nonnull
 0731     public static NumberBinding sumOfSet(@Nonnull final ObservableSet<? extends Number> items) {
 0732         requireNonNull(items, ERROR_ITEMS_NULL);
 0733         return createDoubleBinding(() -> items.stream().mapToDouble(Number::doubleValue).sum(), items);
 0734     }
 0735
 0736     /**
 0737      * Creates a number binding that computes the minimum value amongst elements.
 0738      *
 0739      * @param items        the observable set of items.
 0740      * @param defaultValue the value to be returned if there is no value present.
 0741      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0742      *
 0743      * @return a number binding
 0744      */
 0745     @Nonnull
 0746     public static <T> NumberBinding minInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Number defaultValue, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0747         requireNonNull(items, ERROR_ITEMS_NULL);
 0748         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0749         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0750         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).min().orElse(defaultValue.doubleValue()), items);
 0751     }
 0752
 0753     /**
 0754      * Creates a number binding that computes the minimum value amongst elements.
 0755      *
 0756      * @param items    the observable set of items.
 0757      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0758      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0759      *
 0760      * @return a number binding
 0761      */
 0762     @Nonnull
 0763     public static <T> NumberBinding minInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0764         requireNonNull(items, ERROR_ITEMS_NULL);
 0765         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0766         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0767         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).min().orElseGet(resolveDoubleSupplier(supplier)), items);
 0768     }
 0769
 0770     /**
 0771      * Creates a number binding that computes the maximum value amongst elements.
 0772      *
 0773      * @param items        the observable set of items.
 0774      * @param defaultValue the value to be returned if there is no value present.
 0775      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0776      *
 0777      * @return a number binding
 0778      */
 0779     @Nonnull
 0780     public static <T> NumberBinding maxInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Number defaultValue, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0781         requireNonNull(items, ERROR_ITEMS_NULL);
 0782         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0783         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0784         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).max().orElse(defaultValue.doubleValue()), items);
 0785     }
 0786
 0787     /**
 0788      * Creates a number binding that computes the maximum value amongst elements.
 0789      *
 0790      * @param items    the observable set of items.
 0791      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0792      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0793      *
 0794      * @return a number binding
 0795      */
 0796     @Nonnull
 0797     public static <T> NumberBinding maxInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0798         requireNonNull(items, ERROR_ITEMS_NULL);
 0799         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0800         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0801         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).max().orElseGet(resolveDoubleSupplier(supplier)), items);
 0802     }
 0803
 0804     /**
 0805      * Creates a number binding that computes the average value amongst elements.
 0806      *
 0807      * @param items        the observable set of items.
 0808      * @param defaultValue the value to be returned if there is no value present.
 0809      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0810      *
 0811      * @return a number binding
 0812      */
 0813     @Nonnull
 0814     public static <T> NumberBinding averageInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Number defaultValue, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0815         requireNonNull(items, ERROR_ITEMS_NULL);
 0816         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0817         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0818         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).average().orElse(defaultValue.doubleValue()), items);
 0819     }
 0820
 0821     /**
 0822      * Creates a number binding that computes the average value amongst elements.
 0823      *
 0824      * @param items    the observable set of items.
 0825      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0826      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0827      *
 0828      * @return a number binding
 0829      */
 0830     @Nonnull
 0831     public static <T> NumberBinding averageInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0832         requireNonNull(items, ERROR_ITEMS_NULL);
 0833         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0834         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0835         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).average().orElseGet(resolveDoubleSupplier(supplier)), items);
 0836     }
 0837
 0838     /**
 0839      * Creates a number binding that contains the sum of the items of the given observable set.
 0840      *
 0841      * @param items  the observable set of items.
 0842      * @param mapper a non-interfering, stateless function to apply to the each element.
 0843      *
 0844      * @return a number binding.
 0845      */
 0846     @Nonnull
 0847     public static <T> NumberBinding sumOfSet(@Nonnull final ObservableSet<T> items, @Nonnull final ToDoubleFunction<? super T> mapper) {
 0848         requireNonNull(items, ERROR_ITEMS_NULL);
 0849         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0850         return createDoubleBinding(() -> items.stream().mapToDouble(mapper).sum(), items);
 0851     }
 0852
 0853     /**
 0854      * Creates a number binding that computes the minimum value amongst elements.
 0855      *
 0856      * @param items        the observable set of items.
 0857      * @param defaultValue the value to be returned if there is no value present.
 0858      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0859      *
 0860      * @return a number binding
 0861      */
 0862     @Nonnull
 0863     public static <T> NumberBinding minInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Number defaultValue, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0864         requireNonNull(items, ERROR_ITEMS_NULL);
 0865         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0866         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0867         return createDoubleBinding(() -> {
 0868             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0869             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0870             return items.stream().mapToDouble(mapperValue).min().orElse(defaultValue.doubleValue());
 0871         }, items, mapper);
 0872     }
 0873
 0874     /**
 0875      * Creates a number binding that computes the minimum value amongst elements.
 0876      *
 0877      * @param items    the observable set of items.
 0878      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0879      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0880      *
 0881      * @return a number binding
 0882      */
 0883     @Nonnull
 0884     public static <T> NumberBinding minInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0885         requireNonNull(items, ERROR_ITEMS_NULL);
 0886         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0887         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0888         return createDoubleBinding(() -> {
 0889             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0890             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0891             return items.stream().mapToDouble(mapperValue).min().orElseGet(resolveDoubleSupplier(supplier));
 0892         }, items, mapper);
 0893     }
 0894
 0895     /**
 0896      * Creates a number binding that computes the maximum value amongst elements.
 0897      *
 0898      * @param items        the observable set of items.
 0899      * @param defaultValue the value to be returned if there is no value present.
 0900      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0901      *
 0902      * @return a number binding
 0903      */
 0904     @Nonnull
 0905     public static <T> NumberBinding maxInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Number defaultValue, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0906         requireNonNull(items, ERROR_ITEMS_NULL);
 0907         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0908         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0909         return createDoubleBinding(() -> {
 0910             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0911             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0912             return items.stream().mapToDouble(mapperValue).max().orElse(defaultValue.doubleValue());
 0913         }, items, mapper);
 0914     }
 0915
 0916     /**
 0917      * Creates a number binding that computes the maximum value amongst elements.
 0918      *
 0919      * @param items    the observable set of items.
 0920      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0921      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0922      *
 0923      * @return a number binding
 0924      */
 0925     @Nonnull
 0926     public static <T> NumberBinding maxInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0927         requireNonNull(items, ERROR_ITEMS_NULL);
 0928         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0929         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0930         return createDoubleBinding(() -> {
 0931             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0932             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0933             return items.stream().mapToDouble(mapperValue).max().orElseGet(resolveDoubleSupplier(supplier));
 0934         }, items, mapper);
 0935     }
 0936
 0937     /**
 0938      * Creates a number binding that computes the average value amongst elements.
 0939      *
 0940      * @param items        the observable set of items.
 0941      * @param defaultValue the value to be returned if there is no value present.
 0942      * @param mapper       a non-interfering, stateless function to apply to the each element.
 0943      *
 0944      * @return a number binding
 0945      */
 0946     @Nonnull
 0947     public static <T> NumberBinding averageInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Number defaultValue, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0948         requireNonNull(items, ERROR_ITEMS_NULL);
 0949         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 0950         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0951         return createDoubleBinding(() -> {
 0952             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0953             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0954             return items.stream().mapToDouble(mapperValue).average().orElse(defaultValue.doubleValue());
 0955         }, items, mapper);
 0956     }
 0957
 0958     /**
 0959      * Creates a number binding that computes the average value amongst elements.
 0960      *
 0961      * @param items    the observable set of items.
 0962      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 0963      * @param mapper   a non-interfering, stateless function to apply to the each element.
 0964      *
 0965      * @return a number binding
 0966      */
 0967     @Nonnull
 0968     public static <T> NumberBinding averageInSet(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0969         requireNonNull(items, ERROR_ITEMS_NULL);
 0970         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 0971         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0972         return createDoubleBinding(() -> {
 0973             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0974             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0975             return items.stream().mapToDouble(mapperValue).average().orElseGet(resolveDoubleSupplier(supplier));
 0976         }, items, mapper);
 0977     }
 0978
 0979     /**
 0980      * Creates a number binding that contains the sum of the items of the given observable set.
 0981      *
 0982      * @param items  the observable set of items.
 0983      * @param mapper a non-interfering, stateless function to apply to the each element.
 0984      *
 0985      * @return a number binding.
 0986      */
 0987     @Nonnull
 0988     public static <T> NumberBinding sumOfSet(@Nonnull final ObservableSet<T> items, @Nonnull final ObservableValue<ToDoubleFunction<? super T>> mapper) {
 0989         requireNonNull(items, ERROR_ITEMS_NULL);
 0990         requireNonNull(mapper, ERROR_MAPPER_NULL);
 0991         return createDoubleBinding(() -> {
 0992             ToDoubleFunction<? super T> mapperValue = mapper.getValue();
 0993             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 0994             return items.stream().mapToDouble(mapperValue).sum();
 0995         }, items, mapper);
 0996     }
 0997
 0998     /**
 0999      * Creates a number binding that computes the minimum value amongst values.
 1000      *
 1001      * @param items        the observable map of items.
 1002      * @param defaultValue the value to be returned if there is no value present.
 1003      *
 1004      * @return a number binding
 1005      */
 1006     @Nonnull
 1007     public static <K> NumberBinding minInMap(@Nonnull final ObservableMap<K, ? extends Number> items, @Nonnull final Number defaultValue) {
 1008         requireNonNull(items, ERROR_ITEMS_NULL);
 1009         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 1010         return createDoubleBinding(() -> items.values().stream().mapToDouble(Number::doubleValue).min().orElse(defaultValue.doubleValue()), items);
 1011     }
 1012
 1013     /**
 1014      * Creates a number binding that computes the minimum value amongst values.
 1015      *
 1016      * @param items    the observable map of items.
 1017      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 1018      *
 1019      * @return a number binding
 1020      */
 1021     @Nonnull
 1022     public static <K> NumberBinding minInMap(@Nonnull final ObservableMap<K, ? extends Number> items, @Nonnull final Supplier<? extends Number> supplier) {
 1023         requireNonNull(items, ERROR_ITEMS_NULL);
 1024         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 1025         return createDoubleBinding(() -> items.values().stream().mapToDouble(Number::doubleValue).min().orElseGet(resolveDoubleSupplier(supplier)), items);
 1026     }
 1027
 1028     /**
 1029      * Creates a number binding that computes the maximum value amongst values.
 1030      *
 1031      * @param items        the observable map of items.
 1032      * @param defaultValue the value to be returned if there is no value present.
 1033      *
 1034      * @return a number binding
 1035      */
 1036     @Nonnull
 1037     public static <K> NumberBinding maxInMap(@Nonnull final ObservableMap<K, ? extends Number> items, @Nonnull final Number defaultValue) {
 1038         requireNonNull(items, ERROR_ITEMS_NULL);
 1039         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 1040         return createDoubleBinding(() -> items.values().stream().mapToDouble(Number::doubleValue).max().orElse(defaultValue.doubleValue()), items);
 1041     }
 1042
 1043     /**
 1044      * Creates a number binding that computes the maximum value amongst values.
 1045      *
 1046      * @param items    the observable map of items.
 1047      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 1048      *
 1049      * @return a number binding
 1050      */
 1051     @Nonnull
 1052     public static <K> NumberBinding maxInMap(@Nonnull final ObservableMap<K, ? extends Number> items, @Nonnull final Supplier<? extends Number> supplier) {
 1053         requireNonNull(items, ERROR_ITEMS_NULL);
 1054         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 1055         return createDoubleBinding(() -> items.values().stream().mapToDouble(Number::doubleValue).max().orElseGet(resolveDoubleSupplier(supplier)), items);
 1056     }
 1057
 1058     /**
 1059      * Creates a number binding that computes the average value amongst values.
 1060      *
 1061      * @param items        the observable map of items.
 1062      * @param defaultValue the value to be returned if there is no value present.
 1063      *
 1064      * @return a number binding
 1065      */
 1066     @Nonnull
 1067     public static <K> NumberBinding averageInMap(@Nonnull final ObservableMap<K, ? extends Number> items, @Nonnull final Number defaultValue) {
 1068         requireNonNull(items, ERROR_ITEMS_NULL);
 1069         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 1070         return createDoubleBinding(() -> items.values().stream().mapToDouble(Number::doubleValue).average().orElse(defaultValue.doubleValue()), items);
 1071     }
 1072
 1073     /**
 1074      * Creates a number binding that computes the average value amongst values.
 1075      *
 1076      * @param items    the observable map of items.
 1077      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 1078      *
 1079      * @return a number binding
 1080      */
 1081     @Nonnull
 1082     public static <K> NumberBinding averageInMap(@Nonnull final ObservableMap<K, ? extends Number> items, @Nonnull final Supplier<? extends Number> supplier) {
 1083         requireNonNull(items, ERROR_ITEMS_NULL);
 1084         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 1085         return createDoubleBinding(() -> items.values().stream().mapToDouble(Number::doubleValue).average().orElseGet(resolveDoubleSupplier(supplier)), items);
 1086     }
 1087
 1088     /**
 1089      * Creates a number binding that contains the sum of the values of the given observable map.
 1090      *
 1091      * @param items the observable map of items.
 1092      *
 1093      * @return a number binding.
 1094      */
 1095     @Nonnull
 1096     public static <K> NumberBinding sumOfMap(@Nonnull final ObservableMap<K, ? extends Number> items) {
 1097         requireNonNull(items, ERROR_ITEMS_NULL);
 1098         return createDoubleBinding(() -> items.values().stream().mapToDouble(Number::doubleValue).sum(), items);
 1099     }
 1100
 1101     /**
 1102      * Creates a number binding that computes the minimum value amongst values.
 1103      *
 1104      * @param items        the observable map of items.
 1105      * @param defaultValue the value to be returned if there is no value present.
 1106      * @param mapper       a non-interfering, stateless function to apply to the each value.
 1107      *
 1108      * @return a number binding
 1109      */
 1110     @Nonnull
 1111     public static <K, V> NumberBinding minInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Number defaultValue, @Nonnull final ToDoubleFunction<? super V> mapper) {
 1112         requireNonNull(items, ERROR_ITEMS_NULL);
 1113         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 1114         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1115         return createDoubleBinding(() -> items.values().stream().mapToDouble(mapper).min().orElse(defaultValue.doubleValue()), items);
 1116     }
 1117
 1118     /**
 1119      * Creates a number binding that computes the minimum value amongst values.
 1120      *
 1121      * @param items    the observable map of items.
 1122      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 1123      * @param mapper   a non-interfering, stateless function to apply to the each value.
 1124      *
 1125      * @return a number binding
 1126      */
 1127     @Nonnull
 1128     public static <K, V> NumberBinding minInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ToDoubleFunction<? super V> mapper) {
 1129         requireNonNull(items, ERROR_ITEMS_NULL);
 1130         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 1131         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1132         return createDoubleBinding(() -> items.values().stream().mapToDouble(mapper).min().orElseGet(resolveDoubleSupplier(supplier)), items);
 1133     }
 1134
 1135     /**
 1136      * Creates a number binding that computes the maximum value amongst values.
 1137      *
 1138      * @param items        the observable map of items.
 1139      * @param defaultValue the value to be returned if there is no value present.
 1140      * @param mapper       a non-interfering, stateless function to apply to the each value.
 1141      *
 1142      * @return a number binding
 1143      */
 1144     @Nonnull
 1145     public static <K, V> NumberBinding maxInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Number defaultValue, @Nonnull final ToDoubleFunction<? super V> mapper) {
 1146         requireNonNull(items, ERROR_ITEMS_NULL);
 1147         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 1148         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1149         return createDoubleBinding(() -> items.values().stream().mapToDouble(mapper).max().orElse(defaultValue.doubleValue()), items);
 1150     }
 1151
 1152     /**
 1153      * Creates a number binding that computes the maximum value amongst values.
 1154      *
 1155      * @param items    the observable map of items.
 1156      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 1157      * @param mapper   a non-interfering, stateless function to apply to the each value.
 1158      *
 1159      * @return a number binding
 1160      */
 1161     @Nonnull
 1162     public static <K, V> NumberBinding maxInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ToDoubleFunction<? super V> mapper) {
 1163         requireNonNull(items, ERROR_ITEMS_NULL);
 1164         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 1165         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1166         return createDoubleBinding(() -> items.values().stream().mapToDouble(mapper).max().orElseGet(resolveDoubleSupplier(supplier)), items);
 1167     }
 1168
 1169     /**
 1170      * Creates a number binding that computes the average value amongst values.
 1171      *
 1172      * @param items        the observable map of items.
 1173      * @param defaultValue the value to be returned if there is no value present.
 1174      * @param mapper       a non-interfering, stateless function to apply to the each value.
 1175      *
 1176      * @return a number binding
 1177      */
 1178     @Nonnull
 1179     public static <K, V> NumberBinding averageInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Number defaultValue, @Nonnull final ToDoubleFunction<? super V> mapper) {
 1180         requireNonNull(items, ERROR_ITEMS_NULL);
 1181         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 1182         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1183         return createDoubleBinding(() -> items.values().stream().mapToDouble(mapper).average().orElse(defaultValue.doubleValue()), items);
 1184     }
 1185
 1186     /**
 1187      * Creates a number binding that computes the average value amongst values.
 1188      *
 1189      * @param items    the observable map of items.
 1190      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 1191      * @param mapper   a non-interfering, stateless function to apply to the each value.
 1192      *
 1193      * @return a number binding
 1194      */
 1195     @Nonnull
 1196     public static <K, V> NumberBinding averageInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ToDoubleFunction<? super V> mapper) {
 1197         requireNonNull(items, ERROR_ITEMS_NULL);
 1198         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 1199         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1200         return createDoubleBinding(() -> items.values().stream().mapToDouble(mapper).average().orElseGet(resolveDoubleSupplier(supplier)), items);
 1201     }
 1202
 1203     /**
 1204      * Creates a number binding that contains the sum of the values of the given observable map.
 1205      *
 1206      * @param items  the observable map of items.
 1207      * @param mapper a non-interfering, stateless function to apply to the each value.
 1208      *
 1209      * @return a number binding.
 1210      */
 1211     @Nonnull
 1212     public static <K, V> NumberBinding sumOfMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final ToDoubleFunction<? super V> mapper) {
 1213         requireNonNull(items, ERROR_ITEMS_NULL);
 1214         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1215         return createDoubleBinding(() -> items.values().stream().mapToDouble(mapper).sum(), items);
 1216     }
 1217
 1218     /**
 1219      * Creates a number binding that computes the minimum value amongst values.
 1220      *
 1221      * @param items        the observable map of items.
 1222      * @param defaultValue the value to be returned if there is no value present.
 1223      * @param mapper       a non-interfering, stateless function to apply to the each value.
 1224      *
 1225      * @return a number binding
 1226      */
 1227     @Nonnull
 1228     public static <K, V> NumberBinding minInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Number defaultValue, @Nonnull final ObservableValue<ToDoubleFunction<? super V>> mapper) {
 1229         requireNonNull(items, ERROR_ITEMS_NULL);
 1230         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 1231         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1232         return createDoubleBinding(() -> {
 1233             ToDoubleFunction<? super V> mapperValue = mapper.getValue();
 1234             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 1235             return items.values().stream().mapToDouble(mapperValue).min().orElse(defaultValue.doubleValue());
 1236         }, items, mapper);
 1237     }
 1238
 1239     /**
 1240      * Creates a number binding that computes the minimum value amongst values.
 1241      *
 1242      * @param items    the observable map of items.
 1243      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 1244      * @param mapper   a non-interfering, stateless function to apply to the each value.
 1245      *
 1246      * @return a number binding
 1247      */
 1248     @Nonnull
 1249     public static <K, V> NumberBinding minInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ObservableValue<ToDoubleFunction<? super V>> mapper) {
 1250         requireNonNull(items, ERROR_ITEMS_NULL);
 1251         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 1252         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1253         return createDoubleBinding(() -> {
 1254             ToDoubleFunction<? super V> mapperValue = mapper.getValue();
 1255             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 1256             return items.values().stream().mapToDouble(mapperValue).min().orElseGet(resolveDoubleSupplier(supplier));
 1257         }, items, mapper);
 1258     }
 1259
 1260     /**
 1261      * Creates a number binding that computes the maximum value amongst values.
 1262      *
 1263      * @param items        the observable map of items.
 1264      * @param defaultValue the value to be returned if there is no value present.
 1265      * @param mapper       a non-interfering, stateless function to apply to the each value.
 1266      *
 1267      * @return a number binding
 1268      */
 1269     @Nonnull
 1270     public static <K, V> NumberBinding maxInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Number defaultValue, @Nonnull final ObservableValue<ToDoubleFunction<? super V>> mapper) {
 1271         requireNonNull(items, ERROR_ITEMS_NULL);
 1272         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 1273         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1274         return createDoubleBinding(() -> {
 1275             ToDoubleFunction<? super V> mapperValue = mapper.getValue();
 1276             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 1277             return items.values().stream().mapToDouble(mapperValue).max().orElse(defaultValue.doubleValue());
 1278         }, items, mapper);
 1279     }
 1280
 1281     /**
 1282      * Creates a number binding that computes the maximum value amongst values.
 1283      *
 1284      * @param items    the observable map of items.
 1285      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 1286      * @param mapper   a non-interfering, stateless function to apply to the each value.
 1287      *
 1288      * @return a number binding
 1289      */
 1290     @Nonnull
 1291     public static <K, V> NumberBinding maxInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ObservableValue<ToDoubleFunction<? super V>> mapper) {
 1292         requireNonNull(items, ERROR_ITEMS_NULL);
 1293         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 1294         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1295         return createDoubleBinding(() -> {
 1296             ToDoubleFunction<? super V> mapperValue = mapper.getValue();
 1297             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 1298             return items.values().stream().mapToDouble(mapperValue).max().orElseGet(resolveDoubleSupplier(supplier));
 1299         }, items, mapper);
 1300     }
 1301
 1302     /**
 1303      * Creates a number binding that computes the average value amongst values.
 1304      *
 1305      * @param items        the observable map of items.
 1306      * @param defaultValue the value to be returned if there is no value present.
 1307      * @param mapper       a non-interfering, stateless function to apply to the each value.
 1308      *
 1309      * @return a number binding
 1310      */
 1311     @Nonnull
 1312     public static <K, V> NumberBinding averageInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Number defaultValue, @Nonnull final ObservableValue<ToDoubleFunction<? super V>> mapper) {
 1313         requireNonNull(items, ERROR_ITEMS_NULL);
 1314         requireNonNull(defaultValue, ERROR_DEFAULT_VALUE_NULL);
 1315         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1316         return createDoubleBinding(() -> {
 1317             ToDoubleFunction<? super V> mapperValue = mapper.getValue();
 1318             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 1319             return items.values().stream().mapToDouble(mapperValue).average().orElse(defaultValue.doubleValue());
 1320         }, items, mapper);
 1321     }
 1322
 1323     /**
 1324      * Creates a number binding that computes the average value amongst values.
 1325      *
 1326      * @param items    the observable map of items.
 1327      * @param supplier a {@code Supplier} whose result is returned if no value is present.
 1328      * @param mapper   a non-interfering, stateless function to apply to the each value.
 1329      *
 1330      * @return a number binding
 1331      */
 1332     @Nonnull
 1333     public static <K, V> NumberBinding averageInMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<? extends Number> supplier, @Nonnull final ObservableValue<ToDoubleFunction<? super V>> mapper) {
 1334         requireNonNull(items, ERROR_ITEMS_NULL);
 1335         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 1336         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1337         return createDoubleBinding(() -> {
 1338             ToDoubleFunction<? super V> mapperValue = mapper.getValue();
 1339             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 1340             return items.values().stream().mapToDouble(mapperValue).average().orElseGet(resolveDoubleSupplier(supplier));
 1341         }, items, mapper);
 1342     }
 1343
 1344     /**
 1345      * Creates a number binding that contains the sum of the values of the given observable map.
 1346      *
 1347      * @param items  the observable map of items.
 1348      * @param mapper a non-interfering, stateless function to apply to the each value.
 1349      *
 1350      * @return a number binding.
 1351      */
 1352     @Nonnull
 1353     public static <K, V> NumberBinding sumOfMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final ObservableValue<ToDoubleFunction<? super V>> mapper) {
 1354         requireNonNull(items, ERROR_ITEMS_NULL);
 1355         requireNonNull(mapper, ERROR_MAPPER_NULL);
 1356         return createDoubleBinding(() -> {
 1357             ToDoubleFunction<? super V> mapperValue = mapper.getValue();
 1358             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
 1359             return items.values().stream().mapToDouble(mapperValue).sum();
 1360         }, items, mapper);
 1361     }
 1362
 1363     @Nonnull
 1364     private static DoubleSupplier resolveDoubleSupplier(@Nonnull final Supplier<? extends Number> supplier) {
 1365         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
 1366         return () -> supplier.get().doubleValue();
 1367     }
 1368 }
 |