PageRenderTime 25ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/pd4j/src/main/java/org/bitbucket/pd4j/util/Option.java

https://bitbucket.org/tpataky/pd4j
Java | 237 lines | 185 code | 52 blank | 0 comment | 16 complexity | 01e8e2bcf2ebc2bb5a1dc2f9b0ca3a48 MD5 | raw file
  1. package org.bitbucket.pd4j.util;
  2. import java.io.Serializable;
  3. import java.util.Iterator;
  4. import java.util.Optional;
  5. import java.util.function.Consumer;
  6. import java.util.function.Function;
  7. import java.util.function.Predicate;
  8. import java.util.function.Supplier;
  9. import java.util.stream.Stream;
  10. public abstract class Option<T> implements Iterable<T>, Serializable {
  11. private final static long serialVersionUID = -1L;
  12. private final static Nothing<?> NOTHING = new Nothing<>();
  13. private Option() {
  14. }
  15. @SuppressWarnings("unchecked")
  16. public static <T> Option<T> nothing() {
  17. return (Option<T>) NOTHING;
  18. }
  19. public static <T> Option<T> some(T t) {
  20. return new Some<>(t);
  21. }
  22. public static <T> Option<T> from(Optional<T> optional) {
  23. if (optional.isPresent()) {
  24. return some(optional.get());
  25. } else {
  26. return nothing();
  27. }
  28. }
  29. public abstract Optional<T> toOptional();
  30. public abstract T getOrElse(Supplier<T> fallBack);
  31. public abstract boolean isNothing();
  32. public abstract <R> R fold(Supplier<R> ifNothing, Function<T, R> ifSome);
  33. public abstract void fold(Runnable ifNothing, Consumer<T> ifSome);
  34. public abstract Option<T> filter(Predicate<T> p);
  35. public abstract <R> Option<R> map(Function<T, R> fn);
  36. public abstract <R> Option<R> flatMap(Function<T, Option<R>> fn);
  37. public abstract Option<T> orElse(Option<T> fallBack);
  38. public abstract Stream<T> stream();
  39. @SafeVarargs
  40. public final Option<T> orElse(Supplier<Option<T>>... fallBacks) {
  41. Option<T> underEvaluation = this;
  42. for (Supplier<Option<T>> s : fallBacks) {
  43. if (underEvaluation.isNothing()) {
  44. underEvaluation = s.get();
  45. } else {
  46. break;
  47. }
  48. }
  49. return underEvaluation;
  50. }
  51. public static class Some<T> extends Option<T> {
  52. private final static long serialVersionUID = -1L;
  53. public final T value;
  54. private Some(T value) {
  55. this.value = value;
  56. }
  57. @Override
  58. public Optional<T> toOptional() {
  59. return Optional.ofNullable(value);
  60. }
  61. @Override
  62. public T getOrElse(Supplier<T> fallBack) {
  63. return value;
  64. }
  65. @Override
  66. public <R> R fold(Supplier<R> ifNothing, Function<T, R> ifSome) {
  67. return ifSome.apply(value);
  68. }
  69. @Override
  70. public void fold(Runnable ifNothing, Consumer<T> ifSome) {
  71. ifSome.accept(value);
  72. }
  73. @Override
  74. public Option<T> filter(Predicate<T> p) {
  75. if (p.test(value)) {
  76. return this;
  77. } else {
  78. return nothing();
  79. }
  80. }
  81. @Override
  82. public <R> Option<R> map(Function<T, R> fn) {
  83. return some(fn.apply(value));
  84. }
  85. @Override
  86. public <R> Option<R> flatMap(Function<T, Option<R>> fn) {
  87. return fn.apply(value);
  88. }
  89. @Override
  90. public Option<T> orElse(Option<T> fallBack) {
  91. return this;
  92. }
  93. @Override
  94. public boolean isNothing() {
  95. return false;
  96. }
  97. @Override
  98. public Stream<T> stream() {
  99. return Stream.of(value);
  100. }
  101. @Override
  102. public Iterator<T> iterator() {
  103. return new Iterator<T>() {
  104. boolean consumed;
  105. @Override
  106. public boolean hasNext() {
  107. return !consumed;
  108. }
  109. @Override
  110. public T next() {
  111. consumed = true;
  112. return value;
  113. }
  114. };
  115. }
  116. @Override
  117. public boolean equals(Object obj) {
  118. if (obj == null) {
  119. return false;
  120. }
  121. if (!(obj instanceof Some)) {
  122. return false;
  123. }
  124. final Some<?> other = (Some<?>) obj;
  125. if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) {
  126. return false;
  127. }
  128. return true;
  129. }
  130. @Override
  131. public int hashCode() {
  132. int hash = 7;
  133. hash = 53 * hash + (this.value != null ? this.value.hashCode() : 0);
  134. return hash;
  135. }
  136. }
  137. public static class Nothing<T> extends Option<T> {
  138. private final static long serialVersionUID = -1L;
  139. private Nothing() { }
  140. @Override
  141. public Optional<T> toOptional() {
  142. return Optional.empty();
  143. }
  144. @Override
  145. public T getOrElse(Supplier<T> fallBack) {
  146. return fallBack.get();
  147. }
  148. @Override
  149. public <R> R fold(Supplier<R> ifNothing, Function<T, R> ifSome) {
  150. return ifNothing.get();
  151. }
  152. @Override
  153. public void fold(Runnable ifNothing, Consumer<T> ifSome) {
  154. ifNothing.run();
  155. }
  156. @Override
  157. public Option<T> filter(Predicate<T> p) {
  158. return nothing();
  159. }
  160. @Override
  161. public <R> Option<R> map(Function<T, R> fn) {
  162. return nothing();
  163. }
  164. @Override
  165. public <R> Option<R> flatMap(Function<T, Option<R>> fn) {
  166. return nothing();
  167. }
  168. @Override
  169. public Option<T> orElse(Option<T> fallBack) {
  170. return fallBack;
  171. }
  172. @Override
  173. public boolean isNothing() {
  174. return true;
  175. }
  176. @Override
  177. public Stream<T> stream() {
  178. return Stream.empty();
  179. }
  180. @Override
  181. public Iterator<T> iterator() {
  182. return EmptyIterator.instance();
  183. }
  184. }
  185. }