@@ -177,8 +177,7 @@ private static Map<String, SegmentContext> mapIdentityOverridesToSegments(
177177 List <FeatureContext > overridesKey = entry .getKey ();
178178 List <String > identifiers = entry .getValue ();
179179
180- // Generate unique segment key
181- String segmentKey = String .valueOf (overridesKey .hashCode ());
180+ String segmentKey = generateVirtualSegmentKey (overridesKey );
182181
183182 // Create segment condition for identifier check
184183 SegmentCondition identifierCondition = new SegmentCondition ()
@@ -191,17 +190,17 @@ private static Map<String, SegmentContext> mapIdentityOverridesToSegments(
191190 .withType (SegmentRule .Type .ALL )
192191 .withConditions (List .of (identifierCondition ));
193192
194- // Create overrides from FeatureContext objects (much cleaner now!)
193+ // Create overrides from FeatureContext objects
195194 List <FeatureContext > overrides = new ArrayList <>();
196195 for (FeatureContext featureContext : overridesKey ) {
197196 // Copy the feature context for the override
198197 FeatureContext override = new FeatureContext (featureContext )
199- .withKey ("" ); // Identity overrides are never multivariate, so no need to set key
198+ .withKey ("" ); // Identity overrides never carry multivariate options
200199 overrides .add (override );
201200 }
202201
203202 SegmentContext segmentContext = new SegmentContext ()
204- .withKey ("" )
203+ .withKey ("" ) // Identity override segments never use % Split operator
205204 .withName ("identity_overrides" )
206205 .withRules (List .of (segmentRule ))
207206 .withOverrides (overrides );
@@ -339,7 +338,7 @@ private static FeatureContext mapFeatureStateToFeatureContext(JsonNode featureSt
339338 for (JsonNode multivariateValue : sortedMultivariate ) {
340339 FeatureValue variant = new FeatureValue ()
341340 .withValue (getFeatureStateValue (
342- multivariateValue .get ("multivariate_feature_option" ), "value" ))
341+ multivariateValue .get ("multivariate_feature_option" ), "value" ))
343342 .withWeight (multivariateValue .get ("percentage_allocation" ).asDouble ());
344343 variants .add (variant );
345344 }
@@ -387,4 +386,31 @@ private static SegmentContext mapSegmentToSegmentContext(JsonNode segment) {
387386 .withRules (rules )
388387 .withOverrides (overrides );
389388 }
389+
390+ /**
391+ * Generates a unique segment key based on feature contexts.
392+ * Uses a combination of feature names and values to ensure
393+ * uniqueness.
394+ *
395+ * @param featureContexts list of feature contexts
396+ * @return unique segment key
397+ */
398+ private static String generateVirtualSegmentKey (
399+ List <FeatureContext > featureContexts ) {
400+ StringBuilder keyBuilder = new StringBuilder ();
401+
402+ // Add feature information to the key
403+ for (FeatureContext featureContext : featureContexts ) {
404+ keyBuilder .append (featureContext .getName ())
405+ .append (":" )
406+ .append (featureContext .getEnabled ())
407+ .append (":" )
408+ .append (featureContext .getValue ())
409+ .append ("|" );
410+ }
411+
412+ // Generate a hash of the combined string for a shorter key
413+ // This is safer than using List.hashCode() as we control the string content
414+ return String .valueOf (keyBuilder .toString ().hashCode ());
415+ }
390416}
0 commit comments