/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.collect.result; import java.io.Serializable; import java.util.Arrays; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.BeanDefinition; import org.joda.beans.ImmutableBean; import org.joda.beans.ImmutableValidator; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.PropertyDefinition; import org.joda.beans.impl.direct.DirectFieldsBeanBuilder; import org.joda.beans.impl.direct.DirectMetaBean; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.opengamma.strata.collect.ArgChecker; import com.opengamma.strata.collect.Guavate; import com.opengamma.strata.collect.Messages; /** * The result of an operation, either success or failure. * <p> * This provides a functional approach to error handling, that can be used instead of exceptions. * A success result contains a non-null result value. * A failure result contains details of the {@linkplain Failure failure} that occurred. * <p> * Methods using this approach to error handling are expected to return {@code Result<T>} * and not throw exceptions. The factory method {@link #of(Supplier)} and related methods * can be used to capture exceptions and convert them to failure results. * <p> * Application code using a result should also operate in a functional style. * Use {@link #map(Function)} and {@link #flatMap(Function)} in preference to * {@link #isSuccess()} and {@link #getValue()}. * <p> * <pre> * Result{@literal <Foo>} intermediateResult = calculateIntermediateResult(); * return intermediateResult.flatMap(foo -> calculateFinalResult(foo, ...)); * </pre> * <p> * Results can be generated using the factory methods on this class. * * @param <T> the type of the underlying result for a successful invocation */ @BeanDefinition(builderScope = "private") public final class Result<T> implements ImmutableBean, Serializable { // two properties are used where one might do to reduce serialized data size /** * The value. * This is only present if the result is a success. */ @PropertyDefinition(get = "field") private final T value; /** * The failure. * This is only present if the result is a failure. */ @PropertyDefinition(get = "field") private final Failure failure; //------------------------------------------------------------------------- /** * Creates a successful result wrapping a value. * <p> * This returns a successful result object for the non-null value. * <p> * Note that passing an instance of {@code Failure} to this method would * be a programming error. * * @param <R> the type of the value * @param value the result value * @return a successful result wrapping the value */ public static <R> Result<R> success(R value) { return new Result<>(ArgChecker.notNull(value, "value")); } //------------------------------------------------------------------------- /** * Creates a failed result specifying the failure reason. * <p> * The message is produced using a template that contains zero to many "{}" placeholders. * Each placeholder is replaced by the next available argument. * If there are too few arguments, then the message will be left with placeholders. * If there are too many arguments, then the excess arguments are appended to the * end of the message. No attempt is made to format the arguments. * See {@link Messages#format(String, Object...)} for more details. * * @param <R> the expected type of the result * @param reason the result reason * @param message a message explaining the failure, uses "{}" for inserting {@code messageArgs} * @param messageArgs the arguments for the message * @return a failure result */ public static <R> Result<R> failure(FailureReason reason, String message, Object... messageArgs) { String msg = Messages.format(message, messageArgs); return new Result<>(Failure.of(FailureItem.of(reason, msg, 1))); } /** * Creates a success {@code Result} wrapping the value produced by the * supplier. * <p> * Note that if the supplier throws an exception, this will be caught * and converted to a failure {@code Result}. * * @param <T> the type of the value * @param supplier supplier of the result value * @return a success {@code Result} wrapping the value produced by the supplier */ public static <T> Result<T> of(Supplier<T> supplier) { try { return success(supplier.get()); } catch (Exception e) { return failure(e); } } /** * Creates a {@code Result} wrapping the result produced by the supplier. * <p> * Note that if the supplier throws an exception, this will be caught * and converted to a failure {@code Result}. * * @param <T> the type of the result value * @param supplier supplier of the result * @return a {@code Result} produced by the supplier */ public static <T> Result<T> wrap(Supplier<Result<T>> supplier) { try { return supplier.get(); } catch (Exception e) { return failure(e); } } /** * Creates a failed result caused by an exception. * <p> * The failure will have a reason of {@code ERROR}. * * @param <R> the expected type of the result * @param exception the cause of the failure * @return a failure result */ public static <R> Result<R> failure(Exception exception) { return new Result<>(Failure.of(FailureReason.ERROR, exception)); } /** * Creates a failed result caused by an exception. * <p> * The failure will have a reason of {@code ERROR}. * <p> * The message is produced using a template that contains zero to many "{}" placeholders. * Each placeholder is replaced by the next available argument. * If there are too few arguments, then the message will be left with placeholders. * If there are too many arguments, then the excess arguments are appended to the * end of the message. No attempt is made to format the arguments. * See {@link Messages#format(String, Object...)} for more details. * * @param <R> the expected type of the result * @param exception the cause of the failure * @param message a message explaining the failure, uses "{}" for inserting {@code messageArgs} * @param messageArgs the arguments for the message * @return a failure result */ public static <R> Result<R> failure(Exception exception, String message, Object... messageArgs) { return new Result<>(Failure.of(FailureReason.ERROR, exception, message, messageArgs)); } /** * Creates a failed result caused by an exception with a specified reason. * * @param <R> the expected type of the result * @param reason the result reason * @param exception the cause of the failure * @return a failure result */ public static <R> Result<R> failure(FailureReason reason, Exception exception) { return new Result<>(Failure.of(reason, exception)); } /** * Creates a failed result caused by an exception with a specified reason and message. * <p> * The message is produced using a template that contains zero to many "{}" placeholders. * Each placeholder is replaced by the next available argument. * If there are too few arguments, then the message will be left with placeholders. * If there are too many arguments, then the excess arguments are appended to the * end of the message. No attempt is made to format the arguments. * See {@link Messages#format(String, Object...)} for more details. * * @param <R> the expected type of the result * @param reason the result reason * @param exception the cause of the failure * @param message a message explaining the failure, uses "{}" for inserting {@code messageArgs} * @param messageArgs the arguments for the message * @return a failure result */ public static <R> Result<R> failure(FailureReason reason, Exception exception, String message, Object... messageArgs) { return new Result<>(Failure.of(reason, exception, message, messageArgs)); } /** * Returns a failed result from another failed result. * <p> * This method ensures the result type matches the expected type. * If the specified result is a successful result then an exception is thrown. * * @param <R> the expected result type * @param failureResult a failure result * @return a failure result of the expected type * @throws IllegalArgumentException if the result is a success */ @SuppressWarnings("unchecked") public static <R> Result<R> failure(Result<?> failureResult) { if (failureResult.isSuccess()) { throw new IllegalArgumentException("Result must be a failure"); } return (Result<R>) failureResult; } /** * Creates a failed result combining multiple failed results. * <p> * The input results can be successes or failures, only the failures will be included in the created result. * Intended to be used with {@link #anyFailures(Result...)}. * <blockquote><pre> * if (Result.anyFailures(result1, result2, result3) { * return Result.failure(result1, result2, result3); * } * </pre></blockquote> * * @param <R> the expected type of the result * @param result1 the first result * @param result2 the second result * @param results the rest of the results * @return a failed result wrapping multiple other failed results * @throws IllegalArgumentException if all of the results are successes */ public static <R> Result<R> failure(Result<?> result1, Result<?> result2, Result<?>... results) { ArgChecker.notNull(result1, "result1"); ArgChecker.notNull(result2, "result2"); ArgChecker.notNull(results, "results"); ImmutableList<Result<?>> list = ImmutableList.<Result<?>>builder() .add(result1) .add(result2) .addAll(Arrays.asList(results)) .build(); return failure(list); } /** * Creates a failed result combining multiple failed results. * <p> * The input results can be successes or failures, only the failures will be included in the created result. * Intended to be used with {@link #anyFailures(Iterable)}. * <blockquote><pre> * if (Result.anyFailures(results) { * return Result.failure(results); * } * </pre></blockquote> * * @param <R> the expected type of the result * @param results multiple results, of which at least one must be a failure, not empty * @return a failed result wrapping multiple other failed results * @throws IllegalArgumentException if results is empty or contains nothing but successes */ public static <R> Result<R> failure(Iterable<? extends Result<?>> results) { ArgChecker.notEmpty(results, "results"); ImmutableSet<FailureItem> items = Guavate.stream(results) .filter(Result::isFailure) .map(Result::getFailure) .flatMap(f -> f.getItems().stream()) .collect(Guavate.toImmutableSet()); if (items.isEmpty()) { throw new IllegalArgumentException("All results were successes"); } return new Result<>(Failure.of(items)); } /** * Creates a failed result containing a failure. * <p> * This is useful for converting an existing {@code Failure} instance to a result. * * @param <R> the expected type of the result * @param failure details of the failure * @return a failed result containing the specified failure */ public static <R> Result<R> failure(Failure failure) { return new Result<>(failure); } /** * Returns a success result containing the value if it is non-null, else returns a failure result * with the specified reason and message. * <p> * This is useful for interoperability with APIs that return {@code null}, for example {@code Map.get()}, where * a missing value should be treated as a failure. * <p> * The message is produced using a template that contains zero to many "{}" placeholders. * Each placeholder is replaced by the next available argument. * If there are too few arguments, then the message will be left with placeholders. * If there are too many arguments, then the excess arguments are appended to the * end of the message. No attempt is made to format the arguments. * See {@link Messages#format(String, Object...)} for more details. * * @param <R> the expected type of the result * @param value the potentially null value * @param reason the reason for the failure * @param message a message explaining the failure, uses "{}" for inserting {@code messageArgs} * @param messageArgs the arguments for the message * @return a success result if the value is non-null, else a failure result */ public static <R> Result<R> ofNullable( R value, FailureReason reason, String message, Object... messageArgs) { if (value != null) { return success(value); } else { return failure(reason, message, messageArgs); } } /** * Returns a success result containing the value if it is non-null, else returns a failure result * with a reason of {@link FailureReason#MISSING_DATA} and message to say an unexpected null was found. * <p> * This is useful for interoperability with APIs that can return {@code null} but where null is not expected. * * @param <R> the expected type of the result * @param value the potentially null value * @return a success result if the value is non-null, else a failure result */ public static <R> Result<R> ofNullable(R value) { return ofNullable(value, FailureReason.MISSING_DATA, "Found null where a value was expected"); } //------------------------------------------------------------------------- /** * Checks if all the results are successful. * * @param results the results to check * @return true if all of the results are successes */ public static boolean allSuccessful(Result<?>... results) { return Stream.of(results).allMatch(Result::isSuccess); } /** * Checks if all the results are successful. * * @param results the results to check * @return true if all of the results are successes */ public static boolean allSuccessful(Iterable<? extends Result<?>> results) { return Guavate.stream(results).allMatch(Result::isSuccess); } /** * Checks if any of the results are failures. * * @param results the results to check * @return true if any of the results are failures */ public static boolean anyFailures(Result<?>... results) { return Stream.of(results).anyMatch(Result::isFailure); } /** * Checks if any of the results are failures. * * @param results the results to check * @return true if any of the results are failures */ public static boolean anyFailures(Iterable<? extends Result<?>> results) { return Guavate.stream(results).anyMatch(Result::isFailure); } /** * Counts how many of the results are failures. * * @param results the results to check * @return the number of results that are failures */ public static long countFailures(Result<?>... results) { return Stream.of(results).filter(Result::isFailure).count(); } /** * Counts how many of the results are failures. * * @param results the results to check * @return the number of results that are failures */ public static long countFailures(Iterable<? extends Result<?>> results) { return Guavate.stream(results).filter(Result::isFailure).count(); } /** * Takes a collection of results, checks if all of them are successes * and then applies the supplied function to the successes wrapping * the result in a success result. If any of the initial results was * a failure, then a failure result reflecting the failures in the * initial results is returned. * <p> * If an exception is thrown when the function is applied, this will * be caught and a failure {@code Result} returned. * <p> * The following code shows where this method can be used. The code: * <blockquote><pre> * Set<Result<MyData>> results = goAndGatherData(); * if (Result.anyFailures(results)) { * return Result.failure(results); * } else { * Set<FooData> combined = * results.stream() * .map(Result::getValue) * .map(MyData::transformToFoo) * .collect(toSet()); * return Result.success(combined); * } * </pre></blockquote> * can be replaced with: * <blockquote><pre> * Set<Result<MyData>> results = goAndGatherData(); * return Result.combine(results, myDataStream -> * myDataStream * .map(MyData::transformToFoo) * .collect(toSet()) * ); * </pre></blockquote> * * @param results the results to be transformed if they are all successes * @param function the function to apply to the stream of results if they were all successes * @param <T> the type of the values held in the input results * @param <R> the type of the values held in the transformed results * @return a success result holding the result of applying the function to the * input results if they were all successes, a failure otherwise */ public static <T, R> Result<R> combine( Iterable<? extends Result<T>> results, Function<Stream<T>, R> function) { try { return allSuccessful(results) ? success(function.apply(extractSuccesses(results))) : failure(results); } catch (Exception e) { return failure(e); } } /** * Takes a collection of results, checks if all of them are successes * and then applies the supplied function to the successes. If any of * the initial results was a failure, then a failure result reflecting * the failures in the initial results is returned. * <p> * If an exception is thrown when the function is applied, this will * be caught and a failure {@code Result} returned. * <p> * The following code shows where this method can be used. The code: * <blockquote><pre> * Set<Result<MyData>> results = goAndGatherData(); * if (Result.anyFailures(results)) { * return Result.failure(results); * } else { * Set<FooData> combined = * results.stream() * .map(Result::getValue) * .map(MyData::transformToFoo) * .collect(toSet()); * return doSomethingReturningResult(combined); // this could fail * } * </pre></blockquote> * can be replaced with: * <blockquote><pre> * Set<Result<MyData>> results = goAndGatherData(); * return Result.flatCombine(results, myDataStream -> { * Set<CombinedData> combined = * myDataStream * .map(MyData::transformToFoo) * .collect(toSet()); * return doSomethingReturningResult(combined); // this could fail * }); * </pre></blockquote> * * @param results the results to be transformed if they are all successes * @param function the function to apply to the stream of results if they were all successes * @param <T> the type of the values held in the input results * @param <R> the type of the values held in the transformed results * @return a result holding the result of applying the function to the * input results if they were all successes, a failure otherwise */ public static <T, R> Result<R> flatCombine( Iterable<? extends Result<T>> results, Function<Stream<T>, Result<R>> function) { try { return allSuccessful(results) ? function.apply(extractSuccesses(results)) : failure(results); } catch (Exception e) { return failure(e); } } private static <T> Stream<T> extractSuccesses(Iterable<? extends Result<T>> results) { return Guavate.stream(results).map(Result::getValue); } //------------------------------------------------------------------------- /** * Creates an instance. * * @param value the value to create from */ private Result(T value) { this.value = value; this.failure = null; } /** * Creates an instance. * * @param failure the failure to create from */ private Result(Failure failure) { this.value = null; this.failure = failure; } @ImmutableValidator private void validate() { if (value == null && failure == null) { throw new IllegalArgumentException("Both value and failure are null"); } if (value != null && failure != null) { throw new IllegalArgumentException("Both value and failure are non-null"); } } //------------------------------------------------------------------------- /** * Indicates if this result represents a successful call and has a result available. * <p> * This is the opposite of {@link #isFailure()}. * * @return true if the result represents a success and a value is available */ public boolean isSuccess() { return value != null; } /** * Indicates if this result represents a failure. * <p> * This is the opposite of {@link #isSuccess()}. * * @return true if the result represents a failure */ public boolean isFailure() { return failure != null; } //------------------------------------------------------------------------- /** * Returns the actual result value if calculated successfully, throwing an * exception if a failure occurred. * <p> * If this result is a failure then an {@code IllegalStateException} will be thrown. * To avoid this, call {@link #isSuccess()} or {@link #isFailure()} first. * <p> * Application code is recommended to use {@link #map(Function)} and * {@link #flatMap(Function)} in preference to this method. * * @return the result value, only available if calculated successfully * @throws IllegalStateException if called on a failure result */ public T getValue() { if (isFailure()) { throw new IllegalStateException("Unable to get a value from a failure result: " + getFailure().getMessage()); } return value; } /** * Returns the actual result value if calculated successfully, or the specified * default value if a failure occurred. * <p> * If this result is a success then the result value is returned. * If this result is a failure then the default value is returned. * The default value must not be null. * <p> * Application code is recommended to use {@link #map(Function)} and * {@link #flatMap(Function)} in preference to this method. * * @param defaultValue the default value to return if the result is a failure * @return either the result value or the default value */ public T getValueOrElse(T defaultValue) { ArgChecker.notNull(defaultValue, "defaultValue"); return (isSuccess() ? value : defaultValue); } /** * Returns the actual result value if calculated successfully, else the * specified function is applied to the {@code Failure} that occurred. * <p> * If this result is a success then the result value is returned. * If this result is a failure then the function is applied to the failure. * The function must not be null. * <p> * This method can be used in preference to {@link #getValueOrElse(Object)} * when the default value is expensive to create. In such cases, the * default value will get created on each call, even though it will be * immediately discarded if the result is a success. * * @param mapper function used to generate a default value. The function * has no obligation to use the input {@code Failure} (in other words it can * behave as a {@code Supplier<T>} if desired). * @return either the result value or the result of the function */ public T getValueOrElseApply(Function<Failure, T> mapper) { ArgChecker.notNull(mapper, "mapper"); return (isSuccess() ? value : mapper.apply(failure)); } /** * Returns the failure instance indicating the reason why the calculation failed. * <p> * If this result is a success then an an IllegalStateException will be thrown. * To avoid this, call {@link #isSuccess()} or {@link #isFailure()} first. * * @return the details of the failure, only available if calculation failed * @throws IllegalStateException if called on a success result */ public Failure getFailure() { if (isSuccess()) { throw new IllegalStateException("Unable to get a failure from a success result"); } return failure; } //------------------------------------------------------------------------- /** * Processes a successful result by applying a function that alters the value. * <p> * This operation allows post-processing of a result value. * The specified function represents a conversion to be performed on the value. * <p> * If this result is a success, then the specified function is invoked. * The return value of the specified function is returned to the caller * wrapped in a success result. If an exception is thrown when the function * is invoked, this will be caught and a failure {@code Result} returned. * <p> * If this result is a failure, then {@code this} is returned. * The specified function is not invoked. * <p> * For example, it allows a {@code double} to be converted to a string: * <blockquote><pre> * result = ... * return result.map(value -> Double.toString(value)); * </pre></blockquote> * * @param <R> the type of the value in the returned result * @param function the function to transform the value with * @return the new result */ public <R> Result<R> map(Function<? super T, ? extends R> function) { if (isSuccess()) { try { return Result.success(function.apply(value)); } catch (Exception e) { return Result.failure(e); } } else { return Result.failure(this); } } /** * Processes a successful result by applying a function that returns another result. * <p> * This operation allows chaining of function calls that produce a result. * The specified function will typically call another method that returns a result. * <p> * If this result is a success, then the specified function is invoked. * The return value of the specified function is returned to the caller and may be * a success or failure. If an exception is thrown when the function * is invoked, this will be caught and a failure {@code Result} returned. * <p> * If this result is a failure, then an equivalent failure is returned. * The specified function is not invoked. * <p> * For example, * <blockquote><pre> * result = ... * return result.flatMap(value -> doSomething(value)); * </pre></blockquote> * * @param <R> the type of the value in the returned result * @param function the function to transform the value with * @return the new result */ public <R> Result<R> flatMap(Function<? super T, Result<R>> function) { if (isSuccess()) { try { return Objects.requireNonNull(function.apply(value)); } catch (Exception e) { return failure(e); } } else { return Result.failure(this); } } /** * Combines this result with another result. * <p> * This operation allows two results to be combined handling succeess and failure. * <p> * If both results are a success, then the specified function is invoked to combine them. * The return value of the specified function is returned to the caller and may be * a success or failure. * <p> * If either result is a failure, then a combination failure is returned. * The specified function is not invoked. * <blockquote><pre> * result1 = ... * result2 = ... * return result1.combineWith(result2, (value1, value2) -> doSomething(value1, value2)); * </pre></blockquote> * * @param other another result * @param function a function for combining values from two results * @param <U> the type of the value in the other result * @param <R> the type of the value in the returned result * @return a the result of combining the result values or a failure if either result is a failure */ public <U, R> Result<R> combineWith(Result<U> other, BiFunction<T, U, Result<R>> function) { ArgChecker.notNull(other, "other"); ArgChecker.notNull(function, "function"); if (isSuccess() && other.isSuccess()) { try { return Objects.requireNonNull(function.apply(value, other.value)); } catch (Exception e) { return failure(e); } } else { return failure(this, other); } } /** * Converts this result to a stream. * <p> * If this result is a success then a single element stream containing the result value is returned. * If this result is a failure then an empty stream is returned. * * @return a stream of size one or zero */ public Stream<T> stream() { return (isSuccess() ? Stream.of(value) : Stream.empty()); } //------------------------- AUTOGENERATED START ------------------------- ///CLOVER:OFF /** * The meta-bean for {@code Result}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static Result.Meta meta() { return Result.Meta.INSTANCE; } /** * The meta-bean for {@code Result}. * @param <R> the bean's generic type * @param cls the bean's generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static <R> Result.Meta<R> metaResult(Class<R> cls) { return Result.Meta.INSTANCE; } static { JodaBeanUtils.registerMetaBean(Result.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; private Result( T value, Failure failure) { this.value = value; this.failure = failure; validate(); } @SuppressWarnings("unchecked") @Override public Result.Meta<T> metaBean() { return Result.Meta.INSTANCE; } @Override public <R> Property<R> property(String propertyName) { return metaBean().<R>metaProperty(propertyName).createProperty(this); } @Override public Set<String> propertyNames() { return metaBean().metaPropertyMap().keySet(); } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { Result<?> other = (Result<?>) obj; return JodaBeanUtils.equal(value, other.value) && JodaBeanUtils.equal(failure, other.failure); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(value); hash = hash * 31 + JodaBeanUtils.hashCode(failure); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("Result{"); buf.append("value").append('=').append(value).append(',').append(' '); buf.append("failure").append('=').append(JodaBeanUtils.toString(failure)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code Result}. * @param <T> the type */ public static final class Meta<T> extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code value} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty<T> value = (DirectMetaProperty) DirectMetaProperty.ofImmutable( this, "value", Result.class, Object.class); /** * The meta-property for the {@code failure} property. */ private final MetaProperty<Failure> failure = DirectMetaProperty.ofImmutable( this, "failure", Result.class, Failure.class); /** * The meta-properties. */ private final Map<String, MetaProperty<?>> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "value", "failure"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty<?> metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return value; case -1086574198: // failure return failure; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder<? extends Result<T>> builder() { return new Result.Builder<T>(); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class<? extends Result<T>> beanType() { return (Class) Result.class; } @Override public Map<String, MetaProperty<?>> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code value} property. * @return the meta-property, not null */ public MetaProperty<T> value() { return value; } /** * The meta-property for the {@code failure} property. * @return the meta-property, not null */ public MetaProperty<Failure> failure() { return failure; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 111972721: // value return ((Result<?>) bean).value; case -1086574198: // failure return ((Result<?>) bean).failure; } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code Result}. * @param <T> the type */ private static final class Builder<T> extends DirectFieldsBeanBuilder<Result<T>> { private T value; private Failure failure; /** * Restricted constructor. */ private Builder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 111972721: // value return value; case -1086574198: // failure return failure; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder<T> set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 111972721: // value this.value = (T) newValue; break; case -1086574198: // failure this.failure = (Failure) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public Builder<T> set(MetaProperty<?> property, Object value) { super.set(property, value); return this; } @Override public Builder<T> setString(String propertyName, String value) { setString(meta().metaProperty(propertyName), value); return this; } @Override public Builder<T> setString(MetaProperty<?> property, String value) { super.setString(property, value); return this; } @Override public Builder<T> setAll(Map<String, ? extends Object> propertyValueMap) { super.setAll(propertyValueMap); return this; } @Override public Result<T> build() { return new Result<T>( value, failure); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("Result.Builder{"); buf.append("value").append('=').append(JodaBeanUtils.toString(value)).append(',').append(' '); buf.append("failure").append('=').append(JodaBeanUtils.toString(failure)); buf.append('}'); return buf.toString(); } } ///CLOVER:ON //-------------------------- AUTOGENERATED END -------------------------- }