22
33import static dev .openfeature .contrib .providers .flagd .resolver .process .model .FeatureFlag .EMPTY_TARGETING_STRING ;
44
5+ import java .util .Map ;
6+ import java .util .function .Consumer ;
7+ import java .util .function .Supplier ;
8+
59import dev .openfeature .contrib .providers .flagd .FlagdOptions ;
610import dev .openfeature .contrib .providers .flagd .resolver .Resolver ;
711import dev .openfeature .contrib .providers .flagd .resolver .common .ConnectionEvent ;
@@ -37,8 +41,9 @@ public class InProcessResolver implements Resolver {
3741 private final Consumer <ConnectionEvent > onConnectionEvent ;
3842 private final Operator operator ;
3943 private final long deadline ;
40- private final ImmutableMetadata metadata ;
44+ private final ImmutableMetadata fallBackMetadata ;
4145 private final Supplier <Boolean > connectedSupplier ;
46+ private final String scope ;
4247
4348 /**
4449 * Resolves flag values using https://buf.build/open-feature/flagd/docs/main:flagd.sync.v1. Flags
@@ -48,20 +53,22 @@ public class InProcessResolver implements Resolver {
4853 * @param connectedSupplier lambda providing current connection status from caller
4954 * @param onConnectionEvent lambda which handles changes in the connection/stream
5055 */
51- public InProcessResolver (
52- FlagdOptions options ,
53- final Supplier <Boolean > connectedSupplier ,
54- Consumer <ConnectionEvent > onConnectionEvent ) {
56+ public InProcessResolver (FlagdOptions options , final Supplier <Boolean > connectedSupplier ,
57+ Consumer <ConnectionEvent > onConnectionEvent ) {
5558 this .flagStore = new FlagStore (getConnector (options ));
5659 this .deadline = options .getDeadline ();
5760 this .onConnectionEvent = onConnectionEvent ;
5861 this .operator = new Operator ();
5962 this .connectedSupplier = connectedSupplier ;
60- this .metadata = options .getSelector () == null
61- ? null
62- : ImmutableMetadata .builder ()
63- .addString ("scope" , options .getSelector ())
64- .build ();
63+ if (options .getSelector () == null ) {
64+ this .scope = null ;
65+ this .fallBackMetadata = null ;
66+ } else {
67+ this .scope = options .getSelector ();
68+ this .fallBackMetadata = ImmutableMetadata .builder ()
69+ .addString ("scope" , this .scope )
70+ .build ();
71+ }
6572 }
6673
6774 /** Initialize in-process resolver. */
@@ -109,8 +116,14 @@ public void shutdown() throws InterruptedException {
109116 onConnectionEvent .accept (new ConnectionEvent (false ));
110117 }
111118
112- /** Resolve a boolean flag. */
113- public ProviderEvaluation <Boolean > booleanEvaluation (String key , Boolean defaultValue , EvaluationContext ctx ) {
119+ /**
120+ * Resolve a boolean flag.
121+ */
122+ public ProviderEvaluation <Boolean > booleanEvaluation (
123+ String key ,
124+ Boolean defaultValue ,
125+ EvaluationContext ctx
126+ ) {
114127 return resolve (Boolean .class , key , ctx );
115128 }
116129
@@ -161,6 +174,7 @@ private <T> ProviderEvaluation<T> resolve(Class<T> type, String key, EvaluationC
161174 return ProviderEvaluation .<T >builder ()
162175 .errorMessage ("flag: " + key + " not found" )
163176 .errorCode (ErrorCode .FLAG_NOT_FOUND )
177+ .flagMetadata (fallBackMetadata )
164178 .build ();
165179 }
166180
@@ -169,6 +183,7 @@ private <T> ProviderEvaluation<T> resolve(Class<T> type, String key, EvaluationC
169183 return ProviderEvaluation .<T >builder ()
170184 .errorMessage ("flag: " + key + " is disabled" )
171185 .errorCode (ErrorCode .FLAG_NOT_FOUND )
186+ .flagMetadata (getFlagMetadata (flag ))
172187 .build ();
173188 }
174189
@@ -215,13 +230,51 @@ private <T> ProviderEvaluation<T> resolve(Class<T> type, String key, EvaluationC
215230 throw new TypeMismatchError (message );
216231 }
217232
218- final ProviderEvaluation . ProviderEvaluationBuilder < T > evaluationBuilder = ProviderEvaluation .<T >builder ()
233+ return ProviderEvaluation .<T >builder ()
219234 .value ((T ) value )
220235 .variant (resolvedVariant )
221- .reason (reason );
236+ .reason (reason )
237+ .flagMetadata (getFlagMetadata (flag ))
238+ .build ();
239+ }
240+
241+ private ImmutableMetadata getFlagMetadata (FeatureFlag flag ) {
242+ if (flag == null ) {
243+ return fallBackMetadata ;
244+ }
245+
246+ ImmutableMetadata .ImmutableMetadataBuilder metadataBuilder = ImmutableMetadata .builder ();
247+ if (scope != null ) {
248+ metadataBuilder .addString ("scope" , scope );
249+ }
250+
251+ for (Map .Entry <String , Object > entry : flag .getMetadata ().entrySet ()) {
252+ Object value = entry .getValue ();
253+ if (value instanceof Number ) {
254+ if (value instanceof Long ) {
255+ metadataBuilder .addLong (entry .getKey (), (Long ) value );
256+ continue ;
257+ } else if (value instanceof Double ) {
258+ metadataBuilder .addDouble (entry .getKey (), (Double ) value );
259+ continue ;
260+ } else if (value instanceof Integer ) {
261+ metadataBuilder .addInteger (entry .getKey (), (Integer ) value );
262+ continue ;
263+ } else if (value instanceof Float ) {
264+ metadataBuilder .addFloat (entry .getKey (), (Float ) value );
265+ continue ;
266+ }
267+ } else if (value instanceof Boolean ) {
268+ metadataBuilder .addBoolean (entry .getKey (), (Boolean ) value );
269+ continue ;
270+ } else if (value instanceof String ) {
271+ metadataBuilder .addString (entry .getKey (), (String ) value );
272+ continue ;
273+ }
274+ throw new IllegalArgumentException ("The type of the Metadata entry with key " + entry .getKey ()
275+ + " and value " + entry .getValue () + " is not supported" );
276+ }
222277
223- return this .metadata == null
224- ? evaluationBuilder .build ()
225- : evaluationBuilder .flagMetadata (this .metadata ).build ();
278+ return metadataBuilder .build ();
226279 }
227280}
0 commit comments