1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.opencastproject.assetmanager.api;
22
23 import static java.lang.String.format;
24
25 import org.opencastproject.assetmanager.api.fn.Product;
26
27 import java.util.Date;
28 import java.util.Objects;
29 import java.util.function.Function;
30
31 import javax.annotation.Nonnull;
32 import javax.annotation.ParametersAreNonnullByDefault;
33 import javax.annotation.concurrent.Immutable;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 @ParametersAreNonnullByDefault
57 public abstract class Value {
58 public static final StringType STRING = new StringType();
59 public static final DateType DATE = new DateType();
60 public static final LongType LONG = new LongType();
61 public static final BooleanType BOOLEAN = new BooleanType();
62 public static final VersionType VERSION = new VersionType();
63
64 public static final UntypedType UNTYPED = new UntypedType();
65
66
67 private Value() {
68 }
69
70
71 public abstract Object get();
72
73
74
75
76
77
78
79
80
81
82
83
84
85 public final <A> A get(ValueType<A> ev) {
86 if (getType().getClass().equals(ev.getClass())) {
87 return (A) get();
88 } else {
89 throw new RuntimeException(this + " is not a " + ev.getClass().getSimpleName());
90 }
91 }
92
93 public final ValueType<?> getType() {
94 return decompose(new Function<String, ValueType<?>>() {
95 @Override public ValueType<?> apply(String a) {
96 return STRING;
97 }
98 }, new Function<Date, ValueType<?>>() {
99 @Override public ValueType<?> apply(Date a) {
100 return DATE;
101 }
102 }, new Function<Long, ValueType<?>>() {
103 @Override public ValueType<?> apply(Long a) {
104 return LONG;
105 }
106 }, new Function<Boolean, ValueType<?>>() {
107 @Override public ValueType<?> apply(Boolean a) {
108 return BOOLEAN;
109 }
110 }, new Function<Version, ValueType<?>>() {
111 @Override public ValueType<?> apply(Version a) {
112 return VERSION;
113 }
114 });
115 }
116
117
118
119
120
121 public final <A> A decompose(
122 Function<? super String, ? extends A> stringValue,
123 Function<? super Date, ? extends A> dateValue,
124 Function<? super Long, ? extends A> longValue,
125 Function<? super Boolean, ? extends A> booleanValue,
126 Function<? super Version, ? extends A> versionValue
127 ) {
128 if (this instanceof StringValue) {
129 return stringValue.apply(((StringValue) this).get());
130 } else if (this instanceof DateValue) {
131 return dateValue.apply(((DateValue) this).get());
132 } else if (this instanceof LongValue) {
133 return longValue.apply(((LongValue) this).get());
134 } else if (this instanceof BooleanValue) {
135 return booleanValue.apply(((BooleanValue) this).get());
136 } else if (this instanceof VersionValue) {
137 return versionValue.apply(((VersionValue) this).get());
138 } else {
139
140 throw new Error("Unexhaustive match: " + this);
141 }
142 }
143
144
145
146
147
148
149
150
151
152 public static <B> Function<Object, B> doNotMatch() {
153 return new Function<Object, B>() {
154 @Override public B apply(Object a) {
155 throw new Error("Unexhaustive match: " + a);
156 }
157 };
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176 public abstract static class ValueType<A> {
177
178 private ValueType() {
179 }
180
181 public abstract TypedValue<A> mk(A a);
182
183 public abstract <B> B match(
184 Product<? extends B> stringType,
185 Product<? extends B> dateType,
186 Product<? extends B> longType,
187 Product<? extends B> booleanType,
188 Product<? extends B> versionType);
189 }
190
191 public static final class StringType extends ValueType<String> {
192 @Override public TypedValue<String> mk(String a) {
193 return Value.mk(a);
194 }
195
196 @Override public <B> B match(
197 Product<? extends B> stringType,
198 Product<? extends B> dateType,
199 Product<? extends B> longType,
200 Product<? extends B> booleanType,
201 Product<? extends B> versionType) {
202 return stringType.get1();
203 }
204 }
205
206 public static final class DateType extends ValueType<Date> {
207 @Override public TypedValue<Date> mk(Date a) {
208 return Value.mk(a);
209 }
210
211 @Override public <B> B match(
212 Product<? extends B> stringType,
213 Product<? extends B> dateType,
214 Product<? extends B> longType,
215 Product<? extends B> booleanType,
216 Product<? extends B> versionType) {
217 return dateType.get1();
218 }
219 }
220
221 public static final class LongType extends ValueType<Long> {
222 @Override public TypedValue<Long> mk(Long a) {
223 return Value.mk(a);
224 }
225
226 @Override public <B> B match(
227 Product<? extends B> stringType,
228 Product<? extends B> dateType,
229 Product<? extends B> longType,
230 Product<? extends B> booleanType,
231 Product<? extends B> versionType) {
232 return longType.get1();
233 }
234 }
235
236 public static final class BooleanType extends ValueType<Boolean> {
237 @Override public TypedValue<Boolean> mk(Boolean a) {
238 return Value.mk(a);
239 }
240
241 @Override public <B> B match(
242 Product<? extends B> stringType,
243 Product<? extends B> dateType,
244 Product<? extends B> longType,
245 Product<? extends B> booleanType,
246 Product<? extends B> versionType) {
247 return booleanType.get1();
248 }
249 }
250
251 public static final class VersionType extends ValueType<Version> {
252 @Override public TypedValue<Version> mk(Version a) {
253 return Value.mk(a);
254 }
255
256 @Override public <B> B match(
257 Product<? extends B> stringType,
258 Product<? extends B> dateType,
259 Product<? extends B> longType,
260 Product<? extends B> booleanType,
261 Product<? extends B> versionType) {
262 return versionType.get1();
263 }
264 }
265
266 public static final class UntypedType extends ValueType<Object> {
267 @Override public TypedValue<Object> mk(Object a) {
268 throw new RuntimeException("Cannot create an untyped value");
269 }
270
271 @Override public <B> B match(
272 Product<? extends B> stringType,
273 Product<? extends B> dateType,
274 Product<? extends B> longType,
275 Product<? extends B> booleanType,
276 Product<? extends B> versionType) {
277 throw new RuntimeException("Cannot match an untyped value type");
278 }
279 }
280
281
282
283
284
285
286
287
288
289 public static class TypedValue<A> extends Value {
290 private final A value;
291
292
293 private TypedValue(@Nonnull A value) {
294 this.value = value;
295 }
296
297 @Override public A get() {
298 return value;
299 }
300
301 @Override public int hashCode() {
302 return Objects.hash(value);
303 }
304
305
306
307 @Override public boolean equals(Object that) {
308 return (this == that) || (that instanceof TypedValue && eqFields((TypedValue) that));
309 }
310
311 private boolean eqFields(TypedValue that) {
312 return Objects.equals(value, that.value);
313 }
314
315 @Override public String toString() {
316 return format("%s(%s)", getClass().getSimpleName(), value);
317 }
318 }
319
320
321
322
323
324 @Immutable
325 public static final class StringValue extends TypedValue<String> {
326 public StringValue(@Nonnull String value) {
327 super(value);
328 }
329 }
330
331
332
333
334 public static final class DateValue extends TypedValue<Date> {
335 public DateValue(@Nonnull Date value) {
336 super(value);
337 }
338 }
339
340
341
342
343 @Immutable
344 public static final class LongValue extends TypedValue<Long> {
345 public LongValue(@Nonnull Long value) {
346 super(value);
347 }
348 }
349
350
351
352
353 @Immutable
354 public static final class BooleanValue extends TypedValue<Boolean> {
355 public BooleanValue(@Nonnull Boolean value) {
356 super(value);
357 }
358 }
359
360
361
362
363 @Immutable
364 public static final class VersionValue extends TypedValue<Version> {
365 public VersionValue(@Nonnull Version value) {
366 super(value);
367 }
368 }
369
370
371
372
373
374
375
376
377 public static StringValue mk(String value) {
378 return new StringValue(value);
379 }
380
381
382 public static DateValue mk(Date value) {
383 return new DateValue(value);
384 }
385
386
387 public static LongValue mk(Long value) {
388 return new LongValue(value);
389 }
390
391
392 public static BooleanValue mk(Boolean value) {
393 return new BooleanValue(value);
394 }
395
396
397 public static VersionValue mk(Version value) {
398 return new VersionValue(value);
399 }
400
401
402 public static <A> TypedValue<A> mk(ValueType<A> mk, A a) {
403 return mk.mk(a);
404 }
405 }