+ *
+ * @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);
+ }
+
public Collection items() {
return entries.values();
}
@@ -101,6 +125,10 @@ public String toString() {
return builder.toString();
}
+ private static String namespaceOf(Class> clazz) {
+ return clazz.getName();
+ }
+
/**
* Utility to build up display metadata from a component and its included
* subcomponents.
@@ -126,6 +154,20 @@ public interface Builder {
*/
ItemBuilder add(String key, String value);
+ /**
+ * Register the given string display data if the value is not null.
+ *
+ * @see DisplayData.Builder#add(String, String)
+ */
+ ItemBuilder addIfNotNull(String key, @Nullable String value);
+
+ /**
+ * Register the given string display data if the value is different than the specified default.
+ *
+ * @see DisplayData.Builder#add(String, String)
+ */
+ ItemBuilder addIfNotDefault(String key, @Nullable String value, @Nullable String defaultValue);
+
/**
* Register the given numeric display metadata. The metadata item will be registered with type
* {@link DisplayData.Type#INTEGER}, and is identified by the specified key and namespace from
@@ -133,6 +175,13 @@ public interface Builder {
*/
ItemBuilder add(String key, long value);
+ /**
+ * Register the given numeric display data if the value is different than the specified default.
+ *
+ * @see DisplayData.Builder#add(String, long)
+ */
+ ItemBuilder addIfNotDefault(String key, long value, long defaultValue);
+
/**
* Register the given floating point display metadata. The metadata item will be registered with
* type {@link DisplayData.Type#FLOAT}, and is identified by the specified key and namespace
@@ -141,12 +190,27 @@ public interface Builder {
ItemBuilder add(String key, double value);
/**
- * Register the given floating point display metadata. The metadata item will be registered with
+ * Register the given floating point display data if the value is different than the specified
+ * default.
+ *
+ * @see DisplayData.Builder#add(String, double)
+ */
+ ItemBuilder addIfNotDefault(String key, double value, double defaultValue);
+
+ /**
+ * Register the given boolean display metadata. The metadata item will be registered with
* type {@link DisplayData.Type#BOOLEAN}, and is identified by the specified key and namespace
* from the current transform or component.
*/
ItemBuilder add(String key, boolean value);
+ /**
+ * Register the given boolean display data if the value is different than the specified default.
+ *
+ * @see DisplayData.Builder#add(String, boolean)
+ */
+ ItemBuilder addIfNotDefault(String key, boolean value, boolean defaultValue);
+
/**
* Register the given timestamp display metadata. The metadata item will be registered with type
* {@link DisplayData.Type#TIMESTAMP}, and is identified by the specified key and namespace from
@@ -154,6 +218,22 @@ public interface Builder {
*/
ItemBuilder add(String key, Instant value);
+ /**
+ * Register the given timestamp display data if the value is not null.
+ *
+ * @see DisplayData.Builder#add(String, Instant)
+ */
+ ItemBuilder addIfNotNull(String key, @Nullable Instant value);
+
+ /**
+ * Register the given timestamp display data if the value is different than the specified
+ * default.
+ *
+ * @see DisplayData.Builder#add(String, Instant)
+ */
+ ItemBuilder addIfNotDefault(
+ String key, @Nullable Instant value, @Nullable Instant defaultValue);
+
/**
* Register the given duration display metadata. The metadata item will be registered with type
* {@link DisplayData.Type#DURATION}, and is identified by the specified key and namespace from
@@ -161,12 +241,54 @@ public interface Builder {
*/
ItemBuilder add(String key, Duration value);
+ /**
+ * Register the given duration display data if the value is not null.
+ *
+ * @see DisplayData.Builder#add(String, Duration)
+ */
+ ItemBuilder addIfNotNull(String key, @Nullable Duration value);
+
+ /**
+ * Register the given duration display data if the value is different than the specified
+ * default.
+ *
+ * @see DisplayData.Builder#add(String, Duration)
+ */
+ ItemBuilder addIfNotDefault(
+ String key, @Nullable Duration value, @Nullable Duration defaultValue);
+
/**
* Register the given class display metadata. The metadata item will be registered with type
* {@link DisplayData.Type#JAVA_CLASS}, and is identified by the specified key and namespace
* from the current transform or component.
*/
ItemBuilder add(String key, Class> value);
+
+ /**
+ * Register the given class display data if the value is not null.
+ *
+ * @see DisplayData.Builder#add(String, Class)
+ */
+ ItemBuilder addIfNotNull(String key, @Nullable Class> value);
+
+ /**
+ * Register the given class display data if the value is different than the specified default.
+ *
+ * @see DisplayData.Builder#add(String, Class)
+ */
+ ItemBuilder addIfNotDefault(
+ String key, @Nullable Class> value, @Nullable Class> defaultValue);
+
+ /**
+ * Register the given display metadata with the specified type.
+ *
+ *
The added display data is identified by the specified key and namespace from the current
+ * transform or component.
+ *
+ * @throws ClassCastException if the value cannot be safely cast to the specified type.
+ * @see DisplayData#inferType(Object)
+ */
+ ItemBuilder add(String key, Type type, Object value);
}
/**
@@ -190,6 +312,14 @@ public interface ItemBuilder extends Builder {
*
Specifying a null value will clear the URL if it was previously defined.
*/
ItemBuilder withLinkUrl(@Nullable String url);
+
+ /**
+ * Adds an explicit namespace to the most-recently added display metadata. The namespace
+ * and key uniquely identify the display metadata.
+ *
+ *
Leaving the namespace unspecified will default to the registering instance's class.
+ */
+ ItemBuilder withNamespace(Class> namespace);
}
/**
@@ -207,10 +337,11 @@ public static class Item {
private final String label;
private final String url;
- private static Item create(String namespace, String key, Type type, T value) {
+ private static Item create(Class> nsClass, String key, Type type, Object value) {
FormattedItemValue formatted = type.format(value);
+ String namespace = namespaceOf(nsClass);
return new Item(
- namespace, key, type, formatted.getLongValue(), formatted.getShortValue(), null, null);
+ namespace, key, type, formatted.getLongValue(), formatted.getShortValue(), null, null);
}
private Item(
@@ -337,6 +468,12 @@ private Item withLabel(String label) {
private Item withUrl(String url) {
return new Item(this.ns, this.key, this.type, this.value, this.shortValue, url, this.label);
}
+
+ private Item withNamespace(Class> nsClass) {
+ String namespace = namespaceOf(nsClass);
+ return new Item(
+ namespace, this.key, this.type, this.value, this.shortValue, this.url, this.label);
+ }
}
/**
@@ -354,7 +491,7 @@ public static class Identifier {
private final String key;
public static Identifier of(Class> namespace, String key) {
- return of(namespace.getName(), key);
+ return of(namespaceOf(namespace), key);
}
public static Identifier of(String namespace, String key) {
@@ -403,13 +540,14 @@ public enum Type {
STRING {
@Override
FormattedItemValue format(Object value) {
- return new FormattedItemValue((String) value);
+ return new FormattedItemValue(value.toString());
}
},
INTEGER {
@Override
FormattedItemValue format(Object value) {
- return new FormattedItemValue(Long.toString((long) value));
+ Number number = (Number) value;
+ return new FormattedItemValue(Long.toString(number.longValue()));
}
},
FLOAT {
@@ -451,6 +589,28 @@ FormattedItemValue format(Object value) {
*
Internal-only. Value objects can be safely cast to the expected Java type.
*/
abstract FormattedItemValue format(Object value);
+
+ @Nullable
+ private static Type tryInferFrom(@Nullable Object value) {
+ Type type;
+ 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 {
@@ -480,8 +640,9 @@ private static class InternalBuilder implements ItemBuilder {
private final Set