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.concurrent.locks.Lock; 023import java.util.concurrent.locks.ReentrantLock; 024import java.util.function.Consumer; 025import java.util.function.Predicate; 026import java.util.function.Supplier; 027 028public final class Suppliers { 029 private Suppliers() { 030 } 031 032 /** 033 * Returns a supplier which caches the result of the first call to {@link Supplier#get()}and returns that value on 034 * subsequent calls. 035 * 036 * @param supplier the delegate {@link Supplier}. 037 * @param <T> the type of results supplied by this supplier. 038 * @return the result fo the first call to the delegate's {@link Supplier#get()} method. 039 */ 040 public static <T> Supplier<T> memorize(Supplier<T> supplier) { 041 final AtomicReference<T> valueHolder = new AtomicReference<>(); 042 final Lock lock = new ReentrantLock(); 043 return new Supplier<>() { 044 @Override 045 public T get() { 046 T supplied = valueHolder.get(); 047 if (supplied == null) { 048 lock.lock(); 049 try { 050 supplied = valueHolder.get(); 051 if (supplied == null) { 052 supplied = Objects.requireNonNull(supplier.get(), "Supplier should not return null"); 053 valueHolder.lazySet(supplied); 054 } 055 } finally { 056 lock.unlock(); 057 } 058 } 059 return supplied; 060 } 061 }; 062 } 063 064 /** 065 * Returns a supplier which caches the result of the first call to {@link Supplier#get()} and returns that value on 066 * subsequent calls. 067 * 068 * @param supplier the delegate {@link Supplier}. 069 * @param consumer a consumer for any exception thrown by the {@link ThrowingSupplier#get()}. 070 * @param <T> the type of results supplied by this supplier. 071 * @return the result fo the first call to the delegate's {@link Supplier#get()} method. 072 */ 073 public static <T> Supplier<T> memorize(ThrowingSupplier<T, ? extends Exception> supplier, Consumer<Exception> consumer) { 074 final AtomicReference<T> valueHolder = new AtomicReference<>(); 075 final Lock lock = new ReentrantLock(); 076 return new Supplier<>() { 077 @Override 078 public T get() { 079 T supplied = valueHolder.get(); 080 if (supplied == null) { 081 lock.lock(); 082 try { 083 supplied = valueHolder.get(); 084 if (supplied == null) { 085 try { 086 supplied = Objects.requireNonNull(supplier.get(), "Supplier should not return null"); 087 valueHolder.lazySet(supplied); 088 } catch (Exception e) { 089 consumer.accept(e); 090 } 091 } 092 } finally { 093 lock.unlock(); 094 } 095 } 096 return supplied; 097 } 098 }; 099 } 100 101 /** 102 * Returns a supplier that return a constant value. 103 * 104 * @param value the constant value to return. 105 * @param <T> the type of results supplied by this supplier. 106 * @return the supplied {@code value}. 107 */ 108 public static <T> Supplier<T> constant(T value) { 109 return new Supplier<>() { 110 @Override 111 public T get() { 112 return value; 113 } 114 }; 115 } 116 117 /** 118 * Returns the first non null value provide by the given suppliers. 119 * 120 * @param suppliers a list of supplier. 121 * @param <T> the type of results supplied by this supplier. 122 * @return the optional computed value. 123 */ 124 @SafeVarargs 125 public static <T> Optional<T> firstNotNull(ThrowingSupplier<T, Exception>... suppliers) throws Exception { 126 T answer = null; 127 128 for (ThrowingSupplier<T, Exception> supplier : suppliers) { 129 answer = supplier.get(); 130 if (answer != null) { 131 break; 132 } 133 } 134 135 return Optional.ofNullable(answer); 136 } 137 138 /** 139 * Returns the first value provide by the given suppliers that matches the given predicate. 140 * 141 * @param predicate the predicate used to evaluate the computed values. 142 * @param suppliers a list fo supplier. 143 * @param <T> the type of results supplied by this supplier. 144 * @return the optional matching value. 145 */ 146 public static <T> Optional<T> firstMatching(Predicate<T> predicate, ThrowingSupplier<T, Exception>... suppliers) 147 throws Exception { 148 T answer = null; 149 150 for (ThrowingSupplier<T, Exception> supplier : suppliers) { 151 answer = supplier.get(); 152 if (predicate.test(answer)) { 153 break; 154 } 155 } 156 157 return Optional.ofNullable(answer); 158 } 159}