Jackson deserialization for PreferenceStore

This commit is contained in:
Antonin Delpeuch 2018-11-03 14:49:01 +00:00
parent 5cf58d874b
commit fc7da40055
7 changed files with 77 additions and 80 deletions

View File

@ -42,9 +42,11 @@ import javax.servlet.http.HttpServletResponse;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONTokener; import org.json.JSONTokener;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.PreferenceStore;
import com.google.refine.util.ParsingUtilities;
public class SetPreferenceCommand extends Command { public class SetPreferenceCommand extends Command {
@Override @Override
@ -58,12 +60,12 @@ public class SetPreferenceCommand extends Command {
String valueString = request.getParameter("value"); String valueString = request.getParameter("value");
try { 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)); ps.put(prefName, PreferenceStore.loadObject(o));
respond(response, "{ \"code\" : \"ok\" }"); respond(response, "{ \"code\" : \"ok\" }");
} catch (JSONException e) { } catch (IOException e) {
respondException(response, e); respondException(response, e);
} }
} }

View File

@ -67,6 +67,7 @@ import com.google.refine.model.metadata.DataPackageMetadata;
import com.google.refine.model.metadata.IMetadata; import com.google.refine.model.metadata.IMetadata;
import com.google.refine.model.metadata.MetadataFormat; import com.google.refine.model.metadata.MetadataFormat;
import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.model.metadata.ProjectMetadata;
import com.google.refine.preference.PreferenceStore;
import com.google.refine.preference.TopList; import com.google.refine.preference.TopList;
import com.google.refine.util.ParsingUtilities; import com.google.refine.util.ParsingUtilities;
@ -386,7 +387,7 @@ public class FileProjectManager extends ProjectManager {
// load global preferences firstly // load global preferences firstly
if (obj.has("preferences") && !obj.isNull("preferences")) { 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"); JSONArray a = obj.getJSONArray("projectIDs");
@ -413,8 +414,8 @@ public class FileProjectManager extends ProjectManager {
} }
if (obj.has("expressions") && !obj.isNull("expressions")) { // backward compatibility if (obj.has("expressions") && !obj.isNull("expressions")) { // backward compatibility
((TopList) _preferenceStore.get("scripting.expressions")) TopList newExpressions = ParsingUtilities.mapper.readValue(obj.getJSONArray("expressions").toString(), TopList.class);
.load(obj.getJSONArray("expressions")); this._preferenceStore.put("scripting.expressions", newExpressions);
} }
found = true; found = true;

View File

@ -205,16 +205,17 @@ public class ProjectMetadata extends AbstractMetadata {
if (obj.has("preferences") && !obj.isNull("preferences")) { if (obj.has("preferences") && !obj.isNull("preferences")) {
try { try {
this._preferenceStore.load(obj.getJSONObject("preferences")); this._preferenceStore = ParsingUtilities.mapper.readValue(obj.getJSONObject("preferences").toString(), PreferenceStore.class);
} catch (JSONException e) { } catch (IOException e) {
logger.error(ExceptionUtils.getStackTrace(e)); logger.error(ExceptionUtils.getStackTrace(e));
} }
} }
if (obj.has("expressions") && !obj.isNull("expressions")) { // backward compatibility if (obj.has("expressions") && !obj.isNull("expressions")) { // backward compatibility
try { try {
((TopList) this._preferenceStore.get("scripting.expressions")).load(obj.getJSONArray("expressions")); TopList newExpressions = ParsingUtilities.mapper.readValue(obj.getJSONArray("expressions").toString(), TopList.class);
} catch (JSONException e) { this._preferenceStore.put("scripting.expressions", newExpressions);
} catch (IOException e) {
logger.error(ExceptionUtils.getStackTrace(e)); logger.error(ExceptionUtils.getStackTrace(e));
} }
} }

View File

