11package io .split .openfeature ;
22
3- import dev .openfeature .javasdk .ErrorCode ;
4- import dev .openfeature .javasdk .EvaluationContext ;
5- import dev .openfeature .javasdk .FeatureProvider ;
6- import dev .openfeature .javasdk .Metadata ;
7- import dev .openfeature .javasdk .ProviderEvaluation ;
8- import dev .openfeature .javasdk .Reason ;
9- import dev .openfeature .javasdk .Structure ;
10- import dev .openfeature .javasdk .Value ;
11- import dev .openfeature .javasdk .exceptions .GeneralError ;
12- import dev .openfeature .javasdk .exceptions .OpenFeatureError ;
13- import dev .openfeature .javasdk .exceptions .ParseError ;
3+ import dev .openfeature .sdk .ErrorCode ;
4+ import dev .openfeature .sdk .EvaluationContext ;
5+ import dev .openfeature .sdk .FeatureProvider ;
6+ import dev .openfeature .sdk .Metadata ;
7+ import dev .openfeature .sdk .MutableStructure ;
8+ import dev .openfeature .sdk .ProviderEvaluation ;
9+ import dev .openfeature .sdk .Reason ;
10+ import dev .openfeature .sdk .Value ;
11+ import dev .openfeature .sdk .exceptions .GeneralError ;
12+ import dev .openfeature .sdk .exceptions .OpenFeatureError ;
13+ import dev .openfeature .sdk .exceptions .ParseError ;
14+ import dev .openfeature .sdk .exceptions .TargetingKeyMissingError ;
1415import io .split .client .SplitClient ;
1516import io .split .openfeature .utils .Serialization ;
16-
17- import java .time .ZonedDateTime ;
17+ import java .time .Instant ;
1818import java .time .format .DateTimeParseException ;
1919import java .util .List ;
2020import java .util .Map ;
@@ -48,7 +48,7 @@ public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defa
4848 try {
4949 String evaluated = evaluateTreatment (key , evaluationContext );
5050 if (noTreatment (evaluated )) {
51- return constructProviderEvaluation (defaultTreatment , evaluated , Reason .DEFAULT , ErrorCode .FLAG_NOT_FOUND . name () );
51+ return constructProviderEvaluation (defaultTreatment , evaluated , Reason .DEFAULT , ErrorCode .FLAG_NOT_FOUND );
5252 }
5353 // if treatment is "on" or "true" we treat that as true
5454 // if it is "off" or "false" we treat it as false
@@ -59,7 +59,7 @@ public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defa
5959 } else if (evaluated .equalsIgnoreCase ("false" ) || evaluated .equals ("off" )) {
6060 value = false ;
6161 } else {
62- throw new ParseError (ErrorCode . PARSE_ERROR . name () );
62+ throw new ParseError ();
6363 }
6464 return constructProviderEvaluation (value , evaluated );
6565 } catch (OpenFeatureError e ) {
@@ -75,7 +75,7 @@ public ProviderEvaluation<String> getStringEvaluation(String key, String default
7575 try {
7676 String evaluated = evaluateTreatment (key , evaluationContext );
7777 if (noTreatment (evaluated )) {
78- return constructProviderEvaluation (defaultTreatment , evaluated , Reason .DEFAULT , ErrorCode .FLAG_NOT_FOUND . name () );
78+ return constructProviderEvaluation (defaultTreatment , evaluated , Reason .DEFAULT , ErrorCode .FLAG_NOT_FOUND );
7979 }
8080 return constructProviderEvaluation (evaluated , evaluated );
8181 } catch (OpenFeatureError e ) {
@@ -90,14 +90,14 @@ public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defa
9090 try {
9191 String evaluated = evaluateTreatment (key , evaluationContext );
9292 if (noTreatment (evaluated )) {
93- return constructProviderEvaluation (defaultTreatment , evaluated , Reason .DEFAULT , ErrorCode .FLAG_NOT_FOUND . name () );
93+ return constructProviderEvaluation (defaultTreatment , evaluated , Reason .DEFAULT , ErrorCode .FLAG_NOT_FOUND );
9494 }
9595 Integer value = Integer .valueOf (evaluated );
9696 return constructProviderEvaluation (value , evaluated );
9797 } catch (OpenFeatureError e ) {
9898 throw e ;
9999 } catch (NumberFormatException e ) {
100- throw new ParseError (ErrorCode . PARSE_ERROR . name () );
100+ throw new ParseError ();
101101 } catch (Exception e ) {
102102 throw new GeneralError ("Error getting Integer evaluation" , e );
103103 }
@@ -108,29 +108,29 @@ public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double default
108108 try {
109109 String evaluated = evaluateTreatment (key , evaluationContext );
110110 if (noTreatment (evaluated )) {
111- return constructProviderEvaluation (defaultTreatment , evaluated , Reason .DEFAULT , ErrorCode .FLAG_NOT_FOUND . name () );
111+ return constructProviderEvaluation (defaultTreatment , evaluated , Reason .DEFAULT , ErrorCode .FLAG_NOT_FOUND );
112112 }
113113 Double value = Double .valueOf (evaluated );
114114 return constructProviderEvaluation (value , evaluated );
115115 } catch (OpenFeatureError e ) {
116116 throw e ;
117117 } catch (NumberFormatException e ) {
118- throw new ParseError (ErrorCode . PARSE_ERROR . name () );
118+ throw new ParseError ();
119119 } catch (Exception e ) {
120120 throw new GeneralError ("Error getting Double evaluation" , e );
121121 }
122122 }
123123
124124 @ Override
125- public ProviderEvaluation <Structure > getObjectEvaluation (String key , Structure defaultTreatment , EvaluationContext evaluationContext ) {
125+ public ProviderEvaluation <Value > getObjectEvaluation (String key , Value defaultTreatment , EvaluationContext evaluationContext ) {
126126 try {
127127 String evaluated = evaluateTreatment (key , evaluationContext );
128128 if (noTreatment (evaluated )) {
129- return constructProviderEvaluation (defaultTreatment , evaluated , Reason .DEFAULT , ErrorCode .FLAG_NOT_FOUND . name () );
129+ return constructProviderEvaluation (defaultTreatment , evaluated , Reason .DEFAULT , ErrorCode .FLAG_NOT_FOUND );
130130 }
131131 Map <String , Object > rawMap = Serialization .stringToMap (evaluated );
132- Structure structure = mapToStructure (rawMap );
133- return constructProviderEvaluation (structure , evaluated );
132+ Value value = mapToValue (rawMap );
133+ return constructProviderEvaluation (value , evaluated );
134134 } catch (OpenFeatureError e ) {
135135 throw e ;
136136 } catch (Exception e ) {
@@ -139,14 +139,14 @@ public ProviderEvaluation<Structure> getObjectEvaluation(String key, Structure d
139139 }
140140
141141 public Map <String , Object > transformContext (EvaluationContext context ) {
142- return getMapFromStructMap ( context .asMap () );
142+ return context .asObjectMap ( );
143143 }
144144
145145 private String evaluateTreatment (String key , EvaluationContext evaluationContext ) {
146146 String id = evaluationContext .getTargetingKey ();
147147 if (id == null || id .isEmpty ()) {
148148 // targeting key is always required
149- throw new GeneralError ( "TARGETING_KEY_MISSING" );
149+ throw new TargetingKeyMissingError ( );
150150 }
151151 Map <String , Object > attributes = transformContext (evaluationContext );
152152 return client .getTreatment (id , key , attributes );
@@ -160,87 +160,47 @@ private <T> ProviderEvaluation<T> constructProviderEvaluation(T value, String va
160160 return constructProviderEvaluation (value , variant , Reason .TARGETING_MATCH , null );
161161 }
162162
163- private <T > ProviderEvaluation <T > constructProviderEvaluation (T value , String variant , Reason reason , String errorCode ) {
163+ private <T > ProviderEvaluation <T > constructProviderEvaluation (T value , String variant , Reason reason , ErrorCode errorCode ) {
164164 ProviderEvaluation .ProviderEvaluationBuilder <T > builder = ProviderEvaluation .builder ();
165165 return builder
166166 .value (value )
167- .reason (reason )
167+ .reason (reason . name () )
168168 .variant (variant )
169169 .errorCode (errorCode )
170170 .build ();
171171 }
172172
173- private Map <String , Object > getMapFromStructMap (Map <String , Value > structMap ) {
174- return structMap .entrySet ().stream ().collect (Collectors .toMap (Map .Entry ::getKey , e -> getInnerValue (e .getValue ())));
175- }
176-
177- private Structure mapToStructure (Map <String , Object > map ) {
178- return new Structure (
179- map .entrySet ().stream ().collect (Collectors .toMap (Map .Entry ::getKey , e -> objectToValue (e .getValue ()))));
173+ /**
174+ * Turn map String->Object into a Value.
175+ * @param map a Map String->Object, where object is NOT Value or Structure
176+ * @return Value representing the map passed in
177+ */
178+ private Value mapToValue (Map <String , Object > map ) {
179+ return new Value (
180+ new MutableStructure (
181+ map .entrySet ().stream ().collect (Collectors .toMap (Map .Entry ::getKey , e -> objectToValue (e .getValue ())))));
180182 }
181183
182- private Object getInnerValue (Value value ) {
183- Object object = value .asBoolean ();
184- if (object != null ) {
185- return object ;
186- }
187- object = value .asDouble ();
188- if (object != null ) {
189- return object ;
190- }
191- object = value .asInteger ();
192- if (object != null ) {
193- return object ;
194- }
195- object = value .asString ();
196- if (object != null ) {
197- return object ;
198- }
199- object = value .asZonedDateTime ();
200- if (object != null ) {
201- return object ;
202- }
203- object = value .asStructure ();
204- if (object != null ) {
205- // must return a map
206- return getMapFromStructMap (((Structure ) object ).asMap ());
207- }
208- object = value .asList ();
209- if (object != null ) {
210- // must return a list of inner objects
211- List <Value > values = (List <Value >) object ;
212- return values .stream ().map (this ::getInnerValue ).collect (Collectors .toList ());
213- }
214- throw new ClassCastException ("Could not get inner value from Value object." );
215- }
216184
217185 private Value objectToValue (Object object ) {
218- if (object instanceof Value ) {
219- return (Value ) object ;
220- } else if (object instanceof String ) {
221- // try to parse to zoned date time, otherwise use as string
186+ if (object instanceof String ) {
187+ // try to parse as instant, otherwise use as string
222188 try {
223- return new Value (ZonedDateTime .parse ((String ) object ));
189+ return new Value (Instant .parse ((String ) object ));
224190 } catch (DateTimeParseException e ) {
225191 return new Value ((String ) object );
226192 }
227- } else if (object instanceof Boolean ) {
228- return new Value ((Boolean ) object );
229- } else if (object instanceof Integer ) {
230- return new Value ((Integer ) object );
231- } else if (object instanceof Double ) {
232- return new Value ((Double ) object );
233- } else if (object instanceof Structure ) {
234- return new Value ((Structure ) object );
235193 } else if (object instanceof List ) {
236194 // need to translate each elem in list to a value
237195 return new Value (((List <Object >) object ).stream ().map (this ::objectToValue ).collect (Collectors .toList ()));
238- } else if (object instanceof ZonedDateTime ) {
239- return new Value ((ZonedDateTime ) object );
240196 } else if (object instanceof Map ) {
241- return new Value ( mapToStructure (( Map <String , Object >) object ) );
197+ return mapToValue (( Map <String , Object >) object );
242198 } else {
243- throw new ClassCastException ("Could not cast Object to Value" );
199+ try {
200+ return new Value (object );
201+ } catch (InstantiationException e ) {
202+ throw new ClassCastException ("Could not cast Object to Value" );
203+ }
244204 }
245205 }
246206}
0 commit comments