Skip to content

Commit 69f00a4

Browse files
committed
support setting Flag.featureId via metadata
1 parent 8389a90 commit 69f00a4

File tree

4 files changed

+127
-17
lines changed

4 files changed

+127
-17
lines changed

src/main/java/com/flagsmith/mappers/EngineMappers.java

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
import com.flagsmith.flagengine.EvaluationContext;
88
import com.flagsmith.flagengine.FeatureContext;
99
import com.flagsmith.flagengine.FeatureValue;
10+
import com.flagsmith.flagengine.FlagResult;
1011
import com.flagsmith.flagengine.IdentityContext;
1112
import com.flagsmith.flagengine.SegmentCondition;
1213
import com.flagsmith.flagengine.SegmentContext;
1314
import com.flagsmith.flagengine.SegmentRule;
1415
import com.flagsmith.flagengine.Segments;
1516
import com.flagsmith.flagengine.Traits;
1617
import com.flagsmith.flagengine.segments.constants.SegmentConditions;
18+
import com.flagsmith.models.FeatureMetadata;
19+
import com.flagsmith.models.Flag;
1720
import com.flagsmith.models.SegmentMetadata;
1821
import com.flagsmith.models.environments.EnvironmentModel;
1922
import com.flagsmith.models.features.FeatureModel;
@@ -37,6 +40,33 @@
3740
* <p>Utility class for mapping JSON data to flag engine context objects.
3841
*/
3942
public class EngineMappers {
43+
/**
44+
* Maps FlagResult to Flag.
45+
* Returns null if metadata is missing or invalid.
46+
*
47+
* @param flagResult the flag result
48+
* @return the mapped flag or null
49+
*/
50+
public static Flag mapFlagResultToFlag(
51+
FlagResult flagResult
52+
) {
53+
FeatureMetadata metadata;
54+
55+
metadata = MapperFactory.getMapper()
56+
.convertValue(flagResult.getMetadata(), FeatureMetadata.class);
57+
58+
if (metadata == null || metadata.getFlagsmithId() == null) {
59+
return null;
60+
}
61+
62+
Flag flag = new Flag();
63+
flag.setFeatureId(metadata.getFlagsmithId());
64+
flag.setFeatureName(flagResult.getName());
65+
flag.setValue(flagResult.getValue());
66+
flag.setEnabled(flagResult.getEnabled());
67+
return flag;
68+
}
69+
4070
/**
4171
* Maps context and identity data to evaluation context.
4272
*
@@ -178,7 +208,8 @@ private static Map<String, SegmentContext> mapIdentityOverridesToSegments(
178208
.withName(feature.getName())
179209
.withEnabled(featureState.getEnabled())
180210
.withValue(featureState.getValue())
181-
.withPriority(EngineConstants.STRONGEST_PRIORITY);
211+
.withPriority(EngineConstants.STRONGEST_PRIORITY)
212+
.withMetadata(mapFeatureStateToFeatureMetadata(featureState));
182213
overridesKey.add(featureContext);
183214
}
184215

@@ -332,7 +363,8 @@ private static FeatureContext mapFeatureStateToFeatureContext(FeatureStateModel
332363
.withFeatureKey(String.valueOf(featureState.getFeature().getId()))
333364
.withName(featureState.getFeature().getName())
334365
.withEnabled(featureState.getEnabled())
335-
.withValue(featureState.getValue());
366+
.withValue(featureState.getValue())
367+
.withMetadata(mapFeatureStateToFeatureMetadata(featureState));
336368

337369
// Handle multivariate feature state values
338370
List<FeatureValue> variants = new ArrayList<>();
@@ -358,6 +390,15 @@ private static FeatureContext mapFeatureStateToFeatureContext(FeatureStateModel
358390
return featureContext;
359391
}
360392

393+
private static Map<String, Object> mapFeatureStateToFeatureMetadata(
394+
FeatureStateModel featureState) {
395+
FeatureMetadata metadata = new FeatureMetadata();
396+
metadata.setFlagsmithId(featureState.getFeature().getId());
397+
return MapperFactory.getMapper().convertValue(metadata,
398+
new com.fasterxml.jackson.core.type.TypeReference<Map<String, Object>>() {
399+
});
400+
}
401+
361402
/**
362403
* Maps a segment to segment context.
363404
*
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.flagsmith.models;
2+
3+
/**
4+
* FeatureMetadata
5+
*
6+
* <p>Additional metadata associated with a feature.
7+
*
8+
*/
9+
public class FeatureMetadata {
10+
private Integer flagsmithId;
11+
12+
/*
13+
* FlagsmithId
14+
* <p>The internal Flagsmith ID for the feature.
15+
*
16+
* @return The flagsmithId
17+
*/
18+
public Integer getFlagsmithId() {
19+
return flagsmithId;
20+
}
21+
22+
/*
23+
* FlagsmithId
24+
* <p>The internal Flagsmith ID for the segment.
25+
*
26+
* @param flagsmithId The flagsmithId
27+
*/
28+
public void setFlagsmithId(Integer flagsmithId) {
29+
this.flagsmithId = flagsmithId;
30+
}
31+
}

src/main/java/com/flagsmith/models/Flags.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.flagsmith.flagengine.EvaluationResult;
88
import com.flagsmith.flagengine.FlagResult;
99
import com.flagsmith.interfaces.DefaultFlagHandler;
10+
import com.flagsmith.mappers.EngineMappers;
1011
import com.flagsmith.models.features.FeatureStateModel;
1112
import com.flagsmith.threads.AnalyticsProcessor;
1213
import java.util.HashMap;
@@ -127,21 +128,14 @@ public static Flags fromEvaluationResult(
127128
EvaluationResult evaluationResult,
128129
AnalyticsProcessor analyticsProcessor,
129130
DefaultFlagHandler defaultFlagHandler) {
130-
Map<String, BaseFlag> flagMap = evaluationResult.getFlags().getAdditionalProperties()
131-
.entrySet()
132-
.stream()
133-
.collect(
134-
Collectors.toMap(
135-
Entry::getKey,
136-
entry -> {
137-
FlagResult flagResult = entry.getValue();
138-
Flag flag = new Flag();
139-
flag.setFeatureName(flagResult.getName());
140-
flag.setValue(flagResult.getValue());
141-
flag.setEnabled(flagResult.getEnabled());
142-
return flag;
143-
}));
144-
131+
Map<String, BaseFlag> flagMap = new HashMap<>();
132+
evaluationResult.getFlags().getAdditionalProperties().forEach((featureName, flagResult) -> {
133+
Flag flag = EngineMappers.mapFlagResultToFlag(flagResult);
134+
if (flag != null) {
135+
flagMap.put(featureName, flag);
136+
}
137+
});
138+
145139
Flags flags = new Flags();
146140
flags.setFlags(flagMap);
147141
flags.setAnalyticsProcessor(analyticsProcessor);
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.flagsmith.flagengine.models;
2+
3+
import com.flagsmith.exceptions.FlagsmithClientError;
4+
import com.flagsmith.flagengine.EvaluationResult;
5+
import com.flagsmith.models.Flags;
6+
import com.flagsmith.models.Flag;
7+
import com.flagsmith.flagengine.FlagResult;
8+
import org.junit.Test;
9+
10+
import static org.junit.Assert.assertEquals;
11+
12+
import java.util.Map;
13+
14+
public class FlagsTest {
15+
@Test
16+
public void testFromEvaluationResult__metadata__expected() throws FlagsmithClientError {
17+
com.flagsmith.flagengine.Flags flagResults = new com.flagsmith.flagengine.Flags()
18+
.withAdditionalProperty("feature_1", new FlagResult()
19+
.withEnabled(true)
20+
.withFeatureKey("feature_1")
21+
.withName("Feature 1")
22+
.withValue("value_1")
23+
.withReason("DEFAULT")
24+
.withMetadata(Map.of("flagsmithId", 1)))
25+
.withAdditionalProperty("feature_2", new FlagResult()
26+
.withEnabled(false)
27+
.withFeatureKey("feature_2")
28+
.withName("Feature 2")
29+
.withValue(null)
30+
.withReason("DEFAULT")
31+
);
32+
EvaluationResult evaluationResult = new EvaluationResult()
33+
.withFlags(flagResults);
34+
35+
Flags flags = Flags.fromEvaluationResult(evaluationResult, null, null);
36+
Flag flag = (Flag) flags.getFlag("feature_1");
37+
38+
assertEquals(1, flags.getFlags().size());
39+
assertEquals(true, flag.getEnabled());
40+
assertEquals("value_1", flag.getValue());
41+
assertEquals("Feature 1", flag.getFeatureName());
42+
assertEquals(1, flag.getFeatureId().intValue());
43+
}
44+
}

0 commit comments

Comments
 (0)