Add support for value provider

Improve the "hints" section of the metadata so that each hint can provide
the reference to a value provider.

A value provider defines how a tool can discover the potential values of
a property based on the context. The provider is identifed by a name and
may have an arbitrary number of parameters.

Closes gh-3303
This commit is contained in:
Stephane Nicoll
2015-06-23 17:55:50 +02:00
parent 43b9ea53d6
commit 0ec9de9137
6 changed files with 511 additions and 12 deletions

View File

@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Provide hints on an {@link ItemMetadata}. Defines the list of possible values for a
@@ -27,7 +28,7 @@ import java.util.List;
* <p>
* The {@code name} of the hint is the name of the related property with one major
* exception for map types as both the keys and values of the map can have hints. In such
* a case, the hint should be suffixed by ".key" or ".values" respectively. Creating a
* a case, the hint should be suffixed by ".keys" or ".values" respectively. Creating a
* hint for a map using its property name is therefore invalid.
*
* @author Stephane Nicoll
@@ -39,9 +40,12 @@ public class ItemHint implements Comparable<ItemHint> {
private final List<ValueHint> values;
public ItemHint(String name, List<ValueHint> values) {
private final List<ProviderHint> providers;
public ItemHint(String name, List<ValueHint> values, List<ProviderHint> providers) {
this.name = toCanonicalName(name);
this.values = new ArrayList<ValueHint>(values);
this.values = (values != null ? new ArrayList<ValueHint>(values) : new ArrayList<ValueHint>());
this.providers = (providers != null ? new ArrayList<ProviderHint>(providers) : new ArrayList<ProviderHint>());
}
private String toCanonicalName(String name) {
@@ -62,19 +66,23 @@ public class ItemHint implements Comparable<ItemHint> {
return Collections.unmodifiableList(this.values);
}
public List<ProviderHint> getProviders() {
return Collections.unmodifiableList(this.providers);
}
@Override
public int compareTo(ItemHint other) {
return getName().compareTo(other.getName());
}
public static ItemHint newHint(String name, ValueHint... values) {
return new ItemHint(name, Arrays.asList(values));
return new ItemHint(name, Arrays.asList(values), Collections.<ProviderHint>emptyList());
}
@Override
public String toString() {
return "ItemHint{" + "name='" + this.name + '\'' + ", values=" + this.values
+ '}';
return "ItemHint{" + "name='" + this.name + ", values=" + this.values
+ "providers=" + this.providers + '}';
}
public static class ValueHint {
@@ -104,4 +112,28 @@ public class ItemHint implements Comparable<ItemHint> {
}
public static class ProviderHint {
private final String name;
private final Map<String,Object> parameters;
public ProviderHint(String name, Map<String, Object> parameters) {
this.name = name;
this.parameters = parameters;
}
public String getName() {
return name;
}
public Map<String, Object> getParameters() {
return parameters;
}
@Override
public String toString() {
return "Provider{" + "name='" + this.name + ", parameters=" + this.parameters +
'}';
}
}
}

View File

@@ -24,8 +24,10 @@ import java.lang.reflect.Array;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.json.JSONArray;
@@ -103,6 +105,22 @@ public class JsonMarshaller {
}
jsonObject.put("values", valuesArray);
}
if (!hint.getProviders().isEmpty()) {
JSONArray providersArray = new JSONArray();
for (ItemHint.ProviderHint providerHint : hint.getProviders()) {
JSONObject providerHintObject = new JSONOrderedObject();
providerHintObject.put("name", providerHint.getName());
if (providerHint.getParameters() != null && !providerHint.getParameters().isEmpty()) {
JSONObject parametersObject = new JSONOrderedObject();
for (Map.Entry<String, Object> entry : providerHint.getParameters().entrySet()) {
parametersObject.put(entry.getKey(), extractItemValue(entry.getValue()));
}
providerHintObject.put("parameters", parametersObject);
}
providersArray.put(providerHintObject);
}
jsonObject.put("providers", providersArray);
}
return jsonObject;
}
@@ -182,7 +200,14 @@ public class JsonMarshaller {
values.add(toValueHint((JSONObject) valuesArray.get(i)));
}
}
return new ItemHint(name, values);
List<ItemHint.ProviderHint> providers = new ArrayList<ItemHint.ProviderHint>();
if (object.has("providers")) {
JSONArray providersObject = object.getJSONArray("providers");
for (int i = 0; i < providersObject.length(); i++) {
providers.add(toProviderHint((JSONObject) providersObject.get(i)));
}
}
return new ItemHint(name, values, providers);
}
private ItemHint.ValueHint toValueHint(JSONObject object) {
@@ -191,6 +216,20 @@ public class JsonMarshaller {
return new ItemHint.ValueHint(value, description);
}
private ItemHint.ProviderHint toProviderHint(JSONObject object) {
String name = object.getString("name");
Map<String,Object> parameters = new HashMap<String,Object>();
if (object.has("parameters")) {
JSONObject parametersObject = object.getJSONObject("parameters");
for (Object k : parametersObject.keySet()) {
String key = (String) k;
Object value = readItemValue(parametersObject.get(key));
parameters.put(key, value);
}
}
return new ItemHint.ProviderHint(name, parameters);
}
private Object readItemValue(Object value) {
if (value instanceof JSONArray) {
JSONArray array = (JSONArray) value;