66import java .util .*;
77import java .util .stream .Collectors ;
88import java .util .stream .Stream ;
9+
10+ import io .getunleash .messaging .StrategyDefinition ;
11+ import io .getunleash .messaging .StrategyFeature ;
12+ import io .getunleash .messaging .StrategyParameter ;
13+ import io .getunleash .messaging .TakeStateResponse ;
914import org .slf4j .Logger ;
1015import org .slf4j .LoggerFactory ;
1116
1217class CustomStrategiesEvaluator {
18+
1319 private static final Logger log = LoggerFactory .getLogger (CustomStrategiesEvaluator .class );
1420 static final Map <String , Boolean > EMPTY_STRATEGY_RESULTS = new HashMap <>();
1521 private final Map <String , IStrategy > registeredStrategies ;
@@ -34,68 +40,75 @@ public CustomStrategiesEvaluator(
3440 this .fallbackStrategy = fallbackStrategy ;
3541 }
3642
37- public void loadStrategiesFor (String toggles ) {
43+ public void loadStrategiesFor (TakeStateResponse response ) {
3844 if (this .registeredStrategies .isEmpty () && this .fallbackStrategy == null ) {
3945 return ;
4046 }
4147
42- if (toggles == null || toggles . isEmpty () ) {
48+ if (response . featuresVector () == null || response . featuresLength () == 0 ) {
4349 return ;
4450 }
45-
46- try {
47- VersionedFeatures wrapper =
48- mapper .readValue (toggles , new TypeReference <VersionedFeatures >() {});
49- if (wrapper .features != null ) {
50- featureStrategies =
51- wrapper .features .stream ()
52- .collect (toMap (feature -> feature .name , this ::getFeatureStrategies ));
51+ Map <String , List <MappedStrategy >> featureStrategies = new HashMap <>();
52+ for (int i = 0 ; i < response .featuresLength (); i ++) {
53+ StrategyFeature feature = response .features (i );
54+ String featureName = feature .featureName ();
55+ if (feature .strategiesLength () == 0 ) {
56+ List <MappedStrategy > mappedStrategies = new ArrayList <>();
57+ for (int j = 0 ; j < feature .strategiesLength (); j ++) {
58+ var strategy = feature .strategies (j );
59+ if (builtinStrategies .contains (strategy .name ())) {
60+ continue ;
61+ }
62+ featureStrategies .put (featureName , getFeatureStrategies (feature ));
63+ }
5364 }
54- } catch (JsonProcessingException e ) {
55- log .warn (
56- "Error processing features. This means custom strategies will return false every time they're used" ,
57- e );
5865 }
66+ this .featureStrategies = featureStrategies ;
5967 }
6068
61- List <MappedStrategy > getFeatureStrategies (FeatureDefinition feature ) {
69+ List <MappedStrategy > getFeatureStrategies (StrategyFeature feature ) {
6270 List <MappedStrategy > mappedStrategies = new ArrayList <>();
6371 int index = 1 ;
64- for (StrategyDefinition strategyDefinition : feature .strategies ) {
65- if (builtinStrategies .contains (strategyDefinition .name )) {
66- continue ;
72+ if (feature .strategiesLength () > 0 ) {
73+ for (int i = 0 ; i < feature .strategiesLength (); i ++) {
74+ io .getunleash .messaging .StrategyDefinition strategy = feature .strategies (i );
75+ if (builtinStrategies .contains (strategy .name ())) {
76+ continue ;
77+ }
78+ IStrategy impl =
79+ Optional .ofNullable (registeredStrategies .get (strategy .name ()))
80+ .orElseGet (() -> alwaysFalseStrategy (strategy .name ()));
81+ StrategyDefinition def =
82+ new StrategyDefinition (strategy .name (), getStrategyParameters (strategy ));
83+ mappedStrategies .add (new MappedStrategy ("customStrategy" + (index ++), impl , def ));
6784 }
68- IStrategy impl =
69- Optional .ofNullable (registeredStrategies .get (strategyDefinition .name ))
70- .orElseGet (() -> alwaysFalseStrategy (strategyDefinition .name ));
71- mappedStrategies .add (
72- new MappedStrategy ("customStrategy" + (index ++), impl , strategyDefinition ));
73- }
74- if (fallbackStrategy != null ) {
75- mappedStrategies .add (
76- new MappedStrategy (
77- "customStrategy" + index ,
78- fallbackStrategy ,
79- new StrategyDefinition ("fallback" , Collections .emptyMap ())));
8085 }
8186 return mappedStrategies ;
8287 }
8388
89+ Map <String , String > getStrategyParameters (io .getunleash .messaging .StrategyDefinition strategy ) {
90+ Map <String , String > parameters = new HashMap <>();
91+ if (strategy .parametersLength () > 0 ) {
92+ for (int i = 0 ; i < strategy .parametersLength (); i ++) {
93+ StrategyParameter parameter = strategy .parameters (i );
94+ parameters .put (parameter .key (), parameter .value ());
95+ }
96+ }
97+ return parameters ;
98+ }
99+
84100 public Map <String , Boolean > eval (String name , Context context ) {
85101
86102 List <MappedStrategy > mappedStrategies = featureStrategies .get (name );
87103 if (mappedStrategies == null || mappedStrategies .isEmpty ()) {
88104 return Collections .emptyMap ();
89105 }
90106
91- Map <String , Boolean > results =
92- mappedStrategies .stream ()
93- .collect (
94- Collectors .toMap (
95- mappedStrategy -> mappedStrategy .resultName ,
96- mappedStrategy -> tryIsEnabled (context , mappedStrategy ).orElse (false )));
97-
98- return results ;
107+ return mappedStrategies .stream ()
108+ .collect (
109+ Collectors .toMap (
110+ mappedStrategy -> mappedStrategy .resultName ,
111+ mappedStrategy -> tryIsEnabled (context , mappedStrategy ).orElse (false )));
99112 }
100113
101114 private static Optional <Boolean > tryIsEnabled (Context context , MappedStrategy mappedStrategy ) {
@@ -109,36 +122,11 @@ private static Optional<Boolean> tryIsEnabled(Context context, MappedStrategy ma
109122 }
110123 }
111124
112- private static class VersionedFeatures {
113- private final List <FeatureDefinition > features ;
114-
115- @ JsonCreator
116- private VersionedFeatures (@ JsonProperty ("features" ) List <FeatureDefinition > features ) {
117- this .features = features ;
118- }
119- }
120-
121- static class FeatureDefinition {
122- private final String name ;
123- private final List <StrategyDefinition > strategies ;
124-
125- @ JsonCreator
126- FeatureDefinition (
127- @ JsonProperty ("name" ) String name ,
128- @ JsonProperty ("strategies" ) List <StrategyDefinition > strategies ) {
129- this .name = name ;
130- this .strategies = strategies ;
131- }
132- }
133-
134125 static class StrategyDefinition {
135126 private final String name ;
136127 private final Map <String , String > parameters ;
137128
138- @ JsonCreator
139- StrategyDefinition (
140- @ JsonProperty ("name" ) String name ,
141- @ JsonProperty ("parameters" ) Map <String , String > parameters ) {
129+ StrategyDefinition (String name , Map <String , String > parameters ) {
142130 this .name = name ;
143131 this .parameters = parameters ;
144132 }
0 commit comments