This repository has been archived by the owner on Mar 17, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Toggle.java
109 lines (99 loc) · 3.24 KB
/
Toggle.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package com.whiskerlabs.toggle;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Predicate;
/**
* A {@code Toggle} is a reusable, dynamically-configurable predicate
* (boolean-valued function).
*
* @param <T> The toggle input type. The toggle is applied to
* instances of type {@code T}.
*/
public abstract class Toggle<T> implements Predicate<T>, Cohortable<Toggle<T>> {
public static final String UNABLE_TO_LOOK_UP_KEY_PREFIX =
"Unable to look up toggle state for key ";
/**
* Returns a {@link Predicate} which returns {@code true} for all
* instances of type {@code T}.
*
* @param <T> The toggle input type. The toggle is applied to
* instances of type {@code T}.
* @return A {@code Toggle} whose {@code test} method always returns
* {@code true}.
*/
public static <T> Toggle<T> alwaysTrue() {
return new Toggle<T>() {
@Override
protected boolean test(T t, Optional<String> cohortOpt) {
return true;
}
};
}
/**
* Returns a {@link Predicate} which returns {@code false} for all
* instances of type {@code T}.
*
* @param <T> The toggle input type. The toggle is applied to
* instances of type {@code T}.
* @return A {@code Toggle} whose {@code test} method always returns
* {@code false}.
*/
public static <T> Toggle<T> alwaysFalse() {
return new Toggle<T>() {
@Override
protected boolean test(T t, Optional<String> cohortOpt) {
return false;
}
};
}
/**
* Returns a weighted pseudorandom boolean value.
*
* Results are weight towards true according to the {@code weight}
* parameter. Precisely, for a weight {@code w}, the probability
* that this method returns true is {@code w/10000}.
*
* @param weight An integer which weights the returned boolean
* towards true, up to 10,000.
* @return {@code true} with probability {@code w/10000} for a
* weight {@code w}. {@code false} otherwise.
*/
protected static boolean nextBoolean(int weight) {
return (weight == 0)
? false
: ThreadLocalRandom.current().nextInt(10000 / weight) == 0;
}
@Override
public Toggle<T> withCohort(String cohort) {
final Optional<String> cohortOpt = Optional.of(cohort);
final Toggle<T> outer = this;
return new Toggle<T>() {
@Override
public boolean test(T t) {
return outer.test(t, cohortOpt);
}
@Override
protected boolean test(T t, Optional<String> cohortOpt) {
return outer.test(t, cohortOpt);
}
};
}
@Override
public boolean test(T t) {
return test(t, Optional.empty());
}
/**
* Evaluates this predicate on the given argument.
*
* An optional cohort may be provided, in which case the toggle can
* be targeted by an applicable toggle filter.
*
* @param t The input of this toggle.
* @param cohortOpt An optional cohort string used to match this
* toggle with an applicable toggle filter.
* @return {@code true} with some probablility defined by the
* applicable toggle specification.
*/
protected abstract boolean test(T t, Optional<String> cohortOpt);
}