Class LDContext

java.lang.Object
com.launchdarkly.sdk.LDContext
All Implemented Interfaces:
JsonSerializable

public final class LDContext extends Object implements JsonSerializable
A collection of attributes that can be referenced in flag evaluations and analytics events.

LDContext is the newer replacement for the previous, less flexible LDUser type. The current SDK still supports LDUser, but LDContext is now the preferred model and may entirely replace LDUser in the future.

To create an LDContext of a single kind, such as a user, you may use create(String) or create(ContextKind, String) when only the key matters; or, to specify other attributes, use builder(String).

To create an LDContext with multiple kinds, use createMulti(LDContext...) or multiBuilder().

An LDContext can be in an error state if it was built with invalid attributes. See isValid() and getError().

LaunchDarkly defines a standard JSON encoding for contexts, used by the JavaScript SDK and also in analytics events. LDContext can be converted to and from JSON in any of these ways:

  1. With JsonSerialization.
  2. With Gson, if and only if you configure your Gson instance with LDGson.
  3. With Jackson, if and only if you configure your ObjectMapper instance with LDJackson.

To learn more about contexts, read the documentation.

  • Method Details

    • create

      public static LDContext create(String key)
      Creates a single-kind LDContext with a kind of ContextKind.DEFAULT} and the specified key.

      To specify additional properties, use builder(String). To create a multi-kind LDContext, use createMulti(LDContext...) or multiBuilder(). To create a single-kind LDContext of a different kind than "user", use create(ContextKind, String).

      Parameters:
      key - the context key
      Returns:
      an LDContext
      See Also:
    • create

      public static LDContext create(ContextKind kind, String key)
      Creates a single-kind LDContext with only the kind and keys specified.

      To specify additional properties, use builder(ContextKind, String). To create a multi-kind LDContext, use createMulti(LDContext...) or multiBuilder().

      Parameters:
      kind - the context kind; if null, ContextKind.DEFAULT will be used
      key - the context key
      Returns:
      an LDContext
      See Also:
    • createMulti

      public static LDContext createMulti(LDContext... contexts)
      Creates a multi-kind LDContext out of the specified single-kind LDContexts.

      To create a single-kind Context, use create(String), create(ContextKind, String), or builder(String).

      For the returned LDContext to be valid, the contexts list must not be empty, and all of its elements must be valid LDContexts. Otherwise, the returned LDContext will be invalid as reported by getError().

      If only one context parameter is given, the method returns that same context.

      If the nested context is multi-kind, this is exactly equivalent to adding each of the individual kinds from it separately. For instance, in the following example, "multi1" and "multi2" end up being exactly the same:

      
           LDContext c1 = LDContext.create(ContextKind.of("kind1"), "key1");
           LDContext c2 = LDContext.create(ContextKind.of("kind2"), "key2");
           LDContext c3 = LDContext.create(ContextKind.of("kind3"), "key3");
      
           LDContext multi1 = LDContext.createMulti(c1, c2, c3);
      
           LDContext c1plus2 = LDContext.createMulti(c1, c2);
           LDContext multi2 = LDContext.createMulti(c1plus2, c3);
       
      Parameters:
      contexts - a list of contexts
      Returns:
      an LDContext
      See Also:
    • fromUser

      @Deprecated public static LDContext fromUser(LDUser user)
      Deprecated.
      use LDContext directly instead.
      Converts a user to an equivalent LDContext instance.

      This method is used by the SDK whenever an application passes a LDUser instance to methods such as identify. The SDK operates internally on the LDContext model, which is more flexible than the older LDUser model: an L User can always be converted to an LDContext, but not vice versa. The ContextKind of the resulting Context is ContextKind.DEFAULT ("user").

      Because there is some overhead to this conversion, it is more efficient for applications to construct an LDContext and pass that to the SDK, rather than an LDUser. This is also recommended because the LDUser type may be removed in a future version of the SDK.

      If the user parameter is null, or if the user has a null key, the method returns an LDContext in an invalid state (see isValid()).

      Parameters:
      user - an LDUser object
      Returns:
      an LDContext with the same attributes as the LDUser
    • builder

      public static ContextBuilder builder(String key)
      Creates a ContextBuilder for building an LDContext, initializing its key and setting kind to ContextKind.DEFAULT.

      You may use ContextBuilder methods to set additional attributes and/or change the ContextBuilder.kind(ContextKind) before calling ContextBuilder.build(). If you do not change any values, the defaults for the LDContext are that its kind is ContextKind.DEFAULT ("user"), its key is set to the key parameter passed here, anonymous is false, and it has no values for any other attributes.

      This method is for building an LDContext that has only a single Kind. To define a multi-kind LDContext, use multiBuilder().

      if key is an empty string, there is no default. An LDContext must have a non-empty key, so if you call ContextBuilder.build() in this state without using ContextBuilder.key(String) to set the key, you will get an invalid LDContext.

      Parameters:
      key - the context key
      Returns:
      a builder
      See Also:
    • builder

      public static ContextBuilder builder(ContextKind kind, String key)
      Creates a ContextBuilder for building an LDContext, initializing its key and kind.

      You may use ContextBuilder methods to set additional attributes and/or change the ContextBuilder.kind(ContextKind) before calling ContextBuilder.build(). If you do not change any values, the defaults for the LDContext are that its kind and key is set to the parameters passed here, anonymous is false, and it has no values for any other attributes.

      This method is for building an LDContext that has only a single Kind. To define a multi-kind LDContext, use multiBuilder().

      if key is an empty string, there is no default. An LDContext must have a non-empty key, so if you call ContextBuilder.build() in this state without using ContextBuilder.key(String) to set the key, you will get an invalid LDContext.

      Parameters:
      kind - the context kind; if null, ContextKind.DEFAULT is used
      key - the context key
      Returns:
      a builder
      See Also:
    • builderFromContext

      public static ContextBuilder builderFromContext(LDContext context)
      Creates a builder whose properties are the same as an existing single-kind LDContext.

      You may then change the builder's state in any way and call ContextBuilder.build() to create a new independent LDContext.

      Parameters:
      context - the context to copy from
      Returns:
      a builder
      See Also:
    • multiBuilder

      public static ContextMultiBuilder multiBuilder()
      Creates a ContextMultiBuilder for building a multi-kind context.

      This method is for building a Context that has multiple ContextKind values, each with its own nested LDContext. To define a single-kind context, use builder(String) instead.

      Returns:
      a builder
      See Also:
    • isValid

      public boolean isValid()
      Returns true for a valid LDContext, false for an invalid one.

      A valid context is one that can be used in SDK operations. An invalid context is one that is missing necessary attributes or has invalid attributes, indicating an incorrect usage of the SDK API. The only ways for a context to be invalid are:

      • It has a disallowed value for the kind property. See ContextKind.
      • It is a single-kind context whose key is empty.
      • It is a multi-kind context that does not have any kinds. See createMulti(LDContext...).
      • It is a multi-kind context where the same kind appears more than once.
      • It is a multi-kind context where at least one of the nested LDContexts has an error.
      • It was created with fromUser(LDUser) from a null LDUser reference, or from an LDUser that had a null key.

      In any of these cases, isValid() will return false, and getError() will return a description of the error.

      Since in normal usage it is easy for applications to be sure they are using context kinds correctly, and because throwing an exception is undesirable in application code that uses LaunchDarkly, the SDK stores the error state in the LDContext itself and checks for such errors at the time the Context is used, such as in a flag evaluation. At that point, if the context is invalid, the operation will fail in some well-defined way as described in the documentation for that method, and the SDK will generally log a warning as well. But in any situation where you are not sure if you have a valid LDContext, you can check isValid() or getError().

      Returns:
      true if the context is valid
      See Also:
    • getError

      public String getError()
      Returns null for a valid LDContext, or an error message for an invalid one.

      If this is null, then isValid() is true. If it is non-null, then isValid() is false.

      Returns:
      an error description or null
      See Also:
    • getKind

      public ContextKind getKind()
      Returns the context's kind attribute.

      Every valid context has a non-empty ContextKind. For multi-kind contexts, this value is ContextKind.MULTI and the kinds within the context can be inspected with getIndividualContext(int) or getIndividualContext(String).

      Returns:
      the context kind
      See Also:
    • isMultiple

      public boolean isMultiple()
      Returns true if this is a multi-kind context.

      If this value is true, then getKind() is guaranteed to be ContextKind.MULTI, and you can inspect the individual contexts for each kind with getIndividualContext(int) or getIndividualContext(ContextKind).

      If this value is false, then getKind() is guaranteed to return a value that is not ContextKind.MULTI.

      Returns:
      true for a multi-kind context, false for a single-kind context
    • getKey

      public String getKey()
      Returns the context's key attribute.

      For a single-kind context, this value is set by one of the LDContext factory methods or builders (create(String), create(ContextKind, String), builder(String), builder(ContextKind, String)).

      For a multi-kind context, there is no single value and getKey() returns an empty string. Use getIndividualContext(int) or getIndividualContext(String) to inspect the LDContext for a particular kind, then call getKey() on it.

      This value is never null.

      Returns:
      the context key
      See Also:
    • getName

      public String getName()
      Returns the context's name attribute.

      For a single-kind context, this value is set by ContextBuilder.name(String). It is null if no value was set.

      For a multi-kind context, there is no single value and getName() returns null. Use getIndividualContext(int) or getIndividualContext(String) to inspect the LDContext for a particular kind, then call getName() on it.

      Returns:
      the context name or null
      See Also:
    • isAnonymous

      public boolean isAnonymous()
      Returns true if this context is only intended for flag evaluations and will not be indexed by LaunchDarkly.

      The default value is false. False means that this LDContext represents an entity such as a user that you want to be able to see on the LaunchDarkly dashboard.

      Setting anonymous to true excludes this context from the database that is used by the dashboard. It does not exclude it from analytics event data, so it is not the same as making attributes private; all non-private attributes will still be included in events and data export. There is no limitation on what other attributes may be included (so, for instance, anonymous does not mean there is no name), and the context will still have whatever key you have given it.

      This value is also addressable in evaluations as the attribute name "anonymous". It is always treated as a boolean true or false in evaluations.

      Returns:
      true if the context should be excluded from the LaunchDarkly database
      See Also:
    • getValue

      public LDValue getValue(String attributeName)
      Looks up the value of any attribute of the context by name.

      This includes only attributes that are addressable in evaluations-- not metadata such as getPrivateAttribute(int).

      For a single-kind context, the attribute name can be any custom attribute that was set by methods like ContextBuilder.set(String, boolean). It can also be one of the built-in ones like "kind", "key", or "name"; in such cases, it is equivalent to getKind(), getKey(), or getName(), except that the value is returned using the general-purpose LDValue type.

      For a multi-kind context, the only supported attribute name is "kind". Use getIndividualContext(int) or getIndividualContext(ContextKind) to inspect the LDContext for a particular kind and then get its attributes.

      This method does not support complex expressions for getting individual values out of JSON objects or arrays, such as "/address/street". Use getValue(AttributeRef) with an AttributeRef for that purpose.

      If the value is found, the return value is the attribute value, using the type LDValue to represent a value of any JSON type.

      If there is no such attribute, the return value is LDValue.ofNull() (the method never returns a Java null). An attribute that actually exists cannot have a null value.

      Parameters:
      attributeName - the desired attribute name
      Returns:
      the value or LDValue.ofNull()
      See Also:
    • getValue

      public LDValue getValue(AttributeRef attributeRef)
      Looks up the value of any attribute of the context, or a value contained within an attribute, based on an AttributeRef.

      This includes only attributes that are addressable in evaluations-- not metadata such as getPrivateAttribute(int).

      This implements the same behavior that the SDK uses to resolve attribute references during a flag evaluation. In a single-kind context, the AttributeRef can represent a simple attribute name-- either a built-in one like "name" or "key", or a custom attribute that was set by methods like ContextBuilder.set(String, String)-- or, it can be a slash-delimited path using a JSON-Pointer-like syntax. See AttributeRef for more details.

      For a multi-kind context, the only supported attribute name is "kind". Use getIndividualContext(int) or getIndividualContext(ContextKind) to inspect the LDContext for a particular kind and then get its attributes.

      This method does not support complex expressions for getting individual values out of JSON objects or arrays, such as "/address/street". Use getValue(AttributeRef) with an AttributeRef for that purpose.

      If the value is found, the return value is the attribute value, using the type LDValue to represent a value of any JSON type.

      If there is no such attribute, the return value is LDValue.ofNull() (the method never returns a Java null). An attribute that actually exists cannot have a null value.

      Parameters:
      attributeRef - an attribute reference
      Returns:
      the attribute value
    • getCustomAttributeNames

      public Iterable<String> getCustomAttributeNames()
      Returns the names of all non-built-in attributes that have been set in this context.

      For a single-kind context, this includes all the names that were passed to any of the overloads of ContextBuilder.set(String, LDValue) as long as the values were not null (since a null value in LaunchDarkly is equivalent to the attribute not being set).

      For a multi-kind context, there are no such names.

      Returns:
      an iterable of strings (may be empty, but will never be null)
    • getIndividualContextCount

      public int getIndividualContextCount()
      Returns the number of context kinds in this context.

      For a valid single-kind context, this returns 1. For a multi-kind context, it returns the number of kinds that were added with createMulti(LDContext...) or multiBuilder(). For an invalid context, it returns zero.

      Returns:
      the number of context kinds
    • getIndividualContext

      public LDContext getIndividualContext(int index)
      Returns the single-kind LDContext corresponding to one of the kinds in this context.

      If this method is called on a single-kind LDContext, then the only allowable value for index is zero, and the return value on success is the same LDContext. If the method is called on a multi-kind context, then index must be non-negative and less than the number of kinds (that is, less than the return value of getIndividualContextCount()), and the return value on success is one of the individual LDContexts within.

      Parameters:
      index - the zero-based index of the context to get
      Returns:
      an LDContext, or null if the index was out of range
    • getIndividualContext

      public LDContext getIndividualContext(ContextKind kind)
      Returns the single-kind LDContext corresponding to one of the kinds in this context.

      If this method is called on a single-kind LDContext, then the only allowable value for kind is the same as getKind(), and the return value on success is the same LDContext. If the method is called on a multi-kind context, then kind should be match the kind of one of the contexts that was added with createMulti(LDContext...) or multiBuilder(), and the return value on success is the corresponding individual LDContext within.

      Parameters:
      kind - the context kind to get; if null, defaults to ContextKind.DEFAULT
      Returns:
      an LDContext, or null if that kind was not found
    • getIndividualContext

      public LDContext getIndividualContext(String kind)
      Same as getIndividualContext(ContextKind), but specifies the kind as a plain string.
      Parameters:
      kind - the context kind to get
      Returns:
      an LDContext, or null if that kind was not found
    • getPrivateAttributeCount

      public int getPrivateAttributeCount()
      Returns the number of private attribute references that were specified for this context.

      This is equal to the total number of values passed to ContextBuilder.privateAttributes(String...) and/or its overload ContextBuilder.privateAttributes(AttributeRef...).

      Returns:
      the number of private attribute references
    • getPrivateAttribute

      public AttributeRef getPrivateAttribute(int index)
      Retrieves one of the private attribute references that were specified for this context.
      Parameters:
      index - a non-negative index that must be less than getPrivateAttributeCount()
      Returns:
      an AttributeRef, or null if the index was out of range
    • getFullyQualifiedKey

      public String getFullyQualifiedKey()
      Returns a string that describes the LDContext uniquely based on kind and key values.

      This value is used whenever LaunchDarkly needs a string identifier based on all of the kind and key values in the context; the SDK may use this for caching previously seen contexts, for instance.

      Returns:
      the fully-qualified key
    • toString

      public String toString()
      Returns a string representation of the context.

      For a valid context, this is currently defined as being the same as the JSON representation, since that is the simplest way to represent all of the LDContext properties. However, application code should not rely on toString() always being the same as the JSON representation. If you specifically want the latter, use JsonSerialization.serialize(JsonSerializable).

      For an invalid context, toString() returns a description of why it is invalid.

      Overrides:
      toString in class Object
    • equals

      public boolean equals(Object other)
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object