All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.launchdarkly.client.LDUser Maven / Gradle / Ivy

package com.launchdarkly.client;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.common.collect.ImmutableMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * A {@code LDUser} object contains specific attributes of a user browsing your site. The only mandatory property property is the {@code key},
 * which must uniquely identify each user. For authenticated users, this may be a username or e-mail address. For anonymous users,
 * this could be an IP address or session ID.
 * 

* Besides the mandatory {@code key}, {@code LDUser} supports two kinds of optional attributes: interpreted attributes (e.g. {@code ip} and {@code country}) * and custom attributes. LaunchDarkly can parse interpreted attributes and attach meaning to them. For example, from an {@code ip} address, LaunchDarkly can * do a geo IP lookup and determine the user's country. *

* 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 * launch a feature to the top 10% of users on a site. */ public class LDUser { private final JsonPrimitive key; private JsonPrimitive secondary; private JsonPrimitive ip; private JsonPrimitive email; private JsonPrimitive name; private JsonPrimitive avatar; private JsonPrimitive firstName; private JsonPrimitive lastName; private JsonPrimitive anonymous; private JsonPrimitive country; private Map custom; private static final Logger logger = LoggerFactory.getLogger(LDUser.class); protected LDUser(Builder builder) { if (builder.key == null || builder.key.equals("")) { logger.warn("User was created with null/empty key"); } this.key = builder.key == null ? null : new JsonPrimitive(builder.key); this.ip = builder.ip == null ? null : new JsonPrimitive(builder.ip); this.country = builder.country == null ? null : new JsonPrimitive(builder.country.getAlpha2()); this.secondary = builder.secondary == null ? null : new JsonPrimitive(builder.secondary); this.firstName = builder.firstName == null ? null : new JsonPrimitive(builder.firstName); this.lastName = builder.lastName == null ? null : new JsonPrimitive(builder.lastName); this.email = builder.email == null ? null : new JsonPrimitive(builder.email); this.name = builder.name == null ? null : new JsonPrimitive(builder.name); this.avatar = builder.avatar == null ? null : new JsonPrimitive(builder.avatar); this.anonymous = builder.anonymous == null ? null : new JsonPrimitive(builder.anonymous); this.custom = new HashMap<>(builder.custom); } /** * Create a user with the given key * * @param key a {@code String} that uniquely identifies a user */ public LDUser(String key) { this.key = new JsonPrimitive(key); this.custom = new HashMap<>(); } protected JsonElement getValueForEvaluation(String attribute) { try { return UserAttribute.valueOf(attribute).get(this); } catch (IllegalArgumentException expected) { return getCustom(attribute); } } JsonPrimitive getKey() { return key; } String getKeyAsString() { if (key == null) { return ""; } else { return key.getAsString(); } } JsonPrimitive getIp() { return ip; } JsonPrimitive getCountry() { return country; } JsonPrimitive getSecondary() { return secondary; } JsonPrimitive getName() { return name; } JsonPrimitive getFirstName() { return firstName; } JsonPrimitive getLastName() { return lastName; } JsonPrimitive getEmail() { return email; } JsonPrimitive getAvatar() { return avatar; } JsonPrimitive getAnonymous() { return anonymous; } JsonElement getCustom(String key) { if (custom != null) { return custom.get(key); } return null; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; LDUser ldUser = (LDUser) o; if (key != null ? !key.equals(ldUser.key) : ldUser.key != null) return false; if (secondary != null ? !secondary.equals(ldUser.secondary) : ldUser.secondary != null) return false; if (ip != null ? !ip.equals(ldUser.ip) : ldUser.ip != null) return false; if (email != null ? !email.equals(ldUser.email) : ldUser.email != null) return false; if (name != null ? !name.equals(ldUser.name) : ldUser.name != null) return false; if (avatar != null ? !avatar.equals(ldUser.avatar) : ldUser.avatar != null) return false; if (firstName != null ? !firstName.equals(ldUser.firstName) : ldUser.firstName != null) return false; if (lastName != null ? !lastName.equals(ldUser.lastName) : ldUser.lastName != null) return false; if (anonymous != null ? !anonymous.equals(ldUser.anonymous) : ldUser.anonymous != null) return false; if (country != null ? !country.equals(ldUser.country) : ldUser.country != null) return false; return custom != null ? custom.equals(ldUser.custom) : ldUser.custom == null; } @Override public int hashCode() { int result = key != null ? key.hashCode() : 0; result = 31 * result + (secondary != null ? secondary.hashCode() : 0); result = 31 * result + (ip != null ? ip.hashCode() : 0); result = 31 * result + (email != null ? email.hashCode() : 0); result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (avatar != null ? avatar.hashCode() : 0); result = 31 * result + (firstName != null ? firstName.hashCode() : 0); result = 31 * result + (lastName != null ? lastName.hashCode() : 0); result = 31 * result + (anonymous != null ? anonymous.hashCode() : 0); result = 31 * result + (country != null ? country.hashCode() : 0); result = 31 * result + (custom != null ? custom.hashCode() : 0); return result; } /** * A builder that helps construct {@link LDUser} objects. Builder * calls can be chained, enabling the following pattern: *

*

   * LDUser user = new LDUser.Builder("key")
   *      .country("US")
   *      .ip("192.168.0.1")
   *      .build()
   * 
*/ public static class Builder { private String key; private String secondary; private String ip; private String firstName; private String lastName; private String email; private String name; private String avatar; private Boolean anonymous; private LDCountryCode country; private Map custom; /** * Create a builder with the specified key * * @param key the unique key for this user */ public Builder(String key) { this.key = key; this.custom = new HashMap<>(); } /** * Create a builder with an existing user * * @param user an existing {@code LDUser} */ public Builder(LDUser user) { JsonPrimitive userKey = user.getKey(); if (userKey.isJsonNull()) { this.key = null; } else { this.key = user.getKeyAsString(); } this.secondary = user.getSecondary() != null ? user.getSecondary().getAsString() : null; this.ip = user.getIp() != null ? user.getIp().getAsString() : null; this.firstName = user.getFirstName() != null ? user.getFirstName().getAsString() : null; this.lastName = user.getLastName() != null ? user.getLastName().getAsString() : null; this.email = user.getEmail() != null ? user.getEmail().getAsString() : null; this.name = user.getName() != null ? user.getName().getAsString() : null; this.avatar = user.getAvatar() != null ? user.getAvatar().getAsString() : null; this.anonymous = user.getAnonymous() != null ? user.getAnonymous().getAsBoolean() : null; this.country = user.getCountry() != null ? LDCountryCode.valueOf(user.getCountry().getAsString()) : null; this.custom = ImmutableMap.copyOf(user.custom); } /** * Set the IP for a user * * @param s the IP address for the user * @return the builder */ public Builder ip(String s) { this.ip = s; return this; } public Builder secondary(String s) { this.secondary = s; return this; } /** * Set the country for a user. The country should be a valid ISO 3166-1 * 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. * If that fails, a warning will be logged, and the country will not be set. * * @param s the country for the user * @return the builder */ public Builder country(String s) { country = LDCountryCode.getByCode(s, false); if (country == null) { List codes = LDCountryCode.findByName("^" + Pattern.quote(s) + ".*"); if (codes.isEmpty()) { logger.warn("Invalid country. Expected valid ISO-3166-1 code: " + s); } else if (codes.size() > 1) { // See if any of the codes is an exact match for (LDCountryCode c : codes) { if (c.getName().equals(s)) { country = c; return this; } } logger.warn("Ambiguous country. Provided code matches multiple countries: " + s); country = codes.get(0); } else { country = codes.get(0); } } return this; } /** * Set the country for a user. * * @param country the country for the user * @return the builder */ public Builder country(LDCountryCode country) { this.country = country; return this; } /** * Sets the user's first name * * @param firstName the user's first name * @return the builder */ public Builder firstName(String firstName) { this.firstName = firstName; return this; } /** * Sets whether this user is anonymous * * @param anonymous whether the user is anonymous * @return the builder */ public Builder anonymous(boolean anonymous) { this.anonymous = anonymous; return this; } /** * Sets the user's last name * * @param lastName the user's last name * @return the builder */ public Builder lastName(String lastName) { this.lastName = lastName; return this; } /** * Sets the user's full name * * @param name the user's full name * @return the builder */ public Builder name(String name) { this.name = name; return this; } /** * Sets the user's avatar * * @param avatar the user's avatar * @return the builder */ public Builder avatar(String avatar) { this.avatar = avatar; return this; } /** * Sets the user's e-mail address * * @param email the e-mail address * @return the builder */ public Builder email(String email) { this.email = email; return this; } /** * Add a {@link java.lang.String}-valued custom attribute. When set to one of the * * built-in user attribute keys, this custom attribute will be ignored. * * @param k the key for the custom attribute. * @param v the value for the custom attribute * @return the builder */ public Builder custom(String k, String v) { checkCustomAttribute(k); if (k != null && v != null) { custom.put(k, new JsonPrimitive(v)); } return this; } /** * Add a {@link java.lang.Number}-valued custom attribute. When set to one of the * * built-in user attribute keys, this custom attribute will be ignored. * * @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. * @param n the value for the custom attribute * @return the builder */ public Builder custom(String k, Number n) { checkCustomAttribute(k); if (k != null && n != null) { custom.put(k, new JsonPrimitive(n)); } return this; } /** * Add a {@link java.lang.Boolean}-valued custom attribute. When set to one of the * * built-in user attribute keys, this custom attribute will be ignored. * * @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. * @param b the value for the custom attribute * @return the builder */ public Builder custom(String k, Boolean b) { checkCustomAttribute(k); if (k != null && b != null) { custom.put(k, new JsonPrimitive(b)); } return this; } /** * Add a list of {@link java.lang.String}-valued custom attributes. When set to one of the * * built-in user attribute keys, this custom attribute will be ignored. * * @param k the key for the list. When set to one of the built-in user attribute keys, this custom attribute will be ignored. * @param vs the values for the attribute * @return the builder * @deprecated As of version 0.16.0, renamed to {@link #customString(String, List) customString} */ public Builder custom(String k, List vs) { checkCustomAttribute(k); return this.customString(k, vs); } /** * Add a list of {@link java.lang.String}-valued custom attributes. When set to one of the * * built-in user attribute keys, this custom attribute will be ignored. * * @param k the key for the list. When set to one of the built-in user attribute keys, this custom attribute will be ignored. * @param vs the values for the attribute * @return the builder */ public Builder customString(String k, List vs) { checkCustomAttribute(k); JsonArray array = new JsonArray(); for (String v : vs) { if (v != null) { array.add(new JsonPrimitive(v)); } } custom.put(k, array); return this; } /** * Add a list of {@link java.lang.Integer}-valued custom attributes. When set to one of the * * built-in user attribute keys, this custom attribute will be ignored. * * @param k the key for the list. When set to one of the built-in user attribute keys, this custom attribute will be ignored. * @param vs the values for the attribute * @return the builder */ public Builder customNumber(String k, List vs) { checkCustomAttribute(k); JsonArray array = new JsonArray(); for (Number v : vs) { if (v != null) { array.add(new JsonPrimitive(v)); } } custom.put(k, array); return this; } private void checkCustomAttribute(String key) { for (UserAttribute a : UserAttribute.values()) { if (a.name().equals(key)) { logger.warn("Built-in attribute key: " + key + " added as custom attribute! This custom attribute will be ignored during Feature Flag evaluation"); return; } } } /** * Build the configured {@link com.launchdarkly.client.LDUser} object * * @return the {@link com.launchdarkly.client.LDUser} configured by this builder */ public LDUser build() { return new LDUser(this); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy