001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2022–2023 microBean™.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
006 * the License.  You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
011 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
012 * specific language governing permissions and limitations under the License.
013 */
014package org.microbean.invoke;
015
016import java.util.NoSuchElementException;
017import java.util.Optional;
018
019import java.util.function.BiFunction;
020import java.util.function.Consumer;
021import java.util.function.Function;
022import java.util.function.Supplier;
023
024import java.util.stream.Stream;
025
026/**
027 * A {@link Supplier} with additional contractual requirements.
028 *
029 * <p><strong>An {@link OptionalSupplier} does not behave like an
030 * {@link Optional} or a {@link
031 * java.util.concurrent.CompletableFuture},</strong> despite the
032 * deliberate similarities of some method names.</p>
033 *
034 * <p>An implementation of this interface is not a <a
035 * href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/doc-files/ValueBased.html">value-based
036 * class</a>.</p>
037 *
038 * @param <T> the type of value implementations of this interface
039 * {@linkplain #get() supply}
040 *
041 * @author <a href="https://about.me/lairdnelson"
042 * target="_parent">Laird Nelson</a>
043 *
044 * @see #determinism()
045 *
046 * @see #get()
047 *
048 * @see #optional()
049 */
050@FunctionalInterface
051public interface OptionalSupplier<T> extends Supplier<T> {
052
053  /**
054   * Returns either the result of invoking the {@link #get()} method,
055   * if a {@link RuntimeException} does not occur, or the result of
056   * invoking the {@link Function#apply(Object) apply(Object)} method
057   * on the supplied {@code handler} with any {@link RuntimeException}
058   * that does occur, including {@link NoSuchElementException} and
059   * {@link UnsupportedOperationException} instances that are used to
060   * indicate value absence.
061   *
062   * @param handler the exception handler; must not be {@code null}
063   *
064   * @return either the result of invoking the {@link #get()} method,
065   * if a {@link RuntimeException} does not occur, or the result of
066   * invoking the {@link Function#apply(Object) apply(Object)} method
067   * on the supplied {@code handler} with any {@link RuntimeException}
068   * that does occur
069   *
070   * @exception NullPointerException if {@code handler} is {@code
071   * null}
072   *
073   * @nullability This method and its (discouraged) overrides may
074   * return {@code null}
075   *
076   * @idempotency No guarantees are made about idempotency or
077   * determinism.
078   *
079   * @threadsafety This method itself is, and its (discouraged)
080   * overrides must be, safe for concurrent use by multiple threads,
081   * but the {@link Function#apply(Object) apply(Object)} method of
082   * the supplied {@code handler} may not be.
083   *
084   * @see #get()
085   */
086  public default T exceptionally(final Function<? super RuntimeException, ? extends T> handler) {
087    try {
088      return this.get();
089    } catch (final RuntimeException e) {
090      try {
091        return handler.apply(e);
092      } catch (final RuntimeException r) {
093        r.addSuppressed(e);
094        throw r;
095      }
096    }
097  }
098
099  /**
100   * Returns a value, which may be {@code null}.
101   *
102   * <p>This method's contract extends {@link Supplier#get()}'s
103   * contract with the following additional requirements:</p>
104   *
105   * <ul>
106   *
107   * <li><strong>It is deliberately and explicitly permitted for
108   * implementations of this method to return {@code null} for any
109   * reason.</strong> Callers of this method must be appropriately
110   * prepared.</li>
111   *
112   * <li>If an invocation of the {@link #determinism()} method, on any
113   * thread, returns any of {@link Determinism#ABSENT}, {@link
114   * Determinism#DETERMINISTIC} or {@link Determinism#PRESENT}, then
115   * additional requirements apply to the implementation of this
116   * method; see the {@link #determinism()} method documentation for
117   * details.</li>
118   *
119   * <li>An implementation of this method need not be deterministic if
120   * an invocation of the {@link #determinism()} method returns {@link
121   * Determinism#NON_DETERMINISTIC}.</li>
122   *
123   * <li>An implementation of this method may indicate the (possibly
124   * transitory) absence of a value by any of the following means:
125   *
126   * <ul>
127   *
128   * <li>Throwing a {@link NoSuchElementException}.</li>
129   *
130   * <li>Throwing an {@link UnsupportedOperationException}.</li>
131   *
132   * </ul></li>
133   *
134   * </ul>
135   *
136   * @return a value, which may be {@code null}
137   *
138   * @exception NoSuchElementException to indicate (usually
139   * transitory) absence
140   *
141   * @exception UnsupportedOperationException to indicate (usually
142   * permanent) absence
143   *
144   * @nullability Implementations of this method may, and often will,
145   * return {@code null}, even in the normal course of events.
146   *
147   * @threadsafety Implementations of this method must be safe for
148   * concurrent use by multiple threads.
149   *
150   * @idempotency No guarantees are made about idempotency or
151   * determinism.  An ideal implementation should be idempotent.  If
152   * the {@link #determinism() determinism()} method returns a {@link
153   * Determinism} that is not {@link Determinism#NON_DETERMINISTIC}, then any
154   * implementation of this method must be deterministic.
155   *
156   * @see #determinism()
157   */
158  @Override
159  public T get();
160
161  /**
162   * Returns the result of invoking the {@link
163   * BiFunction#apply(Object, Object) apply(Object, Object)} method on
164   * the supplied {@code handler}, supplying it with the result of an
165   * invocation of the {@link #get()} method, which may be {@code
166   * null}, or any {@link RuntimeException} that an invocation of the
167   * {@link #get()} method throws, including {@link
168   * NoSuchElementException} and {@link UnsupportedOperationException}
169   * instances that are used to indicate value absence.
170   *
171   * <p>The first argument to the handler will be the return value of
172   * the {@link #get()} method, which may be {@code null}.  The second
173   * argument to the handler will be any {@link RuntimeException} that
174   * was thrown during the invocation of the {@link #get()} method,
175   * including {@link NoSuchElementException} and {@link
176   * UnsupportedOperationException} instances that are used to
177   * indicate value absence.</p>
178   *
179   * @param <U> the type of the value returned
180   *
181   * @param handler the handler; must not be {@code null}
182   *
183   * @return the result of invoking the {@link
184   * BiFunction#apply(Object, Object) apply(Object, Object)} method on
185   * the supplied {@code handler}, supplying it with the result of an
186   * invocation of the {@link #get()} method, which may be {@code
187   * null}, or any {@link RuntimeException} that an invocation of the
188   * {@link #get()} method throws, including {@link
189   * NoSuchElementException} and {@link UnsupportedOperationException}
190   * instances that are used to indicate value absence
191   *
192   * @exception NullPointerException if {@code handler} is {@code
193   * null}
194   *
195   * @nullability This method and its (discouraged) overrides may
196   * return {@code null}.
197   *
198   * @threadsafety This method is, and its (discouraged) overrides
199   * must be, safe for concurrent use by multiple threads.
200   *
201   * @idempotency No guarantees are made about idempotency or
202   * determinism.
203   *
204   * @see #get()
205   */
206  public default <U> U handle(final BiFunction<? super T, ? super RuntimeException, ? extends U> handler) {
207    final T value;
208    try {
209      value = this.get();
210    } catch (final RuntimeException e) {
211      try {
212        return handler.apply(null, e);
213      } catch (final RuntimeException r) {
214        r.addSuppressed(e);
215        throw r;
216      }
217    }
218    return handler.apply(value, null);
219  }
220
221  /**
222   * Invokes the {@link Consumer#accept(Object) accept(Object)} method
223   * on the supplied {@code action} with the return value of an
224   * invocation of the {@link #get()} method, which may be {@code
225   * null}, unless the {@link #get()} method throws either a {@link
226   * NoSuchElementException} or an {@link
227   * UnsupportedOperationException}, indicating value absence, in
228   * which case no action is taken.
229   *
230   * @param action the {@link Consumer} representing the action to
231   * take; must not be {@code null}
232   *
233   * @exception NullPointerException if {@code action} is {@code null}
234   *
235   * @idempotency No guarantees are made about idempotency or
236   * determinism.
237   *
238   * @threadsafety This method is, and its (discouraged) overrides
239   * must be, safe for concurrent use by multiple threads, but the
240   * supplied {@link Consumer}'s {@link Consumer#accept(Object)
241   * accept(Object)} method may not be
242   *
243   * @see #get()
244   */
245  public default void ifPresent(final Consumer<? super T> action) {
246    final T value;
247    try {
248      value = this.get();
249    } catch (final NoSuchElementException | UnsupportedOperationException e) {
250      return;
251    }
252    action.accept(value);
253  }
254
255  /**
256   * Invokes the {@link Consumer#accept(Object) accept(Object)} method
257   * on the supplied {@code presentAction} with the return value of an
258   * invocation of the {@link #get()} method, which may be {@code
259   * null}, or, if the {@link #get()} method indicates value absence
260   * by throwing either a {@link NoSuchElementException} or an {@link
261   * UnsupportedOperationException}, invokes the {@link Runnable#run()
262   * run()} method of the supplied {@code absentAction} instead.
263   *
264   * @param presentAction the {@link Consumer} representing the action
265   * to take if a value is present; must not be {@code null}
266   *
267   * @param absentAction the {@link Runnable} representing the action
268   * to take if a value is absent; must not be {@code null}
269   *
270   * @exception NullPointerException if {@code action} or {@code
271   * absentAction} is {@code null}
272   *
273   * @idempotency No guarantees are made about idempotency or
274   * determinism.
275   *
276   * @threadsafety This method is, and its (discouraged) overrides
277   * must be, safe for concurrent use by multiple threads, but the
278   * supplied {@link Consumer}'s {@link Consumer#accept(Object)
279   * accept(Object)} method may not be and the supplied {@link
280   * Runnable}'s {@link Runnable#run() run()} method may not be
281   *
282   * @see #get()
283   */
284  public default void ifPresentOrElse(final Consumer<? super T> presentAction, final Runnable absentAction) {
285    final T value;
286    try {
287      value = this.get();
288    } catch (final NoSuchElementException | UnsupportedOperationException e) {
289      try {
290        absentAction.run();
291        return;
292      } catch (final RuntimeException r) {
293        r.addSuppressed(e);
294        throw r;
295      }
296    }
297    presentAction.accept(value);
298  }
299
300  /**
301   * Returns a non-{@code null} but possibly {@linkplain
302   * Optional#isEmpty() empty} {@link Optional} representing this
303   * {@link OptionalSupplier}'s {@linkplain #get() value}.
304   *
305   * <p>The default implementation of this method does not and its
306   * overrides must not return {@code null}.</p>
307   *
308   * <p>The default implementation of this method catches all {@link
309   * NoSuchElementException}s and {@link
310   * UnsupportedOperationException}s and returns an empty {@link
311   * Optional} in these cases, which may not be valid for some use
312   * cases.  To detect permanent versus transitory absence, potential
313   * callers should use the {@link #get()} method directly or either
314   * the {@link #optional(Function)} or {@link #optional(BiFunction)}
315   * methods.</p>
316   *
317   * @return a non-{@code null} but possibly {@linkplain
318   * Optional#isEmpty() empty} {@link Optional} representing this
319   * {@link OptionalSupplier}'s {@linkplain #get() value}
320   *
321   * @nullability The default implementation of this method does not,
322   * and its (discouraged) overrides must not, return {@code null}.
323   *
324   * @threadsafety The default implementation of this method is, and
325   * its (discouraged) overrides must be, safe for concurrent use by
326   * multiple threads.
327   *
328   * @idempotency No guarantees are made about idempotency or
329   * determinism.
330   *
331   * @see #optional(BiFunction)
332   *
333   * @see #get()
334   */
335  public default Optional<T> optional() {
336    return this.optional(OptionalSupplier::returnNull);
337  }
338
339  /**
340   * Invokes the {@link #handle(BiFunction)} method, supplying it with
341   * the supplied {@code handler}, supplies its return value to the
342   * {@link Optional#ofNullable(Object)} method, and returns the
343   * result.
344   *
345   * @param <U> the type of the returned {@link Optional}
346   *
347   * @param handler the handler; must not be {@code null}
348   *
349   * @return the result of invoking the {@link
350   * Optional#ofNullable(Object)} method supplied with the return
351   * value of invoking the {@link #handle(BiFunction)} method with the
352   * supplied {@code handler}
353   *
354   * @exception NullPointerException if {@code handler} is {@code
355   * null}
356   *
357   * @nullability This method does not, and its (discouraged)
358   * overrides must not, return {@code null}.
359   *
360   * @idempotency No guarantees are made about idempotency or
361   * determinism.
362   *
363   * @threadsafety This method is, and its (discouraged) overrides
364   * must be, safe for concurrent use by multiple threads.
365   *
366   * @see #handle(BiFunction)
367   *
368   * @see Optional#ofNullable(Object)
369   */
370  public default <U> Optional<U> optional(final BiFunction<? super T, ? super RuntimeException, ? extends U> handler) {
371    return Optional.ofNullable(this.handle(handler));
372  }
373
374  /**
375   * Invokes the {@link #exceptionally(Function)} method, supplying it
376   * with the supplied {@code handler}, supplies its return value to
377   * the {@link Optional#ofNullable(Object)} method, and returns the
378   * result.
379   *
380   * @param handler the handler; must not be {@code null}
381   *
382   * @return the result of invoking the {@link
383   * Optional#ofNullable(Object)} method supplied with the return
384   * value of invoking the {@link #exceptionally(Function)} method
385   * with the supplied {@code handler}
386   *
387   * @exception NullPointerException if {@code handler} is {@code
388   * null}
389   *
390   * @nullability This method does not, and its (discouraged)
391   * overrides must not, return {@code null}.
392   *
393   * @idempotency No guarantees are made about idempotency or
394   * determinism.
395   *
396   * @threadsafety This method is, and its (discouraged) overrides
397   * must be, safe for concurrent use by multiple threads.
398   *
399   * @see #exceptionally(Function)
400   *
401   * @see Optional#ofNullable(Object)
402   */
403  public default Optional<T> optional(final Function<? super RuntimeException, ? extends T> handler) {
404    return Optional.ofNullable(this.exceptionally(handler));
405  }
406
407  /**
408   * Returns the result of invoking the {@link #get()} method, which
409   * may be {@code null}, or, if the {@link #get()} method indicates
410   * value absence by throwing either a {@link NoSuchElementException}
411   * or an {@link UnsupportedOperationException}, returns the supplied
412   * alternate value, which may be {@code null}.
413   *
414   * @param other the alternate value; may be {@code null}
415   *
416   * @return the result of invoking the {@link #get()} method, which
417   * may be {@code null}, or, if the {@link #get()} method indicates
418   * value absence by throwing either a {@link NoSuchElementException}
419   * or an {@link UnsupportedOperationException}, returns the supplied
420   * alternate value, which may be {@code null}
421   *
422   * @nullability This method and its (discouraged) overrides may
423   * return {@code null}.
424   *
425   * @idempotency No guarantees are made about idempotency or
426   * determinism.
427   *
428   * @threadsafety This method is, and its (discouraged) overrides
429   * must be, safe for concurrent use by multiple threads.
430   *
431   * @see #get()
432   */
433  public default T orElse(final T other) {
434    try {
435      return this.get();
436    } catch (final NoSuchElementException | UnsupportedOperationException e) {
437      return other;
438    }
439  }
440
441  /**
442   * Returns the result of invoking the {@link #get()} method, which
443   * may be {@code null}, or, if the {@link #get()} method indicates
444   * value absence by throwing either a {@link NoSuchElementException}
445   * or an {@link UnsupportedOperationException}, returns the result
446   * of invoking the {@link #get()} method on the supplied {@link
447   * Supplier}, which may be {@code null}.
448   *
449   * @param supplier the alternate value {@link Supplier}; must not be
450   * {@code null}
451   *
452   * @return the result of invoking the {@link #get()} method, which
453   * may be {@code null}, or, if the {@link #get()} method indicates
454   * value absence by throwing either a {@link NoSuchElementException}
455   * or an {@link UnsupportedOperationException}, returns the result
456   * of invoking the {@link #get()} method on the supplied {@link
457   * Supplier}, which may be {@code null}
458   *
459   * @exception NullPointerException if {@code supplier} is {@code
460   * null}
461   *
462   * @nullability This method and its (discouraged) overrides may
463   * return {@code null}.
464   *
465   * @idempotency No guarantees are made about idempotency or
466   * determinism.
467   *
468   * @threadsafety This method is, and its (discouraged) overrides
469   * msut be, safe for concurrent use by multiple threads, but the
470   * {@link Supplier#get() get()} method of the supplied {@code supplier}
471   * may not be
472   *
473   * @see #get()
474   */
475  public default T orElseGet(final Supplier<? extends T> supplier) {
476    try {
477      return this.get();
478    } catch (final NoSuchElementException | UnsupportedOperationException e) {
479      try {
480        return supplier.get();
481      } catch (final RuntimeException r) {
482        r.addSuppressed(e);
483        throw r;
484      }
485    }
486  }
487
488  /**
489   * Returns the result of invoking the {@link #get()} method, which
490   * may be {@code null}.
491   *
492   * @return the result of invoking the {@link #get()} method, which
493   * may be {@code null}
494   *
495   * @exception NoSuchElementException if value absence was indicated
496   * by the {@link #get()} method
497   *
498   * @nullability This method and its (discouraged) overrides may
499   * return {@code null}.
500   *
501   * @idempotency No guarantees are made about idempotency or
502   * determinism.
503   *
504   * @threadsafety This method is, and its (discouraged) overrides
505   * must be, safe for concurrent use by multiple threads.
506   *
507   * @see #orElseThrow(Supplier)
508   */
509  public default T orElseThrow() {
510    try {
511      return this.get();
512    } catch (final UnsupportedOperationException e) {
513      throw new NoSuchElementException(e.getMessage(), e);
514    }
515  }
516
517  /**
518   * Returns the result of invoking the {@link #get()} method, which
519   * may be {@code null}, or, if the {@link #get()} method indicates
520   * value absence by throwing either a {@link NoSuchElementException}
521   * or an {@link UnsupportedOperationException}, throws the return
522   * value of an invocation of the supplied {@link Supplier}'s {@link
523   * Supplier#get() get()} method.
524   *
525   * @param <X> the type of {@link Throwable} the supplied {@code
526   * throwableSupplier} {@linkplain Supplier#get() supplies}
527   *
528   * @param throwableSupplier the {@link Throwable} {@link Supplier};
529   * must not be {@code null}
530   *
531   * @return the result of invoking the {@link #get()} method, which
532   * may be {@code null}, or, if the {@link #get()} method indicates
533   * value absence by throwing either a {@link NoSuchElementException}
534   * or an {@link UnsupportedOperationException}, throws the return
535   * value of an invocation of the supplied {@link Supplier}'s {@link
536   * Supplier#get() get()} method
537   *
538   * @exception NullPointerException if {@code supplier} is {@code
539   * null}
540   *
541   * @exception X (actually {@code <X>}) if the {@link #get()} method
542   * throws either a {@link NoSuchElementException} or an {@link
543   * UnsupportedOperationException}
544   *
545   * @nullability This method and its (discouraged) overrides may
546   * return {@code null}.
547   *
548   * @idempotency No guarantees are made about idempotency or
549   * determinism.
550   *
551   * @threadsafety This method itself is, and its (discouraged)
552   * overrides must be, safe for concurrent use by multiple threads.
553   *
554   * @see #get()
555   */
556  public default <X extends Throwable> T orElseThrow(final Supplier<? extends X> throwableSupplier) throws X {
557    try {
558      return this.get();
559    } catch (final NoSuchElementException | UnsupportedOperationException e) {
560      final X throwable = throwableSupplier.get();
561      if (throwable.getCause() == null) {
562        throwable.initCause(e);
563      } else {
564        throwable.addSuppressed(e);
565      }
566      throw throwable;
567    }
568  }
569
570  /**
571   * Returns an {@link Determinism} denoting the presence of values
572   * returned by this {@link OptionalSupplier}'s {@link #get() get()}
573   * method.
574   *
575   * <p>Overrides of this method must be compatible with the
576   * implementation of the {@link #get()} method.  Specifically:</p>
577   *
578   * <ul>
579   *
580   * <li>If an override of this method returns {@link
581   * Determinism#PRESENT}, then the implementation of the {@link #get()}
582   * method must never throw either a {@link NoSuchElementException}
583   * or an {@link UnsupportedOperationException}, and, for any two
584   * invocations, on any thread, must return either the same object, or
585   * objects that are indistinguishable from one another and that can
586   * be substituted for each other interchangeably.</li>
587   *
588   * <li>If an override of this method returns {@link
589   * Determinism#ABSENT}, then it is expected that any two invocations of
590   * the {@link #get()} method, on any thread, will each throw either
591   * a {@link NoSuchElementException} or an {@link
592   * UnsupportedOperationException}.  If an implementation of the
593   * {@link #get()} method instead returns a value, contrary to these
594   * requirements, then the value must be treated as irrelevant or
595   * undefined.</li>
596   *
597   * <li>If an override of this method returns {@link
598   * Determinism#DETERMINISTIC}, then any two invocations of the {@link
599   * #get()} method implementation, on any thread, must either throw
600   * either a {@link NoSuchElementException} or an {@link
601   * UnsupportedOperationException}, or must return either the same
602   * object, or objects that are indistinguishable from one another
603   * and that can be substituted for each other interchangeably.</li>
604   *
605   * <li>If an override of this method returns {@link
606   * Determinism#NON_DETERMINISTIC}, then there are no additional requirements
607   * placed upon the implementation of the {@link #get()} method
608   * besides those defined in {@linkplain #get() its existing
609   * contract}.</li>
610   *
611   * </ul>
612   *
613   * <p>Additionally, once an override of this method returns a {@link
614   * Determinism} whose {@link Determinism#deterministic() deterministic()}
615   * method returns {@code true}, then it must forever afterwards, for
616   * all invocations, on all possible threads, return the same {@link
617   * Determinism}.</p>
618   *
619   * <p>If any of the requirements above is not met, undefined
620   * behavior may result.</p>
621   *
622   * <p>The default implementation of this method returns {@link
623   * Determinism#NON_DETERMINISTIC}.  Overrides are strongly encouraged.</p>
624   *
625   * @return an {@link Determinism} denoting the presence of values
626   * returned by this {@link OptionalSupplier}'s {@link #get() get()}
627   * method
628   *
629   * @nullability This method does not, and its (encouraged) overrides
630   * must not, return {@code null}.
631   *
632   * @idempotency This method is idempotent and deterministic.  Its
633   * (encouraged) overrides must be idempotent.  They may not be
634   * deterministic (see above).
635   *
636   * @threadsafety This method is, and its (encouraged) overrides must
637   * be, safe for concurrent use by multiple threads.
638   */
639  public default Determinism determinism() {
640    return Determinism.NON_DETERMINISTIC;
641  }
642
643  /**
644   * Returns the result of invoking the {@link Stream#of(Object)}
645   * method on the return value of an invocation of the {@link #get()}
646   * method, which may be {@code null}, or, if the {@link #get()}
647   * method indicates value absence by throwing either a {@link
648   * NoSuchElementException} or an {@link
649   * UnsupportedOperationException}, returns the result of invoking
650   * the {@link Stream#empty()} method.
651   *
652   * <p>Note that this means the sole element of the {@link Stream}
653   * that is returned may be {@code null}.  If this is undesirable,
654   * consider invoking {@link Optional#stream() stream()} on the
655   * return value of the {@link #optional()} method instead.</p>
656   *
657   * @return the result of invoking the {@link Stream#of(Object)}
658   * method on the return value of an invocation of the {@link #get()}
659   * method, which may be {@code null}, or, if the {@link #get()}
660   * method indicates value absence by throwing either a {@link
661   * NoSuchElementException} or an {@link
662   * UnsupportedOperationException}, returns the result of invoking
663   * the {@link Stream#empty()} method
664   *
665   * @nullability This method does not, and its (discouraged)
666   * overrides must not, return {@code null}.
667   *
668   * @idempotency No guarantees are made about idempotency or
669   * determinism.
670   *
671   * @threadsafety This method is, and its (discouraged) overrides
672   * must be, safe for concurrent use by multiple threads.
673   *
674   * @see #get()
675   */
676  public default Stream<T> stream() {
677    try {
678      return Stream.of(this.get());
679    } catch (final NoSuchElementException | UnsupportedOperationException e) {
680      return Stream.empty();
681    }
682  }
683
684
685  /*
686   * Static methods.
687   */
688
689
690  private static <T> T returnNull(final RuntimeException e) {
691    if (e instanceof NoSuchElementException || e instanceof UnsupportedOperationException) {
692      return null;
693    } else {
694      throw e;
695    }
696  }
697
698  /**
699   * Returns a new {@link OptionalSupplier} whose {@link #determinism()}
700   * method will return the supplied {@link Determinism} and whose {@link
701   * #get()} method will return the result of invoking the {@link
702   * Supplier#get()} method on the supplied {@code supplier}.
703   *
704   * @param <T> the type of value the returned {@link
705   * OptionalSupplier} will {@linkplain #get() supply}
706   *
707   * @param determinism the {@link Determinism} to use; must not be {@code null}
708   *
709   * @param supplier the {@link Supplier} whose {@link #get()} method
710   * will be called; must not be {@code null}
711   *
712   * @return a new {@link OptionalSupplier} whose {@link #determinism()}
713   * method will return the supplied {@link Determinism} and whose {@link
714   * #get()} method will return the result of invoking the {@link
715   * Supplier#get()} method on the supplied {@code supplier}
716   *
717   * @exception NullPointerException if {@code determinism} or {@code
718   * supplier} is {@code null}
719   *
720   * @nullability This method never returns {@code null}.
721   *
722   * @idempotency This method is not idempotent but is deterministic.
723   *
724   * @threadsafety This method is safe for concurrent use by multiple
725   * threads.
726   */
727  public static <T> OptionalSupplier<T> of(final Determinism determinism, final Supplier<? extends T> supplier) {
728    return new OptionalSupplierAdapter<>(determinism, supplier);
729  }
730
731  /**
732   * Invokes {@link Absence#instance()} and returns the result.
733   *
734   * @param <T> the type of the nonexistent value the returned {@link
735   * OptionalSupplier} will never {@linkplain #get() supply}
736   *
737   * @return the result of invoking {@link Absence#instance()}
738   *
739   * @nullability This method never returns {@code null}.
740   *
741   * @idempotency This method is idempotent and deterministic.
742   *
743   * @threadsafety This method is safe for concurrent use by
744   * multiple threads.
745   *
746   * @see Absence#instance()
747   */
748  public static <T> OptionalSupplier<T> of() {
749    return Absence.instance();
750  }
751
752  /**
753   * Returns an {@link OptionalSupplier} representing the supplied
754   * {@link Supplier}.
755   *
756   * @param <T> the type of value the returned {@link
757   * OptionalSupplier} will {@linkplain #get() supply}
758   *
759   * @param supplier the {@link Supplier}; may be {@code null} in
760   * which case the return value of an invocation of {@link
761   * Absence#instance()} will be returned
762   *
763   * @return an {@link OptionalSupplier} representing the supplied
764   * {@link Supplier}
765   *
766   * @nullability This method never returns {@code null}.
767   *
768   * @idempotency This method is not idempotent but is deterministic.
769   *
770   * @threadsafety This method is safe for concurrent use by
771   * multiple threads.
772   */
773  @SuppressWarnings("unchecked")
774  public static <T> OptionalSupplier<T> of(final Supplier<? extends T> supplier) {
775    if (supplier == null) {
776      return Absence.instance();
777    } else if (supplier instanceof OptionalSupplier<? extends T> os) {
778      return (OptionalSupplier<T>)os;
779    } else {
780      return new OptionalSupplierAdapter<>(supplier);
781    }
782  }
783
784  /**
785   * Returns an {@link OptionalSupplier} that will, loosely speaking,
786   * try the supplied {@code supplier} first, and, if it throws a
787   * {@link NoSuchElementException} or an {@link
788   * UnsupportedOperationException} from its {@link Supplier#get()}
789   * method, will then try the supplied {@code defaults}.
790   *
791   * <p>The supplied {@link Supplier} instances can, themselves, be
792   * {@link OptionalSupplier}s, and, if so, the resulting {@link
793   * OptionalSupplier} will have its {@link #determinism()} method
794   * appropriately implemented.</p>
795   *
796   * @param <T> the type of object the returned {@link
797   * OptionalSupplier} will {@linkplain #get() supply}
798   *
799   * @param supplier the first {@link Supplier} to try; may be {@code
800   * null}
801   *
802   * @param defaults the fallback {@link Supplier} to try; may be
803   * {@code null}
804   *
805   * @return a {@link DefaultingOptionalSupplier}
806   *
807   * @nullability This method never returns {@code null}.
808   *
809   * @idempotency This method is idempotent and deterministic.
810   *
811   * @threadsafety This method is safe for concurrent use by multiple
812   * threads.
813   */
814  public static <T> OptionalSupplier<T> of(final Supplier<? extends T> supplier, final Supplier<? extends T> defaults) {
815    if (supplier == null) {
816      if (defaults == null) {
817        return Absence.instance();
818      } else {
819        return of(defaults);
820      }
821    } else if (defaults == null) {
822      return of(supplier);
823    } else {
824      return DefaultingOptionalSupplier.of(supplier, defaults);
825    }
826  }
827
828  /**
829   * Returns a new {@link OptionalSupplier} whose {@link #determinism()}
830   * method will return {@link Determinism#PRESENT} and whose {@link
831   * #get()} method will return the supplied {@code value}.
832   *
833   * @param <T> the type of value the returned {@link
834   * OptionalSupplier} will {@linkplain #get() supply}
835   *
836   * @param value the value the new {@link OptionalSupplier} will
837   * return from its {@link #get()} method; may be {@code null}
838   *
839   * @return a new {@link OptionalSupplier} whose {@link #determinism()}
840   * method will return {@link Determinism#PRESENT} and whose {@link
841   * #get()} method will return the supplied {@code value}
842   *
843   * @nullability This method never returns {@code null}.
844   *
845   * @idempotency This method is not idempotent but is deterministic.
846   *
847   * @threadsafety This method is safe for concurrent use by multiple
848   * threads.
849   */
850  public static <T> OptionalSupplier<T> of(final T value) {
851    return FixedValueSupplier.of(value);
852  }
853
854
855  /*
856   * Inner and nested classes.
857   */
858
859
860  /**
861   * A token indicating transitory or permanent presence or absence.
862   *
863   * @author <a href="https://about.me/lairdnelson"
864   * target="_parent">Laird Nelson</a>
865   *
866   * @see #deterministic()
867   *
868   * @see OptionalSupplier#determinism()
869   */
870  public static enum Determinism {
871
872    /**
873     * An {@link Determinism} indicating an unknown, possibly
874     * transitory, determinism or absence.
875     */
876    NON_DETERMINISTIC(false),
877
878    /**
879     * An {@link Determinism} indicating an unknown permanent presence
880     * or absence.
881     */
882    DETERMINISTIC(true),
883
884    /**
885     * An {@link Determinism} indicating permanent absence.
886     */
887    ABSENT(true),
888
889    /**
890     * An {@link Determinism} indicating permanent determinism.
891     */
892    PRESENT(true);
893
894    private final boolean deterministic;
895
896    private Determinism(final boolean deterministic) {
897      this.deterministic = deterministic;
898    }
899
900    /**
901     * Returns {@code true} if the presence or absence denoted by this
902     * {@link Determinism} is deterministic.
903     *
904     * @return {@code true} if the presence or absence denoted by this
905     * {@link Determinism} is deterministic
906     *
907     * @idempotency This method is idempotent and deterministic.
908     *
909     * @threadsafety This method is safe for concurrent use by
910     * multiple threads.
911     */
912    public final boolean deterministic() {
913      return this.deterministic;
914    }
915
916  }
917
918}