Skip to content

Commit 3819cd9

Browse files
committed
Support segment metadata
1 parent 0e827fc commit 3819cd9

File tree

5 files changed

+151
-7
lines changed

5 files changed

+151
-7
lines changed

src/main/java/com/flagsmith/FlagsmithClient.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.flagsmith;
22

3+
import com.fasterxml.jackson.databind.ObjectMapper;
34
import com.flagsmith.config.FlagsmithCacheConfig;
45
import com.flagsmith.config.FlagsmithConfig;
56
import com.flagsmith.exceptions.FlagsmithApiError;
@@ -14,11 +15,13 @@
1415
import com.flagsmith.models.BaseFlag;
1516
import com.flagsmith.models.Flags;
1617
import com.flagsmith.models.Segment;
18+
import com.flagsmith.models.SegmentMetadata;
1719
import com.flagsmith.threads.PollingManager;
1820
import com.flagsmith.utils.ModelUtils;
1921
import java.util.HashMap;
2022
import java.util.List;
2123
import java.util.Map;
24+
import java.util.Objects;
2225
import java.util.function.Function;
2326
import java.util.stream.Collectors;
2427
import lombok.Data;
@@ -171,12 +174,26 @@ public List<Segment> getIdentitySegments(String identifier, Map<String, Object>
171174
final EvaluationResult result = Engine.getEvaluationResult(context);
172175

173176
return result.getSegments().stream().map((segmentModel) -> {
177+
if (segmentModel.getMetadata() == null) {
178+
return null;
179+
}
180+
181+
ObjectMapper mapper = MapperFactory.getMapper();
182+
SegmentMetadata segmentMetadata = mapper.convertValue(
183+
segmentModel.getMetadata(), SegmentMetadata.class);
184+
185+
Integer flagsmithId = segmentMetadata.getFlagsmithId();
186+
if (segmentMetadata.getSource() != SegmentMetadata.Source.API
187+
|| flagsmithId == null) {
188+
return null;
189+
}
190+
174191
Segment segment = new Segment();
175-
segment.setId(Integer.valueOf(segmentModel.getKey()));
192+
segment.setId(flagsmithId);
176193
segment.setName(segmentModel.getName());
177194

178195
return segment;
179-
}).collect(Collectors.toList());
196+
}).filter(Objects::nonNull).collect(Collectors.toList());
180197
}
181198

182199
/**

src/main/java/com/flagsmith/flagengine/Engine.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ private static SegmentEvaluationResult evaluateSegments(
5151
for (SegmentContext segmentContext : context.getSegments().getAdditionalProperties().values()) {
5252
if (SegmentEvaluator.isContextInSegment(context, segmentContext)) {
5353
segments.add(new SegmentResult().withKey(segmentContext.getKey())
54-
.withName(segmentContext.getName()));
54+
.withName(segmentContext.getName())
55+
.withMetadata(segmentContext.getMetadata()));
5556

5657
List<FeatureContext> segmentOverrides = segmentContext.getOverrides();
5758

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

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
package com.flagsmith.mappers;
22

33
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.flagsmith.MapperFactory;
45
import com.flagsmith.flagengine.EngineConstants;
56
import com.flagsmith.flagengine.EnvironmentContext;
67
import com.flagsmith.flagengine.EvaluationContext;
78
import com.flagsmith.flagengine.FeatureContext;
89
import com.flagsmith.flagengine.FeatureValue;
910
import com.flagsmith.flagengine.IdentityContext;
11+
import com.flagsmith.flagengine.Metadata;
1012
import com.flagsmith.flagengine.SegmentCondition;
1113
import com.flagsmith.flagengine.SegmentContext;
1214
import com.flagsmith.flagengine.SegmentRule;
1315
import com.flagsmith.flagengine.Segments;
1416
import com.flagsmith.flagengine.Traits;
1517
import com.flagsmith.flagengine.segments.constants.SegmentConditions;
18+
import com.flagsmith.models.SegmentMetadata;
1619
import java.util.ArrayList;
1720
import java.util.HashMap;
1821
import java.util.List;
@@ -200,11 +203,20 @@ private static Map<String, SegmentContext> mapIdentityOverridesToSegments(
200203
overrides.add(override);
201204
}
202205

206+
SegmentMetadata metadata = new SegmentMetadata();
207+
metadata.setSource(SegmentMetadata.Source.IDENTITY_OVERRIDES);
208+
209+
Map<String, Object> metadataMap = MapperFactory.getMapper()
210+
.convertValue(metadata,
211+
new com.fasterxml.jackson.core.type.TypeReference<Map<String, Object>>() {
212+
});
213+
203214
SegmentContext segmentContext = new SegmentContext()
204215
.withKey("") // Identity override segments never use % Split operator
205216
.withName("identity_overrides")
206217
.withRules(List.of(segmentRule))
207-
.withOverrides(overrides);
218+
.withOverrides(overrides)
219+
.withMetadata(metadataMap);
208220

209221
segmentContexts.put(segmentKey, segmentContext);
210222
}
@@ -365,8 +377,6 @@ private static FeatureContext mapFeatureStateToFeatureContext(JsonNode featureSt
365377
* @return the segment context
366378
*/
367379
private static SegmentContext mapSegmentToSegmentContext(JsonNode segment) {
368-
String segmentKey = segment.get("id").asText();
369-
370380
// Map rules
371381
List<SegmentRule> rules = new ArrayList<>();
372382
JsonNode segmentRules = segment.get("rules");
@@ -381,11 +391,23 @@ private static SegmentContext mapSegmentToSegmentContext(JsonNode segment) {
381391
overrides = mapEnvironmentDocumentFeatureStatesToFeatureContexts(segmentFeatureStates);
382392
}
383393

394+
// Map metadata
395+
SegmentMetadata metadata = new SegmentMetadata();
396+
metadata.setSource(SegmentMetadata.Source.API);
397+
metadata.setFlagsmithId(segment.get("id").asInt());
398+
399+
Map<String, Object> metadataMap = MapperFactory.getMapper()
400+
.convertValue(metadata,
401+
new com.fasterxml.jackson.core.type.TypeReference<Map<String, Object>>() {
402+
});
403+
404+
String segmentKey = segment.get("id").asText();
384405
return new SegmentContext()
385406
.withKey(segmentKey)
386407
.withName(segment.get("name").asText())
387408
.withRules(rules)
388-
.withOverrides(overrides);
409+
.withOverrides(overrides)
410+
.withMetadata(metadataMap);
389411
}
390412

