/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.beam.sdk.transforms.display;

import static org.apache.beam.vendor.guava.v20_0.com.google.common.base.Preconditions.checkArgument;
import static org.apache.beam.vendor.guava.v20_0.com.google.common.base.Preconditions.checkNotNull;

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.auto.value.AutoValue;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nullable;
import org.apache.beam.sdk.options.ValueProvider;
import org.apache.beam.sdk.transforms.PTransform;
import org.apache.beam.vendor.guava.v20_0.com.google.common.base.Joiner;
import org.apache.beam.vendor.guava.v20_0.com.google.common.collect.ImmutableList;
import org.apache.beam.vendor.guava.v20_0.com.google.common.collect.ImmutableMap;
import org.apache.beam.vendor.guava.v20_0.com.google.common.collect.Maps;
import org.apache.beam.vendor.guava.v20_0.com.google.common.collect.Sets;
import org.joda.time.Duration;
import org.joda.time.Instant;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;

/**
 * Static display data associated with a pipeline component. Display data is useful for pipeline
 * runner UIs and diagnostic dashboards to display details about {@link PTransform PTransforms} that
 * make up a pipeline.
 *
 * <p>Components specify their display data by implementing the {@link HasDisplayData} interface.
 */
public class DisplayData implements Serializable {
  private static final DisplayData EMPTY = new DisplayData(Maps.newHashMap());
  private static final DateTimeFormatter TIMESTAMP_FORMATTER = ISODateTimeFormat.dateTime();

  private final ImmutableMap<Identifier, Item> entries;

  private DisplayData(Map<Identifier, Item> entries) {
    this.entries = ImmutableMap.copyOf(entries);
  }

  /** Default empty {@link DisplayData} instance. */
  public static DisplayData none() {
    return EMPTY;
  }

  /**
   * Collect the {@link DisplayData} from a component. This will traverse all subcomponents
   * specified via {@link Builder#include} in the given component. Data in this component will be in
   * a namespace derived from the component.
   */
  public static DisplayData from(HasDisplayData component) {
    checkNotNull(component, "component argument cannot be null");

    InternalBuilder builder = new InternalBuilder();
    builder.include(Path.root(), component);

    return builder.build();
  }

  /**
   * Infer the {@link Type} for the given object.
   *
   * <p>Use this method if the type of metadata is not known at compile time. For example:
   *
   * <pre>{@code @Override
   * public void populateDisplayData(DisplayData.Builder builder) {
   *   Optional<DisplayData.Type> type = DisplayData.inferType(foo);
   *   if (type.isPresent()) {
   *     builder.add(DisplayData.item("foo", type.get(), foo));
   *   }
   * }
   * }</pre>
   *
   * @return The inferred {@link Type}, or null if the type cannot be inferred,
   */
  @Nullable
  public static Type inferType(@Nullable Object value) {
    return Type.tryInferFrom(value);
  }

  @JsonValue
  public Collection<Item> items() {
    return entries.values();
  }

  public Map<Identifier, Item> asMap() {
    return entries;
  }

  @Override
  public int hashCode() {
    return entries.hashCode();
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof DisplayData) {
      DisplayData that = (DisplayData) obj;
      return Objects.equals(this.entries, that.entries);
    }

    return false;
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    boolean isFirstLine = true;
    for (Item entry : entries.values()) {
      if (isFirstLine) {
        isFirstLine = false;
      } else {
        builder.append("\n");
      }

      builder.append(entry);
    }