@ -34,7 +34,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.preference; package com.google.refine.preference;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; 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.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.refine.RefineServlet; import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.util.ParsingUtilities;
public class PreferenceStore { public class PreferenceStore {
public static final String USER_METADATA_KEY = "userMetadata"; public static final String USER_METADATA_KEY = "userMetadata";
@ -63,7 +63,6 @@ public class PreferenceStore {
protected Map<String, Object> _prefs = new HashMap<>(); protected Map<String, Object> _prefs = new HashMap<>();
// Temporary wrapper while serialization has not been migrated yet. // Temporary wrapper while serialization has not been migrated yet.
@JsonProperty("entries")
protected Map<String, Object> _prefsJackson = new HashMap<>(); protected Map<String, Object> _prefsJackson = new HashMap<>();
public void put(String key, Object value) { public void put(String key, Object value) {
@ -119,39 +118,43 @@ public class PreferenceStore {
return null; return null;
} }
@SuppressWarnings("unchecked") @JsonProperty("entries")
public void load(JSONObject obj) throws JSONException { public void setEntries(JsonNode entries) throws JSONException {
if (obj.has("entries") && !obj.isNull("entries")) { Iterator<String> i = entries.fieldNames();
JSONObject entries = obj.getJSONObject("entries");
Iterator<String> i = entries.keys();
while (i.hasNext()) { while (i.hasNext()) {
String key = i.next(); String key = i.next();
if (!entries.isNull(key)) { System.out.println(key);
Object o = entries.get(key), loaded = loadObject(o); if (entries.get(key) != null) {
JsonNode o = entries.get(key);
Object loaded = loadObject(o);
_prefs.put(key, loaded); _prefs.put(key, loaded);
_prefsJackson.put(key, wrapJSONArray(loaded)); _prefsJackson.put(key, wrapJSONArray(loaded));
} }
} }
dirty = false; // internal puts don't count dirty = false; // internal puts don't count
} }
@JsonProperty("entries")
public Map<String, Object> getEntries() {
return _prefsJackson;
} }
static public Object loadObject(Object o) { static public Object loadObject(JsonNode o) {
if (o instanceof JSONObject) { System.out.println("loading");
System.out.println(o.toString());
try { try {
JSONObject obj2 = (JSONObject) o; if (o instanceof ObjectNode) {
String className = obj2.getString("class"); ObjectNode obj2 = (ObjectNode) o;
Class<?> klass = RefineServlet.getClass(className); return ParsingUtilities.mapper.treeToValue(obj2, PreferenceValue.class);
Method method = klass.getMethod("load", JSONObject.class); } else if (o instanceof ArrayNode) {
return o;
return method.invoke(null, obj2); } else {
// basic datatypes (int, double, boolean, string)
return ParsingUtilities.mapper.treeToValue(o, Object.class);
}
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
} else {
return o;
}
} }
} }

View File

@ -38,24 +38,32 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.commons.collections.list.UnmodifiableList; 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.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
public class TopList implements Iterable<String> { public class TopList implements Iterable<String>, PreferenceValue {
@JsonProperty("top") @JsonProperty("top")
final protected int _top; protected int _top = 10;
final protected List<String> _list = new ArrayList<String>(); protected List<String> _list = new ArrayList<String>();
public TopList(int top) { public TopList(int top) {
_top = top; _top = top;
} }
@JsonCreator
public TopList(
@JsonProperty("top")
int top,
@JsonProperty("list")
List<String> list) {
_top = top;
_list = list;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@JsonProperty("list") @JsonProperty("list")
public List<String> getList() { public List<String> getList() {
@ -75,30 +83,6 @@ public class TopList implements Iterable<String> {
_list.remove(element); _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 @Override
@JsonIgnore @JsonIgnore
public Iterator<String> iterator() { public Iterator<String> iterator() {

View File

@ -3,12 +3,15 @@ package com.google.refine.tests.preference;
import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
import org.json.JSONObject; import java.io.IOException;
import org.testng.annotations.Test; 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.preference.PreferenceStore;
import com.google.refine.tests.RefineTest;
import com.google.refine.tests.util.TestUtils; import com.google.refine.tests.util.TestUtils;
import com.google.refine.util.ParsingUtilities;
public class PreferenceStoreTests { public class PreferenceStoreTests {
public static String json = "{" public static String json = "{"
@ -21,7 +24,7 @@ public class PreferenceStoreTests {
+ "}}"; + "}}";
@Test @Test
public void serializePreferenceStore() { public void serializePreferenceStore() throws JsonParseException, JsonMappingException, IOException {
String jsonAfter = "{" String jsonAfter = "{"
+ "\"entries\":{" + "\"entries\":{"
@ -32,8 +35,7 @@ public class PreferenceStoreTests {
+ " \"scripting.expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":100,\"list\":[]}," + " \"scripting.expressions\":{\"class\":\"com.google.refine.preference.TopList\",\"top\":100,\"list\":[]},"
+ " \"mypreference\":\"myvalue\"" + " \"mypreference\":\"myvalue\""
+ "}}"; + "}}";
PreferenceStore prefStore = new PreferenceStore(); PreferenceStore prefStore = ParsingUtilities.mapper.readValue(json, PreferenceStore.class);
prefStore.load(new JSONObject(json));
assertFalse(prefStore.isDirty()); assertFalse(prefStore.isDirty());
prefStore.put("mypreference", "myvalue"); prefStore.put("mypreference", "myvalue");
assertTrue(prefStore.isDirty()); assertTrue(prefStore.isDirty());

View File

@ -1,14 +1,18 @@
package com.google.refine.tests.preference; package com.google.refine.tests.preference;
import org.json.JSONObject; import java.io.IOException;
import org.testng.annotations.Test; 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.preference.TopList;
import com.google.refine.tests.util.TestUtils; import com.google.refine.tests.util.TestUtils;
import com.google.refine.util.ParsingUtilities;
public class TopListTests { public class TopListTests {
@Test @Test
public void serializeTopList() { public void serializeTopList() throws JsonParseException, JsonMappingException, IOException {
String json = "{" String json = "{"
+ "\"class\":\"com.google.refine.preference.TopList\"," + "\"class\":\"com.google.refine.preference.TopList\","
+ "\"top\":100," + "\"top\":100,"
@ -21,7 +25,7 @@ public class TopListTests {
+ " \"grel:\\\"https://pub.orcid.org/\\\"+value+\\\"/employments\\\"\"" + " \"grel:\\\"https://pub.orcid.org/\\\"+value+\\\"/employments\\\"\""
+ "]}"; + "]}";
TestUtils.isSerializedTo( TestUtils.isSerializedTo(
TopList.load(new JSONObject(json)), ParsingUtilities.mapper.readValue(json, TopList.class),
json); json);
} }
} }