From fc7da40055042fa88f9d0642edbbe09db56bf319 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Sat, 3 Nov 2018 14:49:01 +0000 Subject: [PATCH] Jackson deserialization for PreferenceStore --- .../refine/commands/SetPreferenceCommand.java | 6 +- .../google/refine/io/FileProjectManager.java | 7 +- .../model/metadata/ProjectMetadata.java | 9 +-- .../refine/preference/PreferenceStore.java | 69 ++++++++++--------- .../com/google/refine/preference/TopList.java | 44 ++++-------- .../preference/PreferenceStoreTests.java | 12 ++-- .../refine/tests/preference/TopListTests.java | 10 ++- 7 files changed, 77 insertions(+), 80 deletions(-) diff --git a/main/src/com/google/refine/commands/SetPreferenceCommand.java b/main/src/com/google/refine/commands/SetPreferenceCommand.java index ac5d3cf74..877b8dcd7 100644 --- a/main/src/com/google/refine/commands/SetPreferenceCommand.java +++ b/main/src/com/google/refine/commands/SetPreferenceCommand.java @@ -42,9 +42,11 @@ import javax.servlet.http.HttpServletResponse; import org.json.JSONException; import org.json.JSONTokener; +import com.fasterxml.jackson.databind.JsonNode; import com.google.refine.ProjectManager; import com.google.refine.model.Project; import com.google.refine.preference.PreferenceStore; +import com.google.refine.util.ParsingUtilities; public class SetPreferenceCommand extends Command { @Override @@ -58,12 +60,12 @@ public class SetPreferenceCommand extends Command { String valueString = request.getParameter("value"); try { - Object o = valueString == null ? null : new JSONTokener(valueString).nextValue(); + JsonNode o = valueString == null ? null : ParsingUtilities.mapper.readTree(valueString); ps.put(prefName, PreferenceStore.loadObject(o)); respond(response, "{ \"code\" : \"ok\" }"); - } catch (JSONException e) { + } catch (IOException e) { respondException(response, e); } } diff --git a/main/src/com/google/refine/io/FileProjectManager.java b/main/src/com/google/refine/io/FileProjectManager.java index 2baa454fc..fc93e0ca6 100644 --- a/main/src/com/google/refine/io/FileProjectManager.java +++ b/main/src/com/google/refine/io/FileProjectManager.java @@ -67,6 +67,7 @@ import com.google.refine.model.metadata.DataPackageMetadata; import com.google.refine.model.metadata.IMetadata; import com.google.refine.model.metadata.MetadataFormat; import com.google.refine.model.metadata.ProjectMetadata; +import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.TopList; import com.google.refine.util.ParsingUtilities; @@ -386,7 +387,7 @@ public class FileProjectManager extends ProjectManager { // load global preferences firstly if (obj.has("preferences") && !obj.isNull("preferences")) { - _preferenceStore.load(obj.getJSONObject("preferences")); + _preferenceStore = ParsingUtilities.mapper.readValue(obj.getJSONObject("preferences").toString(), PreferenceStore.class); } JSONArray a = obj.getJSONArray("projectIDs"); @@ -413,8 +414,8 @@ public class FileProjectManager extends ProjectManager { } if (obj.has("expressions") && !obj.isNull("expressions")) { // backward compatibility - ((TopList) _preferenceStore.get("scripting.expressions")) - .load(obj.getJSONArray("expressions")); + TopList newExpressions = ParsingUtilities.mapper.readValue(obj.getJSONArray("expressions").toString(), TopList.class); + this._preferenceStore.put("scripting.expressions", newExpressions); } found = true; diff --git a/main/src/com/google/refine/model/metadata/ProjectMetadata.java b/main/src/com/google/refine/model/metadata/ProjectMetadata.java index 0bf01d540..6ccd26fee 100644 --- a/main/src/com/google/refine/model/metadata/ProjectMetadata.java +++ b/main/src/com/google/refine/model/metadata/ProjectMetadata.java @@ -205,16 +205,17 @@ public class ProjectMetadata extends AbstractMetadata { if (obj.has("preferences") && !obj.isNull("preferences")) { try { - this._preferenceStore.load(obj.getJSONObject("preferences")); - } catch (JSONException e) { + this._preferenceStore = ParsingUtilities.mapper.readValue(obj.getJSONObject("preferences").toString(), PreferenceStore.class); + } catch (IOException e) { logger.error(ExceptionUtils.getStackTrace(e)); } } if (obj.has("expressions") && !obj.isNull("expressions")) { // backward compatibility try { - ((TopList) this._preferenceStore.get("scripting.expressions")).load(obj.getJSONArray("expressions")); - } catch (JSONException e) { + TopList newExpressions = ParsingUtilities.mapper.readValue(obj.getJSONArray("expressions").toString(), TopList.class); + this._preferenceStore.put("scripting.expressions", newExpressions); + } catch (IOException e) { logger.error(ExceptionUtils.getStackTrace(e)); } } diff --git a/main/src/com/google/refine/preference/PreferenceStore.java b/main/src/com/google/refine/preference/PreferenceStore.java index 25a27fba2..69b3bb3fd 100644 --- a/main/src/com/google/refine/preference/PreferenceStore.java +++ b/main/src/com/google/refine/preference/PreferenceStore.java @@ -34,7 +34,6 @@ 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; import java.util.Map; @@ -50,8 +49,9 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; - -import com.google.refine.RefineServlet; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.refine.util.ParsingUtilities; public class PreferenceStore { public static final String USER_METADATA_KEY = "userMetadata"; @@ -63,7 +63,6 @@ public class PreferenceStore { protected Map _prefs = new HashMap<>(); // Temporary wrapper while serialization has not been migrated yet. - @JsonProperty("entries") protected Map _prefsJackson = new HashMap<>(); public void put(String key, Object value) { @@ -119,39 +118,43 @@ public class PreferenceStore { return null; } - @SuppressWarnings("unchecked") - public void load(JSONObject obj) throws JSONException { - if (obj.has("entries") && !obj.isNull("entries")) { - JSONObject entries = obj.getJSONObject("entries"); - - Iterator i = entries.keys(); - while (i.hasNext()) { - String key = i.next(); - if (!entries.isNull(key)) { - Object o = entries.get(key), loaded = loadObject(o); - _prefs.put(key, loaded); - _prefsJackson.put(key, wrapJSONArray(loaded)); - } + @JsonProperty("entries") + public void setEntries(JsonNode entries) throws JSONException { + Iterator i = entries.fieldNames(); + while (i.hasNext()) { + String key = i.next(); + System.out.println(key); + if (entries.get(key) != null) { + JsonNode o = entries.get(key); + Object loaded = loadObject(o); + _prefs.put(key, loaded); + _prefsJackson.put(key, wrapJSONArray(loaded)); } - dirty = false; // internal puts don't count } + dirty = false; // internal puts don't count } - static public Object loadObject(Object o) { - if (o instanceof JSONObject) { - try { - JSONObject obj2 = (JSONObject) o; - String className = obj2.getString("class"); - Class klass = RefineServlet.getClass(className); - Method method = klass.getMethod("load", JSONObject.class); - - return method.invoke(null, obj2); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } else { - return o; + @JsonProperty("entries") + public Map getEntries() { + return _prefsJackson; + } + + static public Object loadObject(JsonNode o) { + System.out.println("loading"); + System.out.println(o.toString()); + try { + if (o instanceof ObjectNode) { + ObjectNode obj2 = (ObjectNode) o; + return ParsingUtilities.mapper.treeToValue(obj2, PreferenceValue.class); + } else if (o instanceof ArrayNode) { + return o; + } else { + // basic datatypes (int, double, boolean, string) + return ParsingUtilities.mapper.treeToValue(o, Object.class); + } + } catch (Exception e) { + e.printStackTrace(); + return null; } } } diff --git a/main/src/com/google/refine/preference/TopList.java b/main/src/com/google/refine/preference/TopList.java index 79b9802f3..f1bfaa860 100644 --- a/main/src/com/google/refine/preference/TopList.java +++ b/main/src/com/google/refine/preference/TopList.java @@ -38,24 +38,32 @@ import java.util.Iterator; import java.util.List; import org.apache.commons.collections.list.UnmodifiableList; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -public class TopList implements Iterable { +public class TopList implements Iterable, PreferenceValue { @JsonProperty("top") - final protected int _top; - final protected List _list = new ArrayList(); + protected int _top = 10; + protected List _list = new ArrayList(); public TopList(int top) { _top = top; } + @JsonCreator + public TopList( + @JsonProperty("top") + int top, + @JsonProperty("list") + List list) { + _top = top; + _list = list; + } + @SuppressWarnings("unchecked") @JsonProperty("list") public List getList() { @@ -75,30 +83,6 @@ public class TopList implements Iterable { _list.remove(element); } - @JsonProperty("class") - public String getClassName() { - return this.getClass().getName(); - } - - static public TopList load(JSONObject obj) throws JSONException { - int top = obj.has("top") && !obj.isNull("top") ? obj.getInt("top") : 10; - TopList tl = new TopList(top); - - if (obj.has("list") && !obj.isNull("list")) { - JSONArray a = obj.getJSONArray("list"); - - tl.load(a); - } - return tl; - } - - public void load(JSONArray a) throws JSONException { - int length = a.length(); - for (int i = 0; i < length && _list.size() < _top; i++) { - _list.add(a.getString(i)); - } - } - @Override @JsonIgnore public Iterator iterator() { diff --git a/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java b/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java index 9a5c1af18..0c58b7178 100644 --- a/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java +++ b/main/tests/server/src/com/google/refine/tests/preference/PreferenceStoreTests.java @@ -3,12 +3,15 @@ package com.google.refine.tests.preference; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; -import org.json.JSONObject; +import java.io.IOException; + import org.testng.annotations.Test; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; import com.google.refine.preference.PreferenceStore; -import com.google.refine.tests.RefineTest; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class PreferenceStoreTests { public static String json = "{" @@ -21,7 +24,7 @@ public class PreferenceStoreTests { + "}}"; @Test - public void serializePreferenceStore() { + public void serializePreferenceStore() throws JsonParseException, JsonMappingException, IOException { String jsonAfter = "{" + "\"entries\":{" @@ -32,8 +35,7 @@ public class PreferenceStoreTests { + " \"scripting.expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":100,\"list\":[]}," + " \"mypreference\":\"myvalue\"" + "}}"; - PreferenceStore prefStore = new PreferenceStore(); - prefStore.load(new JSONObject(json)); + PreferenceStore prefStore = ParsingUtilities.mapper.readValue(json, PreferenceStore.class); assertFalse(prefStore.isDirty()); prefStore.put("mypreference", "myvalue"); assertTrue(prefStore.isDirty()); diff --git a/main/tests/server/src/com/google/refine/tests/preference/TopListTests.java b/main/tests/server/src/com/google/refine/tests/preference/TopListTests.java index e9ed000d5..1339d1b23 100644 --- a/main/tests/server/src/com/google/refine/tests/preference/TopListTests.java +++ b/main/tests/server/src/com/google/refine/tests/preference/TopListTests.java @@ -1,14 +1,18 @@ package com.google.refine.tests.preference; -import org.json.JSONObject; +import java.io.IOException; + import org.testng.annotations.Test; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; import com.google.refine.preference.TopList; import com.google.refine.tests.util.TestUtils; +import com.google.refine.util.ParsingUtilities; public class TopListTests { @Test - public void serializeTopList() { + public void serializeTopList() throws JsonParseException, JsonMappingException, IOException { String json = "{" + "\"class\":\"com.google.refine.preference.TopList\"," + "\"top\":100," @@ -21,7 +25,7 @@ public class TopListTests { + " \"grel:\\\"https://pub.orcid.org/\\\"+value+\\\"/employments\\\"\"" + "]}"; TestUtils.isSerializedTo( - TopList.load(new JSONObject(json)), + ParsingUtilities.mapper.readValue(json, TopList.class), json); } }