    return builder.toString();
  }

  /** Utility to build up display data from a component and its included subcomponents. */
  public interface Builder {
    /**
     * Register display data from the specified subcomponent at the given path. For example, a
     * {@link PTransform} which delegates to a user-provided function can implement {@link
     * HasDisplayData} on the function and include it from the {@link PTransform}:
     *
     * <pre>{@code @Override
     * public void populateDisplayData(DisplayData.Builder builder) {
     *   super.populateDisplayData(builder);
     *
     *   builder
     *     // To register the class name of the userFn
     *     .add(DisplayData.item("userFn", userFn.getClass()))
     *     // To allow the userFn to register additional display data
     *     .include("userFn", userFn);
     * }
     * }</pre>
     *
     * <p>Using {@code include(path, subcomponent)} will associate each of the registered items with
     * the namespace of the {@code subcomponent} being registered, with the specified path element
     * relative to the current path. To register display data in the current path and namespace,
     * such as from a base class implementation, use {@code
     * subcomponent.populateDisplayData(builder)} instead.
     *
     * @see HasDisplayData#populateDisplayData(DisplayData.Builder)
     */
    Builder include(String path, HasDisplayData subComponent);

    /**
     * Register display data from the specified component on behalf of the current component.
     * Display data items will be added with the subcomponent namespace but the current component
     * path.
     *
     * <p>This is useful for components which simply wrap other components and wish to retain the
     * display data from the wrapped component. Such components should implement {@code
     * populateDisplayData} as:
     *
     * <pre>{@code @Override
     * public void populateDisplayData(DisplayData.Builder builder) {
     *   builder.delegate(wrapped);
     * }
     * }</pre>
     */
    Builder delegate(HasDisplayData component);

    /** Register the given display item. */
    Builder add(ItemSpec<?> item);

    /** Register the given display item if the value is not null. */
    Builder addIfNotNull(ItemSpec<?> item);

    /** Register the given display item if the value is different than the specified default. */
    <T> Builder addIfNotDefault(ItemSpec<T> item, @Nullable T defaultValue);
  }

  /**
   * {@link Item Items} are the unit of display data. Each item is identified by a given path, key,
   * and namespace from the component the display item belongs to.
   *
   * <p>{@link Item Items} are registered via {@link DisplayData.Builder#add} within {@link
   * HasDisplayData#populateDisplayData} implementations.
   */
  @AutoValue
  public abstract static class Item implements Serializable {

    /** The path for the display item within a component hierarchy. */
    @Nullable
    @JsonIgnore
    public abstract Path getPath();

    /**
     * The namespace for the display item. The namespace defaults to the component which the display
     * item belongs to.
     */
    @Nullable
    @JsonGetter("namespace")
    public abstract Class<?> getNamespace();

    /**
     * The key for the display item. Each display item is created with a key and value via {@link
     * DisplayData#item}.
     */
    @JsonGetter("key")
    public abstract String getKey();

    /**
     * Retrieve the {@link DisplayData.Type} of display data. All metadata conforms to a predefined
     * set of allowed types.
     */
    @JsonGetter("type")
    public abstract Type getType();

    /**
     * Retrieve the value of the display item. The value is translated from the input to {@link
     * DisplayData#item} into a format suitable for display. Translation is based on the item's
     * {@link #getType() type}.
     */
    @JsonGetter("value")
    public abstract Object getValue();

    /**
     * Return the optional short value for an item, or null if none is provided.
     *
     * <p>The short value is an alternative display representation for items having a long display
     * value. For example, the {@link #getValue() value} for {@link Type#JAVA_CLASS} items contains
     * the full class name with package, while the short value contains just the class name.
     *
     * <p>A {@link #getValue() value} will be provided for each display item, and some types may
     * also provide a short-value. If a short value is provided, display data consumers may choose
     * to display it instead of or in addition to the {@link #getValue() value}.
     */
    @JsonGetter("shortValue")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @Nullable
    public abstract Object getShortValue();

    /**
     * Retrieve the optional label for an item. The label is a human-readable description of what
     * the metadata represents. UIs may choose to display the label instead of the item key.
     *
     * <p>If no label was specified, this will return {@code null}.
     */
    @JsonGetter("label")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @Nullable
    public abstract String getLabel();

    /**
     * Retrieve the optional link URL for an item. The URL points to an address where the reader can
     * find additional context for the display data.
     *
     * <p>If no URL was specified, this will return {@code null}.
     */
    @JsonGetter("linkUrl")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @Nullable
    public abstract String getLinkUrl();

    private static Item create(ItemSpec<?> spec, Path path) {
      checkNotNull(spec, "spec cannot be null");
      checkNotNull(path, "path cannot be null");
      Class<?> ns = checkNotNull(spec.getNamespace(), "namespace must be set");

      return new AutoValue_DisplayData_Item(
          path,
          ns,
          spec.getKey(),
          spec.getType(),
          spec.getValue(),
          spec.getShortValue(),
          spec.getLabel(),
          spec.getLinkUrl());
    }

    @Override
    public String toString() {
      return String.format("%s%s:%s=%s", getPath(), getNamespace().getName(), getKey(), getValue());
    }
  }

  /**
   * Specifies an {@link Item} to register as display data. Each item is identified by a given path,
   * key, and namespace from the component the display item belongs to.
   *
   * <p>{@link Item Items} are registered via {@link DisplayData.Builder#add} within {@link
   * HasDisplayData#populateDisplayData} implementations.
   */
  @AutoValue
  public abstract static class ItemSpec<T> implements Serializable {
    /**
     * The namespace for the display item. If unset, defaults to the component which the display
     * item is registered to.
     */
    @Nullable
    public abstract Class<?> getNamespace();

    /**
     * The key for the display item. Each display item is created with a key and value via {@link
     * DisplayData#item}.
     */
    public abstract String getKey();

    /**
     * The {@link DisplayData.Type} of display data. All display data conforms to a predefined set
     * of allowed types.
     */
    public abstract Type getType();

    /**
     * The value of the display item. The value is translated from the input to {@link
     * DisplayData#item} into a format suitable for display. Translation is based on the item's
     * {@link #getType() type}.
     */
    @Nullable
    public abstract Object getValue();

    /**
     * The optional short value for an item, or {@code null} if none is provided.
     *
     * <p>The short value is an alternative display representation for items having a long display
     * value. For example, the {@link #getValue() value} for {@link Type#JAVA_CLASS} items contains
     * the full class name with package, while the short value contains just the class name.
     *
     * <p>A {@link #getValue() value} will be provided for each display item, and some types may
     * also provide a short-value. If a short value is provided, display data consumers may choose
     * to display it instead of or in addition to the {@link #getValue() value}.
     */
    @Nullable
    public abstract Object getShortValue();

    /**
     * The optional label for an item. The label is a human-readable description of what the
     * metadata represents. UIs may choose to display the label instead of the item key.
     */
    @Nullable
    public abstract String getLabel();

    /**
     * The optional link URL for an item. The URL points to an address where the reader can find
     * additional context for the display data.
     */
    @Nullable
    public abstract String getLinkUrl();

    private static <T> ItemSpec<T> create(String key, Type type, @Nullable T value) {
      return ItemSpec.<T>builder().setKey(key).setType(type).setRawValue(value).build();
    }

    /**
     * Set the item {@link ItemSpec#getNamespace() namespace} from the given {@link Class}.
     *
     * <p>This method does not alter the current instance, but instead returns a new {@link
     * ItemSpec} with the namespace set.
     */
    public ItemSpec<T> withNamespace(Class<?> namespace) {
      checkNotNull(namespace, "namespace argument cannot be null");
      return toBuilder().setNamespace(namespace).build();
    }

    /**
     * Set the item {@link Item#getLabel() label}.
     *
     * <p>Specifying a null value will clear the label if it was previously defined.
     *
     * <p>This method does not alter the current instance, but instead returns a new {@link
     * ItemSpec} with the label set.
     */
    public ItemSpec<T> withLabel(@Nullable String label) {
      return toBuilder().setLabel(label).build();
    }

    /**
     * Set the item {@link Item#getLinkUrl() link url}.
     *
     * <p>Specifying a null value will clear the link url if it was previously defined.
     *
     * <p>This method does not alter the current instance, but instead returns a new {@link
     * ItemSpec} with the link url set.
     */
    public ItemSpec<T> withLinkUrl(@Nullable String url) {
      return toBuilder().setLinkUrl(url).build();
    }

    /**
     * Creates a similar item to the current instance but with the specified value.
     *
     * <p>This should only be used internally. It is useful to compare the value of a {@link
     * DisplayData.Item} to the value derived from a specified input.
     */
    private ItemSpec<T> withValue(T value) {
      return toBuilder().setRawValue(value).build();
    }

    @Override
    public String toString() {
      return String.format("%s:%s=%s", getNamespace(), getKey(), getValue());
    }

    static <T> ItemSpec.Builder<T> builder() {
      return new AutoValue_DisplayData_ItemSpec.Builder<>();
    }

    abstract ItemSpec.Builder<T> toBuilder();

    @AutoValue.Builder
    abstract static class Builder<T> {
      public abstract ItemSpec.Builder<T> setKey(String key);

      public abstract ItemSpec.Builder<T> setNamespace(@Nullable Class<?> namespace);

      public abstract ItemSpec.Builder<T> setType(Type type);

      public abstract ItemSpec.Builder<T> setValue(@Nullable Object longValue);

      public abstract ItemSpec.Builder<T> setShortValue(@Nullable Object shortValue);

      public abstract ItemSpec.Builder<T> setLabel(@Nullable String label);

      public abstract ItemSpec.Builder<T> setLinkUrl(@Nullable String url);

      public abstract ItemSpec<T> build();

      abstract Type getType();

      ItemSpec.Builder<T> setRawValue(@Nullable T value) {
        FormattedItemValue formatted = getType().safeFormat(value);
        return this.setValue(formatted.getLongValue()).setShortValue(formatted.getShortValue());
      }
    }
  }

  /**
   * Unique identifier for a display data item within a component.
   *
   * <p>Identifiers are composed of:
   *
   * <ul>
   *   <li>A {@link #getPath() path} based on the component hierarchy
   *   <li>The {@link #getKey() key} it is registered with
   *   <li>A {@link #getNamespace() namespace} generated from the class of the component which
   *       registered the item.
   * </ul>
   *
   * <p>Display data registered with the same key from different components will have different
   * namespaces and thus will both be represented in the composed {@link DisplayData}. If a single
   * component registers multiple metadata items with the same key, only the most recent item will
   * be retained; previous versions are discarded.
   */
  @AutoValue
  public abstract static class Identifier implements Serializable {
    public abstract Path getPath();

    public abstract Class<?> getNamespace();

    public abstract String getKey();

    public static Identifier of(Path path, Class<?> namespace, String key) {
      return new AutoValue_DisplayData_Identifier(path, namespace, key);
    }

    @Override
    public String toString() {
      return String.format("%s%s:%s", getPath(), getNamespace(), getKey());
    }
  }

  /**
   * Structured path of registered display data within a component hierarchy.
   *
   * <p>Display data items registered directly by a component will have the {@link Path#root() root}
   * path. If the component {@link Builder#include includes} a sub-component, its display data will
   * be registered at the path specified. Each sub-component path is created by appending a child
   * element to the path of its parent component, forming a hierarchy.
   */
  public static class Path implements Serializable {
    private final ImmutableList<String> components;

    private Path(ImmutableList<String> components) {
      this.components = components;
    }

    /** Path for display data registered by a top-level component. */
    public static Path root() {
      return new Path(ImmutableList.of());
    }

    /**
     * Construct a path from an absolute component path hierarchy.
     *
     * <p>For the root path, use {@link Path#root()}.
     *
     * @param firstPath Path of the first sub-component.
     * @param paths Additional path components.
     */
    public static Path absolute(String firstPath, String... paths) {
      ImmutableList.Builder<String> builder = ImmutableList.builder();

      validatePathElement(firstPath);
      builder.add(firstPath);
      for (String path : paths) {
        validatePathElement(path);
        builder.add(path);
      }

      return new Path(builder.build());
    }

    /**
     * Hierarchy list of component paths making up the full path, starting with the top-level child
     * component path. For the {@link #root root} path, returns the empty list.
     */
    public List<String> getComponents() {
      return components;
    }

    /**
     * Extend the path by appending a sub-component path. The new path element is added to the end
     * of the path hierarchy.
     *
     * <p>Returns a new {@link Path} instance; the originating {@link Path} is not modified.
     */
    public Path extend(String path) {
      validatePathElement(path);
      return new Path(
          ImmutableList.<String>builder().addAll(components.iterator()).add(path).build());
    }

    private static void validatePathElement(String path) {
      checkNotNull(path);
      checkArgument(!"".equals(path), "path cannot be empty");
    }

    @Override
    public String toString() {
      StringBuilder b = new StringBuilder().append("[");
      Joiner.on("/").appendTo(b, components);
      b.append("]");
      return b.toString();
    }

    @Override
    public boolean equals(Object obj) {
      return obj instanceof Path && Objects.equals(components, ((Path) obj).components);
    }

    @Override
    public int hashCode() {
      return components.hashCode();
    }
  }

  /** Display data type. */
  public enum Type {
    STRING {
      @Override
      FormattedItemValue format(Object value) {
        return new FormattedItemValue(checkType(value, String.class, STRING));
      }
    },
    INTEGER {
      @Override
      FormattedItemValue format(Object value) {
        if (value instanceof Integer) {
          long l = ((Integer) value).longValue();
          return format(l);
        }

        return new FormattedItemValue(checkType(value, Long.class, INTEGER));
      }
    },
    FLOAT {
      @Override
      FormattedItemValue format(Object value) {
        return new FormattedItemValue(checkType(value, Number.class, FLOAT));
      }
    },
    BOOLEAN() {
      @Override
      FormattedItemValue format(Object value) {
        return new FormattedItemValue(checkType(value, Boolean.class, BOOLEAN));
      }
    },
    TIMESTAMP() {
      @Override
      FormattedItemValue format(Object value) {
        Instant instant = checkType(value, Instant.class, TIMESTAMP);
        return new FormattedItemValue(TIMESTAMP_FORMATTER.print(instant));
      }
    },
    DURATION {
      @Override
      FormattedItemValue format(Object value) {
        Duration duration = checkType(value, Duration.class, DURATION);
        return new FormattedItemValue(duration.getMillis());
      }
    },
    JAVA_CLASS {
      @Override
      FormattedItemValue format(Object value) {
        Class<?> clazz = checkType(value, Class.class, JAVA_CLASS);
        return new FormattedItemValue(clazz.getName(), clazz.getSimpleName());
      }
    };

    private static <T> T checkType(Object value, Class<T> clazz, DisplayData.Type expectedType) {
      if (!clazz.isAssignableFrom(value.getClass())) {
        throw new ClassCastException(
            String.format("Value is not valid for DisplayData type %s: %s", expectedType, value));
      }

      @SuppressWarnings("unchecked") // type checked above.
      T typedValue = (T) value;
      return typedValue;
    }

    /**
     * Format the display data value into a long string representation, and optionally a shorter
     * representation for display.
     *
     * <p>Internal-only. Value objects can be safely cast to the expected Java type.
     */
    abstract FormattedItemValue format(Object value);

    /**
     * Safe version of {@link Type#format(Object)}, which checks for null input value and if so
     * returns a {@link FormattedItemValue} with null value properties.
     *
     * @see #format(Object)
     */
    FormattedItemValue safeFormat(@Nullable Object value) {
      if (value == null) {
        return FormattedItemValue.NULL_VALUES;
      }

      return format(value);
    }

    @Nullable
    private static Type tryInferFrom(@Nullable Object value) {
      if (value instanceof Integer || value instanceof Long) {
        return INTEGER;
      } else if (value instanceof Double || value instanceof Float) {
        return FLOAT;
      } else if (value instanceof Boolean) {
        return BOOLEAN;
      } else if (value instanceof Instant) {
        return TIMESTAMP;
      } else if (value instanceof Duration) {
        return DURATION;
      } else if (value instanceof Class<?>) {
        return JAVA_CLASS;
      } else if (value instanceof String) {
        return STRING;
      } else {
        return null;
      }
    }
  }

  static class FormattedItemValue {
    /** Default instance which contains null values. */
    private static final FormattedItemValue NULL_VALUES = new FormattedItemValue(null);

    @Nullable private final Object shortValue;
    @Nullable private final Object longValue;

    private FormattedItemValue(@Nullable Object longValue) {
      this(longValue, null);
    }

    private FormattedItemValue(@Nullable Object longValue, @Nullable Object shortValue) {
      this.longValue = longValue;
      this.shortValue = shortValue;
    }

    Object getLongValue() {
      return this.longValue;
    }

    Object getShortValue() {
      return this.shortValue;
    }
  }

  private static class InternalBuilder implements Builder {
    private final Map<Identifier, Item> entries;
    private final Set<HasDisplayData> visitedComponents;
    private final Map<Path, HasDisplayData> visitedPathMap;

    @Nullable private Path latestPath;
    @Nullable private Class<?> latestNs;

    private InternalBuilder() {
      this.entries = Maps.newHashMap();
      this.visitedComponents = Sets.newIdentityHashSet();
      this.visitedPathMap = Maps.newHashMap();
    }

    @Override
    public Builder include(String path, HasDisplayData subComponent) {
      checkNotNull(subComponent, "subComponent argument cannot be null");
      checkNotNull(path, "path argument cannot be null");

      Path absolutePath = latestPath.extend(path);

      HasDisplayData existingComponent = visitedPathMap.get(absolutePath);
      if (existingComponent != null) {
        throw new IllegalArgumentException(
            String.format(
                "Specified path '%s' already used for "
                    + "subcomponent %s. Subcomponents must be included using unique paths.",
                path, existingComponent));
      }

      return include(absolutePath, subComponent);
    }

    @Override
    public Builder delegate(HasDisplayData component) {
      checkNotNull(component);

      return include(latestPath, component);
    }

    private Builder include(Path path, HasDisplayData subComponent) {
      if (visitedComponents.contains(subComponent)) {
        // Component previously registered; ignore in order to break cyclic dependencies
        return this;
      }

      // New component; add it.
      visitedComponents.add(subComponent);
      visitedPathMap.put(path, subComponent);
      Class<?> namespace = subComponent.getClass();
      // Common case: AutoValue classes such as AutoValue_FooIO_Read. It's more useful
      // to show the user the FooIO.Read class, which is the direct superclass of the AutoValue
      // generated class.
      if (namespace.getSimpleName().startsWith("AutoValue_")) {
        namespace = namespace.getSuperclass();
      }
      if (namespace.isSynthetic() && namespace.getSimpleName().contains("$$Lambda")) {
        try {
          namespace =
              Class.forName(namespace.getCanonicalName().replaceFirst("\\$\\$Lambda.*", ""));
        } catch (Exception e) {
          throw new PopulateDisplayDataException(
              "Failed to get the enclosing class of lambda " + subComponent, e);
        }
      }

      Path prevPath = latestPath;
      Class<?> prevNs = latestNs;
      latestPath = path;
      latestNs = namespace;

      try {
        subComponent.populateDisplayData(this);
      } catch (PopulateDisplayDataException e) {
        // Don't re-wrap exceptions recursively.
        throw e;
      } catch (Throwable e) {
        String msg =
            String.format(
                "Error while populating display data for component '%s': %s",
                namespace.getName(), e.getMessage());
        throw new PopulateDisplayDataException(msg, e);
      }

      latestPath = prevPath;
      latestNs = prevNs;

      return this;
    }

    /** Marker exception class for exceptions encountered while populating display data. */
    private static class PopulateDisplayDataException extends RuntimeException {
      PopulateDisplayDataException(String message, Throwable cause) {
        super(message, cause);
      }
    }

    @Override
    public Builder add(ItemSpec<?> item) {
      checkNotNull(item, "Input display item cannot be null");
      return addItemIf(true, item);
    }

    @Override
    public Builder addIfNotNull(ItemSpec<?> item) {
      checkNotNull(item, "Input display item cannot be null");
      return addItemIf(item.getValue() != null, item);
    }

    @Override
    public <T> Builder addIfNotDefault(ItemSpec<T> item, @Nullable T defaultValue) {
      checkNotNull(item, "Input display item cannot be null");
      ItemSpec<T> defaultItem = item.withValue(defaultValue);
      return addItemIf(!Objects.equals(item, defaultItem), item);
    }

    private Builder addItemIf(boolean condition, ItemSpec<?> spec) {
      if (!condition) {
        return this;
      }

      checkNotNull(spec, "Input display item cannot be null");
      checkNotNull(spec.getValue(), "Input display value cannot be null");

      if (spec.getNamespace() == null) {
        spec = spec.withNamespace(latestNs);
      }
      Item item = Item.create(spec, latestPath);

      Identifier id = Identifier.of(item.getPath(), item.getNamespace(), item.getKey());
      checkArgument(
          !entries.containsKey(id),
          "Display data key (%s) is not unique within the specified path and namespace: %s%s.",
          item.getKey(),
          item.getPath(),
          item.getNamespace());

      entries.put(id, item);
      return this;
    }

    private DisplayData build() {
      return new DisplayData(this.entries);
    }
  }

  /** Create a display item for the specified key and string value. */
  public static ItemSpec<String> item(String key, @Nullable String value) {
    return item(key, Type.STRING, value);
  }

  /** Create a display item for the specified key and {@link ValueProvider}. */
  public static ItemSpec<?> item(String key, @Nullable ValueProvider<?> value) {
    if (value == null) {
      return item(key, Type.STRING, null);
    }
    if (value.isAccessible()) {
      Object got = value.get();
      if (got == null) {
        return item(key, Type.STRING, null);
      }
      Type type = inferType(got);
      if (type != null) {
        return item(key, type, got);
      }
    }
    // General case: not null and type not inferable. Fall back to toString of the VP itself.
    return item(key, Type.STRING, String.valueOf(value));
  }

  /** Create a display item for the specified key and integer value. */
  public static ItemSpec<Integer> item(String key, @Nullable Integer value) {
    return item(key, Type.INTEGER, value);
  }

  /** Create a display item for the specified key and integer value. */
  public static ItemSpec<Long> item(String key, @Nullable Long value) {
    return item(key, Type.INTEGER, value);
  }

  /** Create a display item for the specified key and floating point value. */
  public static ItemSpec<Float> item(String key, @Nullable Float value) {
    return item(key, Type.FLOAT, value);
  }

  /** Create a display item for the specified key and floating point value. */
  public static ItemSpec<Double> item(String key, @Nullable Double value) {
    return item(key, Type.FLOAT, value);
  }

  /** Create a display item for the specified key and boolean value. */
  public static ItemSpec<Boolean> item(String key, @Nullable Boolean value) {
    return item(key, Type.BOOLEAN, value);
  }

  /** Create a display item for the specified key and timestamp value. */
  public static ItemSpec<Instant> item(String key, @Nullable Instant value) {
    return item(key, Type.TIMESTAMP, value);
  }

  /** Create a display item for the specified key and duration value. */
  public static ItemSpec<Duration> item(String key, @Nullable Duration value) {
    return item(key, Type.DURATION, value);
  }

  /** Create a display item for the specified key and class value. */
  public static <T> ItemSpec<Class<T>> item(String key, @Nullable Class<T> value) {
    return item(key, Type.JAVA_CLASS, value);
  }

  /**
   * Create a display item for the specified key, type, and value. This method should be used if the
   * type of the input value can only be determined at runtime. Otherwise, {@link HasDisplayData}
   * implementors should call one of the typed factory methods, such as {@link #item(String,
   * String)} or {@link #item(String, Integer)}.
   *
   * @throws ClassCastException if the value cannot be formatted as the given type.
   * @see Type#inferType(Object)
   */
  public static <T> ItemSpec<T> item(String key, Type type, @Nullable T value) {
    checkNotNull(key, "key argument cannot be null");
    checkNotNull(type, "type argument cannot be null");

    return ItemSpec.create(key, type, value);
  }
}
