All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.microbean.invoke.OptionalSupplier Maven / Gradle / Ivy

There is a newer version: 0.0.17
Show newest version
/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
 *
 * Copyright © 2022–2023 microBean™.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.microbean.invoke;

import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;

import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import java.util.stream.Stream;

/**
 * A {@link Supplier} with additional contractual requirements.
 *
 * 

An {@link OptionalSupplier} does not behave like an * {@link Optional} or a {@link * java.util.concurrent.CompletableFuture}, despite the * deliberate similarities of some method names.

* *

An implementation of this interface is not a value-based * class.

* * @param the type of value implementations of this interface * {@linkplain #get() supply} * * @author Laird Nelson * * @see #determinism() * * @see #get() * * @see #optional() */ @FunctionalInterface public interface OptionalSupplier extends Supplier { /** * Returns either the result of invoking the {@link #get()} method, * if a {@link RuntimeException} does not occur, or the result of * invoking the {@link Function#apply(Object) apply(Object)} method * on the supplied {@code handler} with any {@link RuntimeException} * that does occur, including {@link NoSuchElementException} and * {@link UnsupportedOperationException} instances that are used to * indicate value absence. * * @param handler the exception handler; must not be {@code null} * * @return either the result of invoking the {@link #get()} method, * if a {@link RuntimeException} does not occur, or the result of * invoking the {@link Function#apply(Object) apply(Object)} method * on the supplied {@code handler} with any {@link RuntimeException} * that does occur * * @exception NullPointerException if {@code handler} is {@code * null} * * @nullability This method and its (discouraged) overrides may * return {@code null} * * @idempotency No guarantees are made about idempotency or * determinism. * * @threadsafety This method itself is, and its (discouraged) * overrides must be, safe for concurrent use by multiple threads, * but the {@link Function#apply(Object) apply(Object)} method of * the supplied {@code handler} may not be. * * @see #get() */ public default T exceptionally(final Function handler) { try { return this.get(); } catch (final RuntimeException e) { try { return handler.apply(e); } catch (final RuntimeException r) { r.addSuppressed(e); throw r; } } } /** * Returns a value, which may be {@code null}. * *

This method's contract extends {@link Supplier#get()}'s * contract with the following additional requirements:

* *
    * *
  • It is deliberately and explicitly permitted for * implementations of this method to return {@code null} for any * reason. Callers of this method must be appropriately * prepared.
  • * *
  • If an invocation of the {@link #determinism()} method, on any * thread, returns any of {@link Determinism#ABSENT}, {@link * Determinism#DETERMINISTIC} or {@link Determinism#PRESENT}, then * additional requirements apply to the implementation of this * method; see the {@link #determinism()} method documentation for * details.
  • * *
  • An implementation of this method need not be deterministic if * an invocation of the {@link #determinism()} method returns {@link * Determinism#NON_DETERMINISTIC}.
  • * *
  • An implementation of this method may indicate the (possibly * transitory) absence of a value by any of the following means: * *
      * *
    • Throwing a {@link NoSuchElementException}.
    • * *
    • Throwing an {@link UnsupportedOperationException}.
    • * *
  • * *
* * @return a value, which may be {@code null} * * @exception NoSuchElementException to indicate (usually * transitory) absence * * @exception UnsupportedOperationException to indicate (usually * permanent) absence * * @nullability Implementations of this method may, and often will, * return {@code null}, even in the normal course of events. * * @threadsafety Implementations of this method must be safe for * concurrent use by multiple threads. * * @idempotency No guarantees are made about idempotency or * determinism. An ideal implementation should be idempotent. If * the {@link #determinism() determinism()} method returns a {@link * Determinism} that is not {@link Determinism#NON_DETERMINISTIC}, then any * implementation of this method must be deterministic. * * @see #determinism() */ @Override public T get(); /** * Returns the result of invoking the {@link * BiFunction#apply(Object, Object) apply(Object, Object)} method on * the supplied {@code handler}, supplying it with the result of an * invocation of the {@link #get()} method, which may be {@code * null}, or any {@link RuntimeException} that an invocation of the * {@link #get()} method throws, including {@link * NoSuchElementException} and {@link UnsupportedOperationException} * instances that are used to indicate value absence. * *

The first argument to the handler will be the return value of * the {@link #get()} method, which may be {@code null}. The second * argument to the handler will be any {@link RuntimeException} that * was thrown during the invocation of the {@link #get()} method, * including {@link NoSuchElementException} and {@link * UnsupportedOperationException} instances that are used to * indicate value absence.

* * @param the type of the value returned * * @param handler the handler; must not be {@code null} * * @return the result of invoking the {@link * BiFunction#apply(Object, Object) apply(Object, Object)} method on * the supplied {@code handler}, supplying it with the result of an * invocation of the {@link #get()} method, which may be {@code * null}, or any {@link RuntimeException} that an invocation of the * {@link #get()} method throws, including {@link * NoSuchElementException} and {@link UnsupportedOperationException} * instances that are used to indicate value absence * * @exception NullPointerException if {@code handler} is {@code * null} * * @nullability This method and its (discouraged) overrides may * return {@code null}. * * @threadsafety This method is, and its (discouraged) overrides * must be, safe for concurrent use by multiple threads. * * @idempotency No guarantees are made about idempotency or * determinism. * * @see #get() */ public default U handle(final BiFunction handler) { T value; try { value = this.get(); } catch (final RuntimeException e) { try { return handler.apply(null, e); } catch (final RuntimeException r) { r.addSuppressed(e); throw r; } } return handler.apply(value, null); } /** * Invokes the {@link Consumer#accept(Object) accept(Object)} method * on the supplied {@code action} with the return value of an * invocation of the {@link #get()} method, which may be {@code * null}, unless the {@link #get()} method throws either a {@link * NoSuchElementException} or an {@link * UnsupportedOperationException}, indicating value absence, in * which case no action is taken. * * @param action the {@link Consumer} representing the action to * take; must not be {@code null} * * @exception NullPointerException if {@code action} is {@code null} * * @idempotency No guarantees are made about idempotency or * determinism. * * @threadsafety This method is, and its (discouraged) overrides * must be, safe for concurrent use by multiple threads, but the * supplied {@link Consumer}'s {@link Consumer#accept(Object) * accept(Object)} method may not be * * @see #get() */ public default void ifPresent(final Consumer action) { T value; try { value = this.get(); } catch (final NoSuchElementException | UnsupportedOperationException e) { return; } action.accept(value); } /** * Invokes the {@link Consumer#accept(Object) accept(Object)} method * on the supplied {@code presentAction} with the return value of an * invocation of the {@link #get()} method, which may be {@code * null}, or, if the {@link #get()} method indicates value absence * by throwing either a {@link NoSuchElementException} or an {@link * UnsupportedOperationException}, invokes the {@link Runnable#run() * run()} method of the supplied {@code absentAction} instead. * * @param presentAction the {@link Consumer} representing the action * to take if a value is present; must not be {@code null} * * @param absentAction the {@link Runnable} representing the action * to take if a value is absent; must not be {@code null} * * @exception NullPointerException if {@code action} or {@code * absentAction} is {@code null} * * @idempotency No guarantees are made about idempotency or * determinism. * * @threadsafety This method is, and its (discouraged) overrides * must be, safe for concurrent use by multiple threads, but the * supplied {@link Consumer}'s {@link Consumer#accept(Object) * accept(Object)} method may not be and the supplied {@link * Runnable}'s {@link Runnable#run() run()} method may not be * * @see #get() */ public default void ifPresentOrElse(final Consumer presentAction, final Runnable absentAction) { T value; try { value = this.get(); } catch (final NoSuchElementException | UnsupportedOperationException e) { try { absentAction.run(); return; } catch (final RuntimeException r) { r.addSuppressed(e); throw r; } } presentAction.accept(value); } /** * Returns a non-{@code null} but possibly {@linkplain * Optional#isEmpty() empty} {@link Optional} representing this * {@link OptionalSupplier}'s {@linkplain #get() value}. * *

The default implementation of this method does not and its * overrides must not return {@code null}.

* *

The default implementation of this method catches all {@link * NoSuchElementException}s and {@link * UnsupportedOperationException}s and returns an empty {@link * Optional} in these cases, which may not be valid for some use * cases. To detect permanent versus transitory absence, potential * callers should use the {@link #get()} method directly or either * the {@link #optional(Function)} or {@link #optional(BiFunction)} * methods.

* * @return a non-{@code null} but possibly {@linkplain * Optional#isEmpty() empty} {@link Optional} representing this * {@link OptionalSupplier}'s {@linkplain #get() value} * * @nullability The default implementation of this method does not, * and its (discouraged) overrides must not, return {@code null}. * * @threadsafety The default implementation of this method is, and * its (discouraged) overrides must be, safe for concurrent use by * multiple threads. * * @idempotency No guarantees are made about idempotency or * determinism. * * @see #optional(BiFunction) * * @see #get() */ public default Optional optional() { return this.optional(OptionalSupplier::returnNull); } /** * Invokes the {@link #handle(BiFunction)} method, supplying it with * the supplied {@code handler}, supplies its return value to the * {@link Optional#ofNullable(Object)} method, and returns the * result. * * @param the type of the returned {@link Optional} * * @param handler the handler; must not be {@code null} * * @return the result of invoking the {@link * Optional#ofNullable(Object)} method supplied with the return * value of invoking the {@link #handle(BiFunction)} method with the * supplied {@code handler} * * @exception NullPointerException if {@code handler} is {@code * null} * * @nullability This method does not, and its (discouraged) * overrides must not, return {@code null}. * * @idempotency No guarantees are made about idempotency or * determinism. * * @threadsafety This method is, and its (discouraged) overrides * must be, safe for concurrent use by multiple threads. * * @see #handle(BiFunction) * * @see Optional#ofNullable(Object) */ public default Optional optional(final BiFunction handler) { return Optional.ofNullable(this.handle(handler)); } /** * Invokes the {@link #exceptionally(Function)} method, supplying it * with the supplied {@code handler}, supplies its return value to * the {@link Optional#ofNullable(Object)} method, and returns the * result. * * @param handler the handler; must not be {@code null} * * @return the result of invoking the {@link * Optional#ofNullable(Object)} method supplied with the return * value of invoking the {@link #exceptionally(Function)} method * with the supplied {@code handler} * * @exception NullPointerException if {@code handler} is {@code * null} * * @nullability This method does not, and its (discouraged) * overrides must not, return {@code null}. * * @idempotency No guarantees are made about idempotency or * determinism. * * @threadsafety This method is, and its (discouraged) overrides * must be, safe for concurrent use by multiple threads. * * @see #exceptionally(Function) * * @see Optional#ofNullable(Object) */ public default Optional optional(final Function handler) { return Optional.ofNullable(this.exceptionally(handler)); } /** * Returns the result of invoking the {@link #get()} method, which * may be {@code null}, or, if the {@link #get()} method indicates * value absence by throwing either a {@link NoSuchElementException} * or an {@link UnsupportedOperationException}, returns the supplied * alternate value, which may be {@code null}. * * @param other the alternate value; may be {@code null} * * @return the result of invoking the {@link #get()} method, which * may be {@code null}, or, if the {@link #get()} method indicates * value absence by throwing either a {@link NoSuchElementException} * or an {@link UnsupportedOperationException}, returns the supplied * alternate value, which may be {@code null} * * @nullability This method and its (discouraged) overrides may * return {@code null}. * * @idempotency No guarantees are made about idempotency or * determinism. * * @threadsafety This method is, and its (discouraged) overrides * must be, safe for concurrent use by multiple threads. * * @see #get() */ public default T orElse(final T other) { try { return this.get(); } catch (final NoSuchElementException | UnsupportedOperationException e) { return other; } } /** * Returns the result of invoking the {@link #get()} method, which * may be {@code null}, or, if the {@link #get()} method indicates * value absence by throwing either a {@link NoSuchElementException} * or an {@link UnsupportedOperationException}, returns the result * of invoking the {@link #get()} method on the supplied {@link * Supplier}, which may be {@code null}. * * @param supplier the alternate value {@link Supplier}; must not be * {@code null} * * @return the result of invoking the {@link #get()} method, which * may be {@code null}, or, if the {@link #get()} method indicates * value absence by throwing either a {@link NoSuchElementException} * or an {@link UnsupportedOperationException}, returns the result * of invoking the {@link #get()} method on the supplied {@link * Supplier}, which may be {@code null} * * @exception NullPointerException if {@code supplier} is {@code * null} * * @nullability This method and its (discouraged) overrides may * return {@code null}. * * @idempotency No guarantees are made about idempotency or * determinism. * * @threadsafety This method is, and its (discouraged) overrides * msut be, safe for concurrent use by multiple threads, but the * {@link Supplier#get() get()} method of the supplied {@code supplier} * may not be * * @see #get() */ public default T orElseGet(final Supplier supplier) { try { return this.get(); } catch (final NoSuchElementException | UnsupportedOperationException e) { try { return supplier.get(); } catch (final RuntimeException r) { r.addSuppressed(e); throw r; } } } /** * Returns the result of invoking the {@link #get()} method, which * may be {@code null}. * * @return the result of invoking the {@link #get()} method, which * may be {@code null} * * @exception NoSuchElementException if value absence was indicated * by the {@link #get()} method * * @nullability This method and its (discouraged) overrides may * return {@code null}. * * @idempotency No guarantees are made about idempotency or * determinism. * * @threadsafety This method is, and its (discouraged) overrides * must be, safe for concurrent use by multiple threads. * * @see #orElseThrow(Supplier) */ public default T orElseThrow() { try { return this.get(); } catch (final UnsupportedOperationException e) { throw new NoSuchElementException(e.getMessage(), e); } } /** * Returns the result of invoking the {@link #get()} method, which * may be {@code null}, or, if the {@link #get()} method indicates * value absence by throwing either a {@link NoSuchElementException} * or an {@link UnsupportedOperationException}, throws the return * value of an invocation of the supplied {@link Supplier}'s {@link * Supplier#get() get()} method. * * @param the type of {@link Throwable} the supplied {@code * throwableSupplier} {@linkplain Supplier#get() supplies} * * @param throwableSupplier the {@link Throwable} {@link Supplier}; * must not be {@code null} * * @return the result of invoking the {@link #get()} method, which * may be {@code null}, or, if the {@link #get()} method indicates * value absence by throwing either a {@link NoSuchElementException} * or an {@link UnsupportedOperationException}, throws the return * value of an invocation of the supplied {@link Supplier}'s {@link * Supplier#get() get()} method * * @exception NullPointerException if {@code supplier} is {@code * null} * * @exception X (actually {@code }) if the {@link #get()} method * throws either a {@link NoSuchElementException} or an {@link * UnsupportedOperationException} * * @nullability This method and its (discouraged) overrides may * return {@code null}. * * @idempotency No guarantees are made about idempotency or * determinism. * * @threadsafety This method itself is, and its (discouraged) * overrides must be, safe for concurrent use by multiple threads. * * @see #get() */ public default T orElseThrow(final Supplier throwableSupplier) throws X { try { return this.get(); } catch (final NoSuchElementException | UnsupportedOperationException e) { final X throwable = throwableSupplier.get(); if (throwable.getCause() == null) { throwable.initCause(e); } else { throwable.addSuppressed(e); } throw throwable; } } /** * Returns an {@link Determinism} denoting the presence of values * returned by this {@link OptionalSupplier}'s {@link #get() get()} * method. * *

Overrides of this method must be compatible with the * implementation of the {@link #get()} method. Specifically:

* *
    * *
  • If an override of this method returns {@link * Determinism#PRESENT}, then the implementation of the {@link #get()} * method must never throw either a {@link NoSuchElementException} * or an {@link UnsupportedOperationException}, and, for any two * invocations, on any thread, must return either the same object, or * objects that are indistinguishable from one another and that can * be substituted for each other interchangeably.
  • * *
  • If an override of this method returns {@link * Determinism#ABSENT}, then it is expected that any two invocations of * the {@link #get()} method, on any thread, will each throw either * a {@link NoSuchElementException} or an {@link * UnsupportedOperationException}. If an implementation of the * {@link #get()} method instead returns a value, contrary to these * requirements, then the value must be treated as irrelevant or * undefined.
  • * *
  • If an override of this method returns {@link * Determinism#DETERMINISTIC}, then any two invocations of the {@link * #get()} method implementation, on any thread, must either throw * either a {@link NoSuchElementException} or an {@link * UnsupportedOperationException}, or must return either the same * object, or objects that are indistinguishable from one another * and that can be substituted for each other interchangeably.
  • * *
  • If an override of this method returns {@link * Determinism#NON_DETERMINISTIC}, then there are no additional requirements * placed upon the implementation of the {@link #get()} method * besides those defined in {@linkplain #get() its existing * contract}.
  • * *
* *

Additionally, once an override of this method returns a {@link * Determinism} whose {@link Determinism#deterministic() deterministic()} * method returns {@code true}, then it must forever afterwards, for * all invocations, on all possible threads, return the same {@link * Determinism}.

* *

If any of the requirements above is not met, undefined * behavior may result.

* *

The default implementation of this method returns {@link * Determinism#NON_DETERMINISTIC}. Overrides are strongly encouraged.

* * @return an {@link Determinism} denoting the presence of values * returned by this {@link OptionalSupplier}'s {@link #get() get()} * method * * @nullability This method does not, and its (encouraged) overrides * must not, return {@code null}. * * @idempotency This method is idempotent and deterministic. Its * (encouraged) overrides must be idempotent. They may not be * deterministic (see above). * * @threadsafety This method is, and its (encouraged) overrides must * be, safe for concurrent use by multiple threads. */ public default Determinism determinism() { return Determinism.NON_DETERMINISTIC; } /** * Returns the result of invoking the {@link Stream#of(Object)} * method on the return value of an invocation of the {@link #get()} * method, which may be {@code null}, or, if the {@link #get()} * method indicates value absence by throwing either a {@link * NoSuchElementException} or an {@link * UnsupportedOperationException}, returns the result of invoking * the {@link Stream#empty()} method. * *

Note that this means the sole element of the {@link Stream} * that is returned may be {@code null}. If this is undesirable, * consider invoking {@link Optional#stream() stream()} on the * return value of the {@link #optional()} method instead.

* * @return the result of invoking the {@link Stream#of(Object)} * method on the return value of an invocation of the {@link #get()} * method, which may be {@code null}, or, if the {@link #get()} * method indicates value absence by throwing either a {@link * NoSuchElementException} or an {@link * UnsupportedOperationException}, returns the result of invoking * the {@link Stream#empty()} method * * @nullability This method does not, and its (discouraged) * overrides must not, return {@code null}. * * @idempotency No guarantees are made about idempotency or * determinism. * * @threadsafety This method is, and its (discouraged) overrides * must be, safe for concurrent use by multiple threads. * * @see #get() */ public default Stream stream() { try { return Stream.of(this.get()); } catch (final NoSuchElementException | UnsupportedOperationException e) { return Stream.empty(); } } /* * Static methods. */ private static T returnNull(final RuntimeException e) { if (e instanceof NoSuchElementException || e instanceof UnsupportedOperationException) { return null; } else { throw e; } } /** * Returns a new {@link OptionalSupplier} whose {@link #determinism()} * method will return the supplied {@link Determinism} and whose {@link * #get()} method will return the result of invoking the {@link * Supplier#get()} method on the supplied {@code supplier}. * * @param the type of value the returned {@link * OptionalSupplier} will {@linkplain #get() supply} * * @param determinism the {@link Determinism} to use; must not be {@code null} * * @param supplier the {@link Supplier} whose {@link #get()} method * will be called; must not be {@code null} * * @return a new {@link OptionalSupplier} whose {@link #determinism()} * method will return the supplied {@link Determinism} and whose {@link * #get()} method will return the result of invoking the {@link * Supplier#get()} method on the supplied {@code supplier} * * @exception NullPointerException if {@code determinism} or {@code * supplier} is {@code null} * * @nullability This method never returns {@code null}. * * @idempotency This method is not idempotent but is deterministic. * * @threadsafety This method is safe for concurrent use by multiple * threads. */ public static OptionalSupplier of(final Determinism determinism, final Supplier supplier) { return new OptionalSupplierAdapter<>(determinism, supplier); } /** * Invokes {@link Absence#instance()} and returns the result. * * @param the type of the nonexistent value the returned {@link * OptionalSupplier} will never {@linkplain #get() supply} * * @return the result of invoking {@link Absence#instance()} * * @nullability This method never returns {@code null}. * * @idempotency This method is idempotent and deterministic. * * @threadsafety This method is safe for concurrent use by * multiple threads. * * @see Absence#instance() */ public static OptionalSupplier of() { return Absence.instance(); } /** * Returns an {@link OptionalSupplier} representing the supplied * {@link Supplier}. * * @param the type of value the returned {@link * OptionalSupplier} will {@linkplain #get() supply} * * @param supplier the {@link Supplier}; may be {@code null} in * which case the return value of an invocation of {@link * Absence#instance()} will be returned * * @return an {@link OptionalSupplier} representing the supplied * {@link Supplier} * * @nullability This method never returns {@code null}. * * @idempotency This method is not idempotent but is deterministic. * * @threadsafety This method is safe for concurrent use by * multiple threads. */ @SuppressWarnings("unchecked") public static OptionalSupplier of(final Supplier supplier) { if (supplier == null) { return Absence.instance(); } else if (supplier instanceof OptionalSupplier os) { return (OptionalSupplier)os; } else { return new OptionalSupplierAdapter<>(supplier); } } /** * Returns an {@link OptionalSupplier} that will, loosely speaking, * try the supplied {@code supplier} first, and, if it throws a * {@link NoSuchElementException} or an {@link * UnsupportedOperationException} from its {@link Supplier#get()} * method, will then try the supplied {@code defaults}. * *

The supplied {@link Supplier} instances can, themselves, be * {@link OptionalSupplier}s, and, if so, the resulting {@link * OptionalSupplier} will have its {@link #determinism()} method * appropriately implemented.

* * @param the type of object the returned {@link * OptionalSupplier} will {@linkplain #get() supply} * * @param supplier the first {@link Supplier} to try; may be {@code * null} * * @param defaults the fallback {@link Supplier} to try; may be * {@code null} * * @return a {@link DefaultingOptionalSupplier} * * @nullability This method never returns {@code null}. * * @idempotency This method is idempotent and deterministic. * * @threadsafety This method is safe for concurrent use by multiple * threads. */ public static OptionalSupplier of(final Supplier supplier, final Supplier defaults) { if (supplier == null) { if (defaults == null) { return Absence.instance(); } else { return of(defaults); } } else if (defaults == null) { return of(supplier); } else { return DefaultingOptionalSupplier.of(supplier, defaults); } } /** * Returns a new {@link OptionalSupplier} whose {@link #determinism()} * method will return {@link Determinism#PRESENT} and whose {@link * #get()} method will return the supplied {@code value}. * * @param the type of value the returned {@link * OptionalSupplier} will {@linkplain #get() supply} * * @param value the value the new {@link OptionalSupplier} will * return from its {@link #get()} method; may be {@code null} * * @return a new {@link OptionalSupplier} whose {@link #determinism()} * method will return {@link Determinism#PRESENT} and whose {@link * #get()} method will return the supplied {@code value} * * @nullability This method never returns {@code null}. * * @idempotency This method is not idempotent but is deterministic. * * @threadsafety This method is safe for concurrent use by multiple * threads. */ public static OptionalSupplier of(final T value) { return FixedValueSupplier.of(value); } /* * Inner and nested classes. */ /** * A token indicating transitory or permanent presence or absence. * * @author Laird Nelson * * @see #deterministic() * * @see OptionalSupplier#determinism() */ public static enum Determinism { /** * An {@link Determinism} indicating an unknown, possibly * transitory, determinism or absence. */ NON_DETERMINISTIC(false), /** * An {@link Determinism} indicating an unknown permanent presence * or absence. */ DETERMINISTIC(true), /** * An {@link Determinism} indicating permanent absence. */ ABSENT(true), /** * An {@link Determinism} indicating permanent determinism. */ PRESENT(true); private final boolean deterministic; private Determinism(final boolean deterministic) { this.deterministic = deterministic; } /** * Returns {@code true} if the presence or absence denoted by this * {@link Determinism} is deterministic. * * @return {@code true} if the presence or absence denoted by this * {@link Determinism} is deterministic * * @idempotency This method is idempotent and deterministic. * * @threadsafety This method is safe for concurrent use by * multiple threads. */ public final boolean deterministic() { return this.deterministic; } } }