16
16
17
17
package com .palantir .conjure .java .types ;
18
18
19
+ import com .google .common .collect .ImmutableTable ;
20
+ import com .google .common .collect .Table ;
19
21
import com .palantir .conjure .java .util .TypeFunctions ;
20
22
import com .palantir .conjure .spec .AliasDefinition ;
21
23
import com .palantir .conjure .spec .ArgumentDefinition ;
37
39
import com .palantir .conjure .spec .UnionDefinition ;
38
40
import com .palantir .logsafe .Preconditions ;
39
41
import java .util .HashSet ;
42
+ import java .util .List ;
40
43
import java .util .Map ;
41
44
import java .util .Optional ;
42
45
import java .util .Set ;
43
46
import java .util .function .Supplier ;
47
+ import java .util .stream .Stream ;
44
48
45
49
public final class SafetyEvaluator {
50
+
51
+ // Make a constant to avoid allocating a new Optional every time we process a type definition for safety
52
+ private static final Optional <LogSafety > OPTIONAL_OF_SAFE = Optional .of (LogSafety .SAFE );
53
+
46
54
/**
47
55
* Enums contain an unknown variant, however we assume that the unknown variant is only used
48
56
* for past and future values which are known at compile-time in that version.
49
57
*/
50
- public static final Optional <LogSafety > ENUM_SAFETY = Optional . of ( LogSafety . SAFE ) ;
58
+ public static final Optional <LogSafety > ENUM_SAFETY = OPTIONAL_OF_SAFE ;
51
59
/**
52
60
* Unknown variant should be considered unsafe because we don't know what kind of data it may contain,
53
61
* however this makes rollout much more challenging, so we will ratchet unknown safety once we have
@@ -137,7 +145,7 @@ public Optional<LogSafety> visitEnum(EnumDefinition _value) {
137
145
@ Override
138
146
public Optional <LogSafety > visitObject (ObjectDefinition value ) {
139
147
return with (value .getTypeName (), () -> {
140
- Optional <LogSafety > safety = Optional . of ( LogSafety . SAFE ) ;
148
+ Optional <LogSafety > safety = OPTIONAL_OF_SAFE ;
141
149
for (FieldDefinition field : value .getFields ()) {
142
150
safety = combine (safety , getSafety (field .getType (), field .getSafety ()));
143
151
}
@@ -164,7 +172,7 @@ public Optional<LogSafety> visitUnknown(String unknownType) {
164
172
private Optional <LogSafety > with (TypeName typeName , Supplier <Optional <LogSafety >> task ) {
165
173
if (!inProgress .add (typeName )) {
166
174
// Given recursive evaluation, we return the least restrictive type: SAFE.
167
- return Optional . of ( LogSafety . SAFE ) ;
175
+ return OPTIONAL_OF_SAFE ;
168
176
}
169
177
Optional <LogSafety > result = task .get ();
170
178
if (!inProgress .remove (typeName )) {
@@ -298,7 +306,25 @@ public Optional<LogSafety> visitUnknown(String unknownValue) {
298
306
}
299
307
}
300
308
301
- public static Optional <LogSafety > combine (Optional <LogSafety > one , Optional <LogSafety > two ) {
309
+ private static final Table <Optional <LogSafety >, Optional <LogSafety >, Optional <LogSafety >> COMBINE_TABLE =
310
+ computeCombineTable ();
311
+
312
+ private static Table <Optional <LogSafety >, Optional <LogSafety >, Optional <LogSafety >> computeCombineTable () {
313
+ List <Optional <LogSafety >> allValues = Stream .concat (
314
+ Stream .of (Optional .<LogSafety >empty ()),
315
+ LogSafety .values ().stream ().map (Optional ::of ))
316
+ .toList ();
317
+ ImmutableTable .Builder <Optional <LogSafety >, Optional <LogSafety >, Optional <LogSafety >> builder =
318
+ ImmutableTable .builder ();
319
+ for (Optional <LogSafety > left : allValues ) {
320
+ for (Optional <LogSafety > right : allValues ) {
321
+ builder .put (left , right , computeCombine (left , right ));
322
+ }
323
+ }
324
+ return builder .buildOrThrow ();
325
+ }
326
+
327
+ private static Optional <LogSafety > computeCombine (Optional <LogSafety > one , Optional <LogSafety > two ) {
302
328
if (one .isPresent () && two .isPresent ()) {
303
329
return Optional .of (combine (one .get (), two .get ()));
304
330
}
@@ -307,7 +333,7 @@ public static Optional<LogSafety> combine(Optional<LogSafety> one, Optional<LogS
307
333
.filter (value -> !LogSafety .SAFE .equals (value ));
308
334
}
309
335
310
- public static LogSafety combine (LogSafety one , LogSafety two ) {
336
+ private static LogSafety combine (LogSafety one , LogSafety two ) {
311
337
LogSafety .Value first = one .get ();
312
338
LogSafety .Value second = two .get ();
313
339
if (first == LogSafety .Value .UNKNOWN || second == LogSafety .Value .UNKNOWN ) {
@@ -322,6 +348,10 @@ public static LogSafety combine(LogSafety one, LogSafety two) {
322
348
return one ;
323
349
}
324
350
351
+ public static Optional <LogSafety > combine (Optional <LogSafety > one , Optional <LogSafety > two ) {
352
+ return Preconditions .checkNotNull (COMBINE_TABLE .get (one , two ), "Missing an entry in the combine table" );
353
+ }
354
+
325
355
public static boolean allows (Optional <LogSafety > required , Optional <LogSafety > given ) {
326
356
if (required .isEmpty () || given .isEmpty ()) {
327
357
// If there is no requirement, all inputs are allowed.
0 commit comments