github.com/searKing/golang/go@v1.2.74/util/optional/optional.go (about)

     1  // Copyright 2020 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package optional
     6  
     7  import (
     8  	"errors"
     9  
    10  	"github.com/searKing/golang/go/util/function/consumer"
    11  	"github.com/searKing/golang/go/util/function/predicate"
    12  	"github.com/searKing/golang/go/util/object"
    13  )
    14  
    15  var (
    16  	ErrorNoValuePresent = errors.New("no value present")
    17  )
    18  
    19  // Optional is a container object which may or may not contain a non-{@code null} value.
    20  // If a value is present, {@code isPresent()} returns {@code true}. If no
    21  // value is present, the object is considered <i>empty</i> and
    22  // {@code isPresent()} returns {@code false}.
    23  type Optional struct {
    24  	isPresent bool
    25  	value     interface{}
    26  }
    27  
    28  // Empty returns an empty {@code Optional} instance.  No value is present for this
    29  // {@code Optional}.
    30  func Empty() Optional {
    31  	return Optional{}
    32  }
    33  
    34  // Of Returns an {@code Optional} describing the given value.
    35  func Of(value interface{}) Optional {
    36  	return Optional{
    37  		isPresent: true,
    38  		value:     value,
    39  	}
    40  }
    41  
    42  // Of Returns an {@code Optional} describing the given value, if
    43  // non-{@code null}, otherwise returns an empty {@code Optional}.
    44  func OfNillable(value interface{}) Optional {
    45  	if value == nil {
    46  		return Empty()
    47  	}
    48  	return Of(value)
    49  }
    50  
    51  // Get returns the value if a value is present, otherwise throws
    52  // {@code ErrorNoValuePresent}.
    53  func (o Optional) Get() interface{} {
    54  	return o.value
    55  }
    56  
    57  // IsPresent returns {@code true} if a value is present, otherwise {@code false}.
    58  func (o Optional) IsPresent() bool {
    59  	return o.isPresent
    60  }
    61  
    62  type EmptyConsumer interface {
    63  	Run()
    64  }
    65  
    66  /**
    67   * If a value is present, performs the given action with the value,
    68   * otherwise does nothing.
    69   *
    70   * @param action the action to be performed, if a value is present
    71   * @throws ErrorNilPointer if value is present and the given action is
    72   *         {@code null}
    73   */
    74  func (o Optional) IfPresent(action consumer.Consumer) {
    75  	if o.IsPresent() {
    76  		action.Accept(o.value)
    77  	}
    78  }
    79  
    80  /**
    81   * If a value is present, performs the given action with the value,
    82   * otherwise performs the given empty-based action.
    83   *
    84   * @param action the action to be performed, if a value is present
    85   * @param emptyAction the empty-based action to be performed, if no value is
    86   *        present
    87   * @throws NullPointerException if a value is present and the given action
    88   *         is {@code null}, or no value is present and the given empty-based
    89   *         action is {@code null}.
    90   * @since 9
    91   */
    92  func (o Optional) IfPresentOrElse(action consumer.Consumer, emptyAction EmptyConsumer) {
    93  	if o.IsPresent() {
    94  		action.Accept(o.value)
    95  		return
    96  	}
    97  	emptyAction.Run()
    98  }
    99  
   100  /**
   101   * If a value is present, and the value matches the given predicate,
   102   * returns an {@code Optional} describing the value, otherwise returns an
   103   * empty {@code Optional}.
   104   *
   105   * @param predicate the predicate to apply to a value, if present
   106   * @return an {@code Optional} describing the value of this
   107   *         {@code Optional}, if a value is present and the value matches the
   108   *         given predicate, otherwise an empty {@code Optional}
   109   * @throws NullPointerException if the predicate is {@code null}
   110   */
   111  func (o Optional) Filter(predicate predicate.Predicater) Optional {
   112  	object.RequireNonNull(predicate)
   113  	if !o.IsPresent() {
   114  		return o
   115  	}
   116  	if predicate.Test(o.value) {
   117  		return o
   118  	}
   119  	return Empty()
   120  }
   121  
   122  /**
   123   * If a value is present, returns an {@code Optional} describing (as if by
   124   * {@link #ofNullable}) the result of applying the given mapping function to
   125   * the value, otherwise returns an empty {@code Optional}.
   126   *
   127   * <p>If the mapping function returns a {@code null} result then this method
   128   * returns an empty {@code Optional}.
   129   *
   130   * @apiNote
   131   * This method supports post-processing on {@code Optional} values, without
   132   * the need to explicitly check for a return status.  For example, the
   133   * following code traverses a stream of URIs, selects one that has not
   134   * yet been processed, and creates a path from that URI, returning
   135   * an {@code Optional<Path>}:
   136   *
   137   * <pre>{@code
   138   *     Optional<Path> p =
   139   *         uris.stream().filter(uri -> !isProcessedYet(uri))
   140   *                       .findFirst()
   141   *                       .map(Paths::get);
   142   * }</pre>
   143   *
   144   * Here, {@code findFirst} returns an {@code Optional<URI>}, and then
   145   * {@code map} returns an {@code Optional<Path>} for the desired
   146   * URI if one exists.
   147   *
   148   * @param mapper the mapping function to apply to a value, if present
   149   * @param <U> The type of the value returned from the mapping function
   150   * @return an {@code Optional} describing the result of applying a mapping
   151   *         function to the value of this {@code Optional}, if a value is
   152   *         present, otherwise an empty {@code Optional}
   153   * @throws NullPointerException if the mapping function is {@code null}
   154   */
   155  func (o Optional) Map(mapper func(interface{}) interface{}) Optional {
   156  	object.RequireNonNil(mapper)
   157  	if !o.IsPresent() {
   158  		return Empty()
   159  	}
   160  
   161  	return OfNillable(mapper(o.value))
   162  }
   163  
   164  /**
   165   * If a value is present, returns the result of applying the given
   166   * {@code Optional}-bearing mapping function to the value, otherwise returns
   167   * an empty {@code Optional}.
   168   *
   169   * <p>This method is similar to {@link #map(Function)}, but the mapping
   170   * function is one whose result is already an {@code Optional}, and if
   171   * invoked, {@code flatMap} does not wrap it within an additional
   172   * {@code Optional}.
   173   *
   174   * @param <U> The type of value of the {@code Optional} returned by the
   175   *            mapping function
   176   * @param mapper the mapping function to apply to a value, if present
   177   * @return the result of applying an {@code Optional}-bearing mapping
   178   *         function to the value of this {@code Optional}, if a value is
   179   *         present, otherwise an empty {@code Optional}
   180   * @throws NullPointerException if the mapping function is {@code null} or
   181   *         returns a {@code null} result
   182   */
   183  func (o *Optional) FlatMap(mapper func(interface{}) interface{}) Optional {
   184  	object.RequireNonNil(mapper)
   185  	if !o.IsPresent() {
   186  		return Empty()
   187  	}
   188  
   189  	return OfNillable(mapper(o.value))
   190  }