001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.util.function;
018
019import java.util.Objects;
020import java.util.Optional;
021import java.util.concurrent.atomic.AtomicReference;
022import java.util.function.Consumer;
023import java.util.function.Predicate;
024import java.util.function.Supplier;
025
026public final class Suppliers {
027    private Suppliers() {
028    }
029
030    public static <T> Supplier<T> memorize(Supplier<T> supplier) {
031        final AtomicReference<T> valueHolder = new AtomicReference<>();
032        return () -> {
033            T supplied = valueHolder.get();
034            if (supplied == null) {
035                synchronized (valueHolder) {
036                    supplied = valueHolder.get();
037                    if (supplied == null) {
038                        supplied = Objects.requireNonNull(supplier.get(), "Supplier should not return null");
039                        valueHolder.lazySet(supplied);
040                    }
041                }
042            }
043            return supplied;
044        };
045    }
046
047    public static <T> Supplier<T> memorize(ThrowingSupplier<T, ? extends Exception> supplier, Consumer<Exception> consumer) {
048        final AtomicReference<T> valueHolder = new AtomicReference<>();
049        return () -> {
050            T supplied = valueHolder.get();
051            if (supplied == null) {
052                synchronized (valueHolder) {
053                    supplied = valueHolder.get();
054                    if (supplied == null) {
055                        try {
056                            supplied = Objects.requireNonNull(supplier.get(), "Supplier should not return null");
057                            valueHolder.lazySet(supplied);
058                        } catch (Exception e) {
059                            consumer.accept(e);
060                        }
061                    }
062                }
063            }
064            return supplied;
065        };
066    }
067
068    public static <T> Optional<T> firstNotNull(ThrowingSupplier<T, Exception>... suppliers) throws Exception {
069        T answer = null;
070
071        for (int i = 0; i < suppliers.length; i++) {
072            answer = suppliers[i].get();
073            if (answer != null) {
074                break;
075            }
076        }
077
078        return Optional.ofNullable(answer);
079    }
080
081    public static <T> Optional<T> firstMatching(Predicate<T> predicate, ThrowingSupplier<T, Exception>... suppliers) throws Exception {
082        T answer = null;
083
084        for (int i = 0; i < suppliers.length; i++) {
085            answer = suppliers[i].get();
086            if (predicate.test(answer)) {
087                break;
088            }
089        }
090
091        return Optional.ofNullable(answer);
092    }
093}