1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 package org.apache.thrift;
21 
22 import java.util.Optional;
23 
24 /** Implementation of the Option type pattern */
25 public abstract class Option<T> {
26 
27   @SuppressWarnings("rawtypes")
28   private static final Option NONE = new None();
29 
30   /**
31    * Whether the Option is defined or not
32    *
33    * @return true if the Option is defined (of type Some) false if the Option is not defined (of
34    *     type None)
35    */
isDefined()36   public abstract boolean isDefined();
37 
38   /**
39    * Get the value of the Option (if it is defined)
40    *
41    * @return the value
42    * @throws IllegalStateException if called on a None
43    */
get()44   public abstract T get();
45 
46   /**
47    * Get the contained value (if defined) or else return a default value
48    *
49    * @param other what to return if the value is not defined (a None)
50    * @return either the value, or other if the value is not defined
51    */
or(T other)52   public T or(T other) {
53     if (isDefined()) {
54       return get();
55     } else {
56       return other;
57     }
58   }
59 
60   /**
61    * Turn this Option into Java 8 Optional type
62    *
63    * @return Java 8+ Optional Type
64    */
toOptional()65   public Optional<T> toOptional() {
66     if (isDefined()) {
67       return Optional.of(get());
68     } else {
69       return Optional.empty();
70     }
71   }
72 
73   /** The None type, representing an absent value (instead of "null") */
74   public static class None<T> extends Option<T> {
isDefined()75     public boolean isDefined() {
76       return false;
77     }
78 
get()79     public T get() {
80       throw new IllegalStateException("Cannot call get() on None");
81     }
82 
toString()83     public String toString() {
84       return "None";
85     }
86   }
87 
88   /**
89    * The Some type, representing an existence of some value
90    *
91    * @param <T> The type of value
92    */
93   public static class Some<T> extends Option<T> {
94     private final T value;
95 
Some(T value)96     public Some(T value) {
97       this.value = value;
98     }
99 
isDefined()100     public boolean isDefined() {
101       return true;
102     }
103 
get()104     public T get() {
105       return value;
106     }
107 
toString()108     public String toString() {
109       return "Some(" + value + ")";
110     }
111   }
112 
113   /**
114    * Wraps value in an Option type, depending on whether or not value is null
115    *
116    * @param value the value to wrap in Option
117    * @param <T> the type of value
118    * @return Some(value) if value is not null, None if value is null
119    */
fromNullable(T value)120   public static <T> Option<T> fromNullable(T value) {
121     if (value != null) {
122       return some(value);
123     } else {
124       return none();
125     }
126   }
127 
128   /**
129    * Wrap value in a Some type (NB! value must not be null!)
130    *
131    * @param value the value to wrap.
132    * @param <T> the type of value
133    * @return a new Some(value)
134    */
some(T value)135   public static <T> Some<T> some(T value) {
136     return new Some<T>(value);
137   }
138 
139   @SuppressWarnings("unchecked")
none()140   public static <T> None<T> none() {
141     return (None<T>) NONE;
142   }
143 }
144