391413
/**
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.flagsmith.models;
2+
3+
/**
4+
* SegmentMetadata
5+
*
6+
* <p>Additional metadata associated with a segment.
7+
*
8+
*/
9+
public class SegmentMetadata {
10+
/**
11+
* Source
12+
*
13+
* <p>How the segment was created.
14+
* If the segment was created via the API, this will be `API`.
15+
* If the segment was created to support identity overrides in local evaluation,
16+
* this will be `IDENTITY_OVERRIDES`.
17+
*/
18+
public enum Source {
19+
API,
20+
IDENTITY_OVERRIDES;
21+
}
22+
23+
private Integer flagsmithId;
24+
private Source source;
25+
26+
/*
27+
* FlagsmithId
28+
* <p>The internal Flagsmith ID for the segment.
29+
*
30+
* @return The flagsmithId
31+
*/
32+
public Integer getFlagsmithId() {
33+
return flagsmithId;
34+
}
35+
36+
/*
37+
* FlagsmithId
38+
* <p>The internal Flagsmith ID for the segment.
39+
*
40+
* @param flagsmithId The flagsmithId
41+
*/
42+
public void setFlagsmithId(Integer flagsmithId) {
43+
this.flagsmithId = flagsmithId;
44+
}
45+
46+
/*
47+
* Source
48+
* <p>How the segment was created.
49+
*
50+
* @return The source
51+
*/
52+
public Source getSource() {
53+
return source;
54+
}
55+
56+
/*
57+
* Source
58+
* <p>How the segment was created.
59+
*
60+
* @param source The source
61+
*/
62+
public void setSource(Source source) {
63+
this.source = source;
64+
}
65+
}

src/test/java/com/flagsmith/FlagsmithClientTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,45 @@ public void testGetIdentitySegmentsWithValidTrait() throws JsonProcessingExcepti
543543
assertEquals(segments.get(0).getName(), "Test segment");
544544
}
545545

546+
@Test
547+
public void testGetIdentitySegments__NonAPISourceInMetadata__ReturnsExpected() throws JsonProcessingException,
548+
FlagsmithClientError {
549+
String baseUrl = "http://bad-url";
550+
551+
MockInterceptor interceptor = new MockInterceptor();
552+
interceptor.addRule()
553+
.get(baseUrl + "/environment-document/")
554+
.anyTimes()
555+
.respond(
556+
FlagsmithTestHelper.environmentString(),
557+
MEDIATYPE_JSON);
558+
559+
FlagsmithClient client = FlagsmithClient.newBuilder()
560+
.withConfiguration(
561+
FlagsmithConfig.newBuilder()
562+
.baseUri(baseUrl)
563+
.addHttpInterceptor(interceptor)
564+
.withLocalEvaluation(true)
565+
.build())
566+
.setApiKey("ser.abcdefg")
567+
.build();
568+
569+
client.updateEnvironment();
570+
571+
String identifier = "overridden-identity";
572+
Map<String, Object> traits = new HashMap<String, Object>() {
573+
{
574+
put("foo", "bar");
575+
}
576+
};
577+
578+
List<Segment> segments = client.getIdentitySegments(identifier, traits);
579+
580+
// no identity overrides segment present
581+
assertEquals(segments.size(), 1);
582+
assertEquals(segments.get(0).getName(), "Test segment");
583+
}
584+
546585
@Test
547586
public void testUpdateEnvironment_DoesNothing_WhenGetEnvironmentThrowsExceptionAndEnvironmentExists() {
548587
// Given

0 commit comments

Comments
 (0)