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

Commit 1f24ce7

Browse files
author
Dan Richelson
committed
Add check when adding custom attribute with same key as built-in attribute. Fix formatting. Fix null check in user builder.
1 parent 1fb5b23 commit 1f24ce7

File tree

2 files changed

+90
-29
lines changed

2 files changed

+90
-29
lines changed

src/main/java/com/launchdarkly/client/LDUser.java

Lines changed: 76 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
* A {@code LDUser} object contains specific attributes of a user browsing your site. The only mandatory property property is the {@code key},
1616
* which must uniquely identify each user. For authenticated users, this may be a username or e-mail address. For anonymous users,
1717
* this could be an IP address or session ID.
18-
*
18+
* <p>
1919
* Besides the mandatory {@code key}, {@code LDUser} supports two kinds of optional attributes: interpreted attributes (e.g. {@code ip} and {@code country})
2020
* and custom attributes. LaunchDarkly can parse interpreted attributes and attach meaning to them. For example, from an {@code ip} address, LaunchDarkly can
2121
* do a geo IP lookup and determine the user's country.
22-
*
22+
* <p>
2323
* Custom attributes are not parsed by LaunchDarkly. They can be used in custom rules-- for example, a custom attribute such as "customer_ranking" can be used to
2424
* launch a feature to the top 10% of users on a site.
2525
*/
@@ -43,21 +43,22 @@ public class LDUser {
4343
}
4444

4545
protected LDUser(Builder builder) {
46-
this.key = builder.key == null? null : new JsonPrimitive(builder.key);
47-
this.ip = builder.ip == null? null : new JsonPrimitive(builder.ip);
48-
this.country = builder.country == null? null : new JsonPrimitive(builder.country.getAlpha2());
46+
this.key = builder.key == null ? null : new JsonPrimitive(builder.key);
47+
this.ip = builder.ip == null ? null : new JsonPrimitive(builder.ip);
48+
this.country = builder.country == null ? null : new JsonPrimitive(builder.country.getAlpha2());
4949
this.secondary = builder.secondary == null ? null : new JsonPrimitive(builder.secondary);
5050
this.firstName = builder.firstName == null ? null : new JsonPrimitive(builder.firstName);
5151
this.lastName = builder.lastName == null ? null : new JsonPrimitive(builder.lastName);
5252
this.email = builder.email == null ? null : new JsonPrimitive(builder.email);
5353
this.name = builder.name == null ? null : new JsonPrimitive(builder.name);
5454
this.avatar = builder.avatar == null ? null : new JsonPrimitive(builder.avatar);
55-
this.anonymous = builder.anonymous == null ? null : new JsonPrimitive(builder.anonymous);
55+
this.anonymous = builder.anonymous == null ? null : new JsonPrimitive(builder.anonymous);
5656
this.custom = new HashMap<>(builder.custom);
5757
}
5858

5959
/**
6060
* Create a user with the given key
61+
*
6162
* @param key a {@code String} that uniquely identifies a user
6263
*/
6364
public LDUser(String key) {
@@ -69,23 +70,41 @@ JsonPrimitive getKey() {
6970
return key;
7071
}
7172

72-
JsonPrimitive getIp() { return ip; }
73+
JsonPrimitive getIp() {
74+
return ip;
75+
}
7376

74-
JsonPrimitive getCountry() { return country; }
77+
JsonPrimitive getCountry() {
78+
return country;
79+
}
7580

76-
JsonPrimitive getSecondary() { return secondary; }
81+
JsonPrimitive getSecondary() {
82+
return secondary;
83+
}
7784

78-
JsonPrimitive getName() { return name; }
85+
JsonPrimitive getName() {
86+
return name;
87+
}
7988

80-
JsonPrimitive getFirstName() { return firstName; }
89+
JsonPrimitive getFirstName() {
90+
return firstName;
91+
}
8192

82-
JsonPrimitive getLastName() { return lastName; }
93+
JsonPrimitive getLastName() {
94+
return lastName;
95+
}
8396

84-
JsonPrimitive getEmail() { return email; }
97+
JsonPrimitive getEmail() {
98+
return email;
99+
}
85100

86-
JsonPrimitive getAvatar() { return avatar; }
101+
JsonPrimitive getAvatar() {
102+
return avatar;
103+
}
87104

88-
JsonPrimitive getAnonymous() { return anonymous; }
105+
JsonPrimitive getAnonymous() {
106+
return anonymous;
107+
}
89108

90109
JsonElement getCustom(String key) {
91110
return custom.get(key);
@@ -94,14 +113,13 @@ JsonElement getCustom(String key) {
94113
/**
95114
* A <a href="http://en.wikipedia.org/wiki/Builder_pattern">builder</a> that helps construct {@link com.launchdarkly.client.LDUser} objects. Builder
96115
* calls can be chained, enabling the following pattern:
97-
*
116+
* <p>
98117
* <pre>
99118
* LDUser user = new LDUser.Builder("key")
100119
* .country("US")
101120
* .ip("192.168.0.1")
102121
* .build()
103122
* </pre>
104-
*
105123
*/
106124
public static class Builder {
107125
private String key;
@@ -118,6 +136,7 @@ public static class Builder {
118136

119137
/**
120138
* Create a builder with the specified key
139+
*
121140
* @param key the unique key for this user
122141
*/
123142
public Builder(String key) {
@@ -127,6 +146,7 @@ public Builder(String key) {
127146

128147
/**
129148
* Set the IP for a user
149+
*
130150
* @param s the IP address for the user
131151
* @return the builder
132152
*/
@@ -144,6 +164,7 @@ public Builder secondary(String s) {
144164
* Set the country for a user. The country should be a valid <a href="http://en.wikipedia.org/wiki/ISO_3166-1">ISO 3166-1</a>
145165
* alpha-2 or alpha-3 code. If it is not a valid ISO-3166-1 code, an attempt will be made to look up the country by its name.
146166
* If that fails, a warning will be logged, and the country will not be set.
167+
*
147168
* @param s the country for the user
148169
* @return the builder
149170
*/
@@ -155,8 +176,7 @@ public Builder country(String s) {
155176

156177
if (codes.isEmpty()) {
157178
logger.warn("Invalid country. Expected valid ISO-3166-1 code: " + s);
158-
}
159-
else if (codes.size() > 1) {
179+
} else if (codes.size() > 1) {
160180
// See if any of the codes is an exact match
161181
for (LDCountryCode c : codes) {
162182
if (c.getName().equals(s)) {
@@ -166,8 +186,7 @@ else if (codes.size() > 1) {
166186
}
167187
logger.warn("Ambiguous country. Provided code matches multiple countries: " + s);
168188
country = codes.get(0);
169-
}
170-
else {
189+
} else {
171190
country = codes.get(0);
172191
}
173192

@@ -188,6 +207,7 @@ public Builder country(LDCountryCode country) {
188207

189208
/**
190209
* Sets the user's first name
210+
*
191211
* @param firstName the user's first name
192212
* @return the builder
193213
*/
@@ -198,6 +218,7 @@ public Builder firstName(String firstName) {
198218

199219
/**
200220
* Sets whether this user is anonymous
221+
*
201222
* @param anonymous whether the user is anonymous
202223
* @return the builder
203224
*/
@@ -208,6 +229,7 @@ public Builder anonymous(boolean anonymous) {
208229

209230
/**
210231
* Sets the user's last name
232+
*
211233
* @param lastName the user's last name
212234
* @return the builder
213235
*/
@@ -218,6 +240,7 @@ public Builder lastName(String lastName) {
218240

219241
/**
220242
* Sets the user's full name
243+
*
221244
* @param name the user's full name
222245
* @return the builder
223246
*/
@@ -228,6 +251,7 @@ public Builder name(String name) {
228251

229252
/**
230253
* Sets the user's avatar
254+
*
231255
* @param avatar the user's avatar
232256
* @return the builder
233257
*/
@@ -238,6 +262,7 @@ public Builder avatar(String avatar) {
238262

239263
/**
240264
* Sets the user's e-mail address
265+
*
241266
* @param email the e-mail address
242267
* @return the builder
243268
*/
@@ -248,61 +273,71 @@ public Builder email(String email) {
248273

249274
/**
250275
* Add a {@link java.lang.String}-valued custom attribute.
276+
*
251277
* @param k the key for the custom attribute. When set to one of the built-in user attribute keys, this custom attribute will be ignored.
252278
* @param v the value for the custom attribute
253279
* @return the builder
254280
*/
255281
public Builder custom(String k, String v) {
256-
if (key != null && v != null) {
282+
checkCustomAttribute(k);
283+
if (k != null && v != null) {
257284
custom.put(k, new JsonPrimitive(v));
258285
}
259286
return this;
260287
}
261288

262289
/**
263290
* Add a {@link java.lang.Number}-valued custom attribute
291+
*
264292
* @param k the key for the custom attribute. When set to one of the built-in user attribute keys, this custom attribute will be ignored.
265293
* @param n the value for the custom attribute
266294
* @return the builder
267295
*/
268296
public Builder custom(String k, Number n) {
269-
if (key != null && n != null) {
297+
checkCustomAttribute(k);
298+
if (k != null && n != null) {
270299
custom.put(k, new JsonPrimitive(n));
271300
}
272301
return this;
273302
}
274303

275304
/**
276305
* Add a {@link java.lang.Boolean}-valued custom attribute
306+
*
277307
* @param k the key for the custom attribute. When set to one of the built-in user attribute keys, this custom attribute will be ignored.
278308
* @param b the value for the custom attribute
279309
* @return the builder
280310
*/
281311
public Builder custom(String k, Boolean b) {
282-
if (key != null && b != null) {
312+
checkCustomAttribute(k);
313+
if (k != null && b != null) {
283314
custom.put(k, new JsonPrimitive(b));
284315
}
285316
return this;
286317
}
287318

288319
/**
289320
* Add a list of {@link java.lang.String}-valued custom attributes
290-
* @param k the key for the list. When set to one of the built-in user attribute keys, this custom attribute will be ignored.
321+
*
322+
* @param k the key for the list. When set to one of the built-in user attribute keys, this custom attribute will be ignored.
291323
* @param vs the values for the attribute
292324
* @return the builder
293325
* @deprecated As of version 0.16.0, renamed to {@link #customString(String, List) customString}
294326
*/
295327
public Builder custom(String k, List<String> vs) {
328+
checkCustomAttribute(k);
296329
return this.customString(k, vs);
297330
}
298-
331+
299332
/**
300333
* Add a list of {@link java.lang.String}-valued custom attributes
301-
* @param k the key for the list. When set to one of the built-in user attribute keys, this custom attribute will be ignored.
334+
*
335+
* @param k the key for the list. When set to one of the built-in user attribute keys, this custom attribute will be ignored.
302336
* @param vs the values for the attribute
303337
* @return the builder
304338
*/
305339
public Builder customString(String k, List<String> vs) {
340+
checkCustomAttribute(k);
306341
JsonArray array = new JsonArray();
307342
for (String v : vs) {
308343
if (v != null) {
@@ -312,14 +347,16 @@ public Builder customString(String k, List<String> vs) {
312347
custom.put(k, array);
313348
return this;
314349
}
315-
350+
316351
/**
317352
* Add a list of {@link java.lang.Integer}-valued custom attributes
318-
* @param k the key for the list. When set to one of the built-in user attribute keys, this custom attribute will be ignored.
353+
*
354+
* @param k the key for the list. When set to one of the built-in user attribute keys, this custom attribute will be ignored.
319355
* @param vs the values for the attribute
320356
* @return the builder
321357
*/
322358
public Builder customNumber(String k, List<Number> vs) {
359+
checkCustomAttribute(k);
323360
JsonArray array = new JsonArray();
324361
for (Number v : vs) {
325362
if (v != null) {
@@ -330,8 +367,18 @@ public Builder customNumber(String k, List<Number> vs) {
330367
return this;
331368
}
332369

370+
private void checkCustomAttribute(String key) {
371+
for (UserAttribute a : UserAttribute.values()) {
372+
if (a.name().equals(key)) {
373+
logger.warn("Built-in attribute key: " + key + " added as custom attribute! This custom attribute will be ignored during Feature Flag evaluation");
374+
return;
375+
}
376+
}
377+
}
378+
333379
/**
334380
* Build the configured {@link com.launchdarkly.client.LDUser} object
381+
*
335382
* @return the {@link com.launchdarkly.client.LDUser} configured by this builder
336383
*/
337384
public LDUser build() {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.launchdarkly.client;
2+
3+
public enum UserAttribute {
4+
key,
5+
secondary,
6+
ip,
7+
email,
8+
name,
9+
avatar,
10+
firstName,
11+
lastName,
12+
anonymous,
13+
country;
14+
}

0 commit comments

Comments
 (0)