4
4
5
5
import cloud .eppo .ufc .dto .*;
6
6
import cloud .eppo .ufc .dto .adapters .EppoModule ;
7
+ import com .fasterxml .jackson .databind .JsonNode ;
7
8
import com .fasterxml .jackson .databind .ObjectMapper ;
8
- import java .io .IOException ;
9
+ import com .fasterxml .jackson .databind .node .ObjectNode ;
10
+ import java .io .*;
9
11
import java .util .Collections ;
10
12
import java .util .Map ;
11
13
import java .util .Set ;
12
14
import java .util .stream .Collectors ;
15
+ import org .jetbrains .annotations .Nullable ;
13
16
import org .slf4j .Logger ;
14
17
import org .slf4j .LoggerFactory ;
15
18
46
49
* then check `requiresBanditModels()`.
47
50
*/
48
51
public class Configuration {
52
+ private static final ObjectMapper mapper =
53
+ new ObjectMapper ().registerModule (EppoModule .eppoModule ());
54
+
49
55
private static final Logger log = LoggerFactory .getLogger (Configuration .class );
50
56
private final Map <String , BanditReference > banditReferences ;
51
57
private final Map <String , FlagConfig > flags ;
@@ -68,6 +74,17 @@ private Configuration(
68
74
this .banditReferences = banditReferences ;
69
75
this .bandits = bandits ;
70
76
this .isConfigObfuscated = isConfigObfuscated ;
77
+
78
+ // Graft the `forServer` boolean into the flagConfigJson'
79
+ if (flagConfigJson != null && flagConfigJson .length != 0 ) {
80
+ try {
81
+ JsonNode jNode = mapper .readTree (flagConfigJson );
82
+ ((ObjectNode ) jNode ).put ("forServer" , !isConfigObfuscated );
83
+ flagConfigJson = mapper .writeValueAsBytes (jNode );
84
+ } catch (IOException e ) {
85
+ log .error ("Error adding `forServer` field to FlagConfigResponse JSON" );
86
+ }
87
+ }
71
88
this .flagConfigJson = flagConfigJson ;
72
89
this .banditParamsJson = banditParamsJson ;
73
90
}
@@ -123,6 +140,10 @@ public byte[] serializeBanditParamsToBytes() {
123
140
return banditParamsJson ;
124
141
}
125
142
143
+ public boolean isEmpty () {
144
+ return flags == null || flags .isEmpty ();
145
+ }
146
+
126
147
public static Builder builder (byte [] flagJson , boolean isConfigObfuscated ) {
127
148
return new Builder (flagJson , isConfigObfuscated );
128
149
}
@@ -132,44 +153,59 @@ public static Builder builder(byte[] flagJson, boolean isConfigObfuscated) {
132
153
* @see Configuration for usage.
133
154
*/
134
155
public static class Builder {
135
- private static final ObjectMapper mapper =
136
- new ObjectMapper ().registerModule (EppoModule .eppoModule ());
137
156
138
157
private final boolean isConfigObfuscated ;
139
158
private final Map <String , FlagConfig > flags ;
140
- private Map <String , BanditReference > banditReferences ;
159
+ private final Map <String , BanditReference > banditReferences ;
141
160
private Map <String , BanditParameters > bandits = Collections .emptyMap ();
142
161
private final byte [] flagJson ;
143
162
private byte [] banditParamsJson ;
144
163
145
- public Builder (String flagJson , boolean isConfigObfuscated ) {
146
- this (flagJson .getBytes (), isConfigObfuscated );
147
- }
148
-
149
- public Builder (byte [] flagJson , boolean isConfigObfuscated ) {
150
- this .isConfigObfuscated = isConfigObfuscated ;
151
-
164
+ private static FlagConfigResponse parseFlagResponse (byte [] flagJson ) {
152
165
if (flagJson == null || flagJson .length == 0 ) {
153
- throw new RuntimeException (
154
- "Null or empty configuration string. Call `Configuration.Empty()` instead" ) ;
166
+ log . warn ( "Null or empty configuration string. Call `Configuration.Empty()` instead" );
167
+ return null ;
155
168
}
156
-
157
- // Build the flags config from the json string.
158
169
FlagConfigResponse config ;
159
170
try {
160
- config = mapper .readValue (flagJson , FlagConfigResponse .class );
171
+ return mapper .readValue (flagJson , FlagConfigResponse .class );
161
172
} catch (IOException e ) {
162
173
throw new RuntimeException (e );
163
174
}
175
+ }
176
+
177
+ public Builder (String flagJson , boolean isConfigObfuscated ) {
178
+ this (flagJson .getBytes (), parseFlagResponse (flagJson .getBytes ()), isConfigObfuscated );
179
+ }
180
+
181
+ public Builder (byte [] flagJson , boolean isConfigObfuscated ) {
182
+ this (flagJson , parseFlagResponse (flagJson ), isConfigObfuscated );
183
+ }
184
+
185
+ public Builder (byte [] flagJson , FlagConfigResponse flagConfigResponse ) {
186
+ this (flagJson , flagConfigResponse , !flagConfigResponse .isForServer ());
187
+ }
164
188
165
- if (config == null || config .getFlags () == null ) {
189
+ /** Use this constructor when the FlagConfigResponse has the `forServer` field populated. */
190
+ public Builder (byte [] flagJson ) {
191
+ this (flagJson , parseFlagResponse (flagJson ));
192
+ }
193
+
194
+ public Builder (
195
+ byte [] flagJson ,
196
+ @ Nullable FlagConfigResponse flagConfigResponse ,
197
+ boolean isConfigObfuscated ) {
198
+ this .isConfigObfuscated = isConfigObfuscated ;
199
+ this .flagJson = flagJson ;
200
+ if (flagConfigResponse == null
201
+ || flagConfigResponse .getFlags () == null
202
+ || flagConfigResponse .getFlags ().isEmpty ()) {
166
203
log .warn ("'flags' map missing in flag definition JSON" );
167
204
flags = Collections .emptyMap ();
168
- this . flagJson = null ;
205
+ banditReferences = Collections . emptyMap () ;
169
206
} else {
170
- flags = Collections .unmodifiableMap (config .getFlags ());
171
- banditReferences = Collections .unmodifiableMap (config .getBanditReferences ());
172
- this .flagJson = flagJson ;
207
+ flags = Collections .unmodifiableMap (flagConfigResponse .getFlags ());
208
+ banditReferences = Collections .unmodifiableMap (flagConfigResponse .getBanditReferences ());
173
209
log .debug ("Loaded {} flag definitions from flag definition JSON" , flags .size ());
174
210
}
175
211
}
@@ -206,6 +242,10 @@ public Builder banditParameters(String banditParameterJson) {
206
242
}
207
243
208
244
public Builder banditParameters (byte [] banditParameterJson ) {
245
+ if (banditParameterJson == null || banditParameterJson .length == 0 ) {
246
+ log .debug ("Bandit parameters are null or empty" );
247
+ return this ;
248
+ }
209
249
BanditParametersResponse config ;
210
250
try {
211
251
config = mapper .readValue (banditParameterJson , BanditParametersResponse .class );
0 commit comments