Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.
Merged

4.1.0 #127

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion src/main/java/com/launchdarkly/client/LDUser.java
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,28 @@ public Builder customNumber(String k, List<Number> vs) {
custom.put(k, array);
return this;
}


/**
* Add a custom attribute with a list of arbitrary JSON values. When set to one of the
* <a href="http://docs.launchdarkly.com/docs/targeting-users#targeting-based-on-user-attributes">built-in
* user attribute keys</a>, this custom attribute will be ignored.
*
* @param k the key for the list
* @param vs the values for the attribute
* @return the builder
*/
public Builder customValues(String k, List<JsonElement> vs) {
checkCustomAttribute(k);
JsonArray array = new JsonArray();
for (JsonElement v : vs) {
if (v != null) {
array.add(v);
}
}
custom.put(k, array);
return this;
}

/**
* Add a {@link java.lang.String}-valued custom attribute that will not be sent back to LaunchDarkly.
* When set to one of the
Expand Down Expand Up @@ -766,6 +787,21 @@ public Builder privateCustomNumber(String k, List<Number> vs) {
return customNumber(k, vs);
}

/**
* Add a custom attribute with a list of arbitrary JSON values. When set to one of the
* <a href="http://docs.launchdarkly.com/docs/targeting-users#targeting-based-on-user-attributes">
* built-in user attribute keys</a>, this custom attribute will be ignored. The custom attribute value will not be sent
* back to LaunchDarkly in analytics events.
*
* @param k the key for the list
* @param vs the values for the attribute
* @return the builder
*/
public Builder privateCustomValues(String k, List<JsonElement> vs) {
privateAttrNames.add(k);
return customValues(k, vs);
}

private void checkCustomAttribute(String key) {
for (UserAttribute a : UserAttribute.values()) {
if (a.name().equals(key)) {
Expand Down
20 changes: 19 additions & 1 deletion src/main/java/com/launchdarkly/client/VersionedDataKind.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package com.launchdarkly.client;

import com.google.common.collect.ImmutableList;

/**
* The descriptor for a specific kind of {@link VersionedData} objects that may exist in a {@link FeatureStore}.
* You will not need to refer to this type unless you are directly manipulating a {@code FeatureStore}
* or writing your own {@code FeatureStore} implementation. If you are implementing a custom store, for
* maximum forward compatibility you should only refer to {@link VersionedData}, {@link VersionedDataKind},
* and {@link VersionedDataKind#ALL}, and avoid any dependencies on specific type descriptor instances
* or any specific fields of the types they describe.
* @since 3.0.0
*/
public abstract class VersionedDataKind<T extends VersionedData> {
Expand Down Expand Up @@ -41,7 +48,9 @@ String getKeyFromStreamApiPath(String path) {
return path.startsWith(getStreamApiPath()) ? path.substring(getStreamApiPath().length()) : null;
}


/**
* The {@link VersionedDataKind} instance that describes feature flag data.
*/
public static VersionedDataKind<FeatureFlag> FEATURES = new VersionedDataKind<FeatureFlag>() {

public String getNamespace() {
Expand All @@ -61,6 +70,9 @@ public FeatureFlag makeDeletedItem(String key, int version) {
}
};

/**
* The {@link VersionedDataKind} instance that describes user segment data.
*/
public static VersionedDataKind<Segment> SEGMENTS = new VersionedDataKind<Segment>() {

public String getNamespace() {
Expand All @@ -79,4 +91,10 @@ public Segment makeDeletedItem(String key, int version) {
return new Segment.Builder(key).deleted(true).version(version).build();
}
};

/**
* A list of all existing instances of {@link VersionedDataKind}.
* @since 4.1.0
*/
public static Iterable<VersionedDataKind<?>> ALL = ImmutableList.of(FEATURES, SEGMENTS);
}
47 changes: 47 additions & 0 deletions src/test/java/com/launchdarkly/client/LDUserTest.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.launchdarkly.client;

import com.google.common.collect.ImmutableList;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.reflect.TypeToken;

Expand All @@ -10,6 +13,10 @@
import java.lang.reflect.Type;
import java.util.Map;

import static com.launchdarkly.client.TestUtil.jbool;
import static com.launchdarkly.client.TestUtil.jdouble;
import static com.launchdarkly.client.TestUtil.jint;
import static com.launchdarkly.client.TestUtil.js;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

Expand Down Expand Up @@ -233,4 +240,44 @@ public void getValueReturnsNullIfNotFound() {
.build();
assertNull(user.getValueForEvaluation("height"));
}

@Test
public void canAddCustomAttrWithListOfStrings() {
LDUser user = new LDUser.Builder("key")
.customString("foo", ImmutableList.of("a", "b"))
.build();
JsonElement expectedAttr = makeCustomAttrWithListOfValues("foo", js("a"), js("b"));
JsonObject jo = LDConfig.DEFAULT.gson.toJsonTree(user).getAsJsonObject();
assertEquals(expectedAttr, jo.get("custom"));
}

@Test
public void canAddCustomAttrWithListOfNumbers() {
LDUser user = new LDUser.Builder("key")
.customNumber("foo", ImmutableList.<Number>of(new Integer(1), new Double(2)))
.build();
JsonElement expectedAttr = makeCustomAttrWithListOfValues("foo", jint(1), jdouble(2));
JsonObject jo = LDConfig.DEFAULT.gson.toJsonTree(user).getAsJsonObject();
assertEquals(expectedAttr, jo.get("custom"));
}

@Test
public void canAddCustomAttrWithListOfMixedValues() {
LDUser user = new LDUser.Builder("key")
.customValues("foo", ImmutableList.<JsonElement>of(js("a"), jint(1), jbool(true)))
.build();
JsonElement expectedAttr = makeCustomAttrWithListOfValues("foo", js("a"), jint(1), jbool(true));
JsonObject jo = LDConfig.DEFAULT.gson.toJsonTree(user).getAsJsonObject();
assertEquals(expectedAttr, jo.get("custom"));
}

private JsonElement makeCustomAttrWithListOfValues(String name, JsonElement... values) {
JsonObject ret = new JsonObject();
JsonArray a = new JsonArray();
for (JsonElement v: values) {
a.add(v);
}
ret.add(name, a);
return ret;
}
}