Jackson serialization for preferences

This commit is contained in:
Antonin Delpeuch 2018-09-29 18:09:41 +01:00
parent 418b21dda2
commit 18c2183cbc
4 changed files with 79 additions and 6 deletions

View File

@ -44,6 +44,7 @@ import org.json.JSONObject;
import org.json.JSONWriter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.refine.Jsonizable;
import com.google.refine.browsing.facets.Facet;
@ -72,6 +73,7 @@ public class Engine implements Jsonizable {
protected Project _project;
protected List<Facet> _facets = new LinkedList<Facet>();
@JsonValue
protected EngineConfig _config = new EngineConfig(Collections.emptyList(), Mode.RowBased);
static public String modeToString(Mode mode) {

View File

@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.preference;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
@ -40,10 +41,18 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.Jsonizable;
import com.google.refine.RefineServlet;
@ -54,21 +63,40 @@ public class PreferenceStore implements Jsonizable {
public static final String USER_NAME = "username";
private boolean dirty = false;
protected Map<String, Object> _prefs = new HashMap<String, Object>();
protected Map<String, Object> _prefs = new HashMap<>();
// Temporary wrapper while serialization has not been migrated yet.
@JsonProperty("entries")
protected Map<String, Object> _prefsJackson = new HashMap<>();
public void put(String key, Object value) {
if (value == null) {
_prefs.remove(key);
_prefsJackson.remove(key);
} else {
_prefs.put(key, value);
_prefsJackson.put(key, wrapJSONArray(value));
}
dirty = true;
}
private Object wrapJSONArray(Object value) {
ObjectMapper mapper = new ObjectMapper();
if(value != null && value instanceof JSONArray) {
try {
return mapper.readValue(value.toString(), JsonNode.class);
} catch (IOException e) {
return null;
}
}
return value;
}
public Object get(String key) {
return _prefs.get(key);
}
@JsonIgnore
public Set<String> getKeys() {
return _prefs.keySet();
}
@ -98,10 +126,24 @@ public class PreferenceStore implements Jsonizable {
/**
* @return true if the preference store has unsaved changes
*/
@JsonIgnore
public boolean isDirty() {
return dirty;
}
/**
* Mark the object as clean every time it is serialized.
* This behaviour is not very clean - it is inherited from
* the previous deserialization code.
* @return
*/
@JsonProperty("makeClean")
@JsonInclude(Include.NON_NULL)
public Integer markAsClean() {
dirty = false;
return null;
}
@SuppressWarnings("unchecked")
public void load(JSONObject obj) throws JSONException {
if (obj.has("entries") && !obj.isNull("entries")) {
@ -111,8 +153,9 @@ public class PreferenceStore implements Jsonizable {
while (i.hasNext()) {
String key = i.next();
if (!entries.isNull(key)) {
Object o = entries.get(key);
_prefs.put(key, loadObject(o));
Object o = entries.get(key), loaded = loadObject(o);
_prefs.put(key, loaded);
_prefsJackson.put(key, wrapJSONArray(loaded));
}
}
dirty = false; // internal puts don't count

View File

@ -44,10 +44,14 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.Jsonizable;
public class TopList implements Jsonizable, Iterable<String> {
@JsonProperty("top")
final protected int _top;
final protected List<String> _list = new ArrayList<String>();
@ -56,6 +60,7 @@ public class TopList implements Jsonizable, Iterable<String> {
}
@SuppressWarnings("unchecked")
@JsonProperty("list")
public List<String> getList() {
return UnmodifiableList.decorate(_list);
}
@ -72,11 +77,16 @@ public class TopList implements Jsonizable, Iterable<String> {
{
_list.remove(element);
}
@JsonProperty("class")
public String getClassName() {
return this.getClass().getName();
}
@Override
public void write(JSONWriter writer, Properties options) throws JSONException {
writer.object();
writer.key("class"); writer.value(this.getClass().getName());
writer.key("class"); writer.value(getClassName());
writer.key("top"); writer.value(_top);
writer.key("list");
@ -107,7 +117,8 @@ public class TopList implements Jsonizable, Iterable<String> {
}
}
@Override
@Override
@JsonIgnore
public Iterator<String> iterator() {
return _list.iterator();
}

View File

@ -1,5 +1,8 @@
package com.google.refine.tests.preference;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import org.json.JSONObject;
import org.testng.annotations.Test;
@ -17,8 +20,22 @@ public class PreferenceStoreTests {
+ " \"scripting.starred-expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":2147483647,\"list\":[]},"
+ " \"scripting.expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":100,\"list\":[]}"
+ "}}";
String jsonAfter = "{"
+ "\"entries\":{"
+ " \"reconciliation.standardServices\":["
+ " {\"propose_properties\":{\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/propose_properties\"},\"preview\":{\"width\":320,\"url\":\"https://tools.wmflabs.org/openrefine-wikidata/en/preview?id={{id}}\",\"height\":90},\"view\":{\"url\":\"https://www.wikidata.org/wiki/{{id}}\"},\"ui\":{\"handler\":\"ReconStandardServicePanel\"},\"identifierSpace\":\"http://www.wikidata.org/entity/\",\"name\":\"Wikidata Reconciliation for OpenRefine (en)\",\"suggest\":{\"property\":{\"flyout_service_path\":\"/en/flyout/property?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/property\"},\"type\":{\"flyout_service_path\":\"/en/flyout/type?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/type\"},\"entity\":{\"flyout_service_path\":\"/en/flyout/entity?id=${id}\",\"service_url\":\"https://tools.wmflabs.org/openrefine-wikidata\",\"service_path\":\"/en/suggest/entity\"}},\"defaultTypes\":[{\"name\":\"entity\",\"id\":\"Q35120\"}],\"url\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\",\"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"}"
+ " ],"
+ " \"scripting.starred-expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":2147483647,\"list\":[]},"
+ " \"scripting.expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":100,\"list\":[]},"
+ " \"mypreference\":\"myvalue\""
+ "}}";
PreferenceStore prefStore = new PreferenceStore();
prefStore.load(new JSONObject(json));
TestUtils.isSerializedTo(prefStore, json);
assertFalse(prefStore.isDirty());
prefStore.put("mypreference", "myvalue");
assertTrue(prefStore.isDirty());
TestUtils.isSerializedTo(prefStore, jsonAfter);
assertFalse(prefStore.isDirty());
}
}