Jackson serialization for project managers

This commit is contained in:
Antonin Delpeuch 2018-09-30 11:28:41 +01:00
parent 49b84574da
commit 987c2d1c80
4 changed files with 118 additions and 36 deletions

View File

@ -54,6 +54,9 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.history.HistoryEntryManager;
import com.google.refine.model.Project;
import com.google.refine.model.metadata.IMetadata;
@ -342,6 +345,7 @@ public abstract class ProjectManager {
/**
* Gets the InterProjectModel from memory
*/
@JsonIgnore
public InterProjectModel getInterProjectModel() {
return _interProjectModel;
}
@ -472,7 +476,7 @@ public abstract class ProjectManager {
* Gets all the project Metadata currently held in memory.
* @return
*/
@JsonIgnore
public Map<Long, ProjectMetadata> getAllProjectMetadata() {
for(Project project : _projects.values()) {
mergeEmptyUserMetadata(project.getMetadata());
@ -486,6 +490,7 @@ public abstract class ProjectManager {
*
* @return
*/
@JsonIgnore
public Map<String, Integer> getAllProjectTags() {
return _projectsTags;
}
@ -517,6 +522,7 @@ public abstract class ProjectManager {
* Gets the preference store
* @return
*/
@JsonProperty("preferences")
public PreferenceStore getPreferenceStore() {
return _preferenceStore;
}
@ -525,6 +531,7 @@ public abstract class ProjectManager {
* Gets all expressions from the preference store
* @return
*/
@JsonIgnore
public List<String> getExpressions() {
return ((TopList) _preferenceStore.get("scripting.expressions")).getList();
}
@ -533,6 +540,7 @@ public abstract class ProjectManager {
* The history entry manager deals with changes
* @return manager for handling history
*/
@JsonIgnore
public abstract HistoryEntryManager getHistoryEntryManager();

View File

@ -42,7 +42,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@ -57,6 +59,10 @@ import org.json.JSONWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.Jsonizable;
import com.google.refine.ProjectManager;
import com.google.refine.history.HistoryEntryManager;
import com.google.refine.model.Project;
@ -67,7 +73,7 @@ import com.google.refine.model.metadata.ProjectMetadata;
import com.google.refine.preference.TopList;
public class FileProjectManager extends ProjectManager {
public class FileProjectManager extends ProjectManager implements Jsonizable {
final static protected String PROJECT_DIR_SUFFIX = ".project";
protected File _workspaceDir;
@ -95,6 +101,7 @@ public class FileProjectManager extends ProjectManager {
load();
}
@JsonIgnore
public File getWorkspaceDir() {
return _workspaceDir;
}
@ -107,6 +114,7 @@ public class FileProjectManager extends ProjectManager {
return dir;
}
@JsonIgnore
public File getProjectDir(long projectID) {
return getProjectDir(_workspaceDir, projectID);
}
@ -267,6 +275,7 @@ public class FileProjectManager extends ProjectManager {
@Override
protected void saveWorkspace() {
synchronized (this) {
// TODO refactor this so that we check if the save is needed before writing to the file!
File tempFile = new File(_workspaceDir, "workspace.temp.json");
try {
if (!saveToFile(tempFile)) {
@ -294,39 +303,32 @@ public class FileProjectManager extends ProjectManager {
}
tempFile.renameTo(file);
logger.info("Saved workspace");
}
}
protected boolean saveNeeded() {
boolean projectSaveNeeded = _projectsMetadata.entrySet().stream()
.anyMatch(e -> e.getValue() != null && e.getValue().isDirty());
return projectSaveNeeded || _preferenceStore.isDirty();
}
protected void saveProjectMetadata() throws JSONException, IOException {
for(Entry<Long,ProjectMetadata> entry : _projectsMetadata.entrySet()) {
ProjectMetadata metadata = entry.getValue();
if (metadata != null && metadata.isDirty()) {
ProjectMetadataUtilities.save(metadata, getProjectDir(entry.getKey()));
}
}
}
protected boolean saveToFile(File file) throws IOException, JSONException {
FileWriter writer = new FileWriter(file);
boolean saveWasNeeded = false;
boolean saveWasNeeded = saveNeeded();
try {
JSONWriter jsonWriter = new JSONWriter(writer);
jsonWriter.object();
jsonWriter.key("projectIDs");
jsonWriter.array();
for (Long id : _projectsMetadata.keySet()) {
ProjectMetadata metadata = _projectsMetadata.get(id);
if (metadata != null) {
jsonWriter.value(id);
if (metadata.isDirty()) {
Project project = ProjectManager.singleton.getProject(id);
metadata.setRowCount(project.rows.size());
ProjectMetadataUtilities.save(metadata, getProjectDir(id));
saveWasNeeded = true;
}
}
}
jsonWriter.endArray();
writer.write('\n');
jsonWriter.key("preferences");
saveWasNeeded |= _preferenceStore.isDirty();
_preferenceStore.write(jsonWriter, new Properties());
jsonWriter.endObject();
write(jsonWriter, new Properties());
saveProjectMetadata();
} finally {
writer.close();
}
@ -370,7 +372,7 @@ public class FileProjectManager extends ProjectManager {
}
logger.error("Failed to load workspace from any attempted alternatives.");
}
protected boolean loadFromFile(File file) {
logger.info("Loading workspace: {}", file.getAbsolutePath());
@ -484,4 +486,28 @@ public class FileProjectManager extends ProjectManager {
gos.close();
}
}
@Override
public void write(JSONWriter jsonWriter, Properties options)
throws JSONException {
jsonWriter.object();
jsonWriter.key("projectIDs");
jsonWriter.array();
for (Long id : _projectsMetadata.keySet()) {
ProjectMetadata metadata = _projectsMetadata.get(id);
if (metadata != null) {
jsonWriter.value(id);
}
}
jsonWriter.endArray();
jsonWriter.key("preferences");
_preferenceStore.write(jsonWriter, new Properties());
jsonWriter.endObject();
}
@JsonProperty("projectIDs")
public Set<Long> getProjectIds() {
return _projectsMetadata.keySet();
}
}

View File

@ -0,0 +1,45 @@
package com.google.refine.tests.io;
import java.io.File;
import org.testng.annotations.Test;
import static org.mockito.Mockito.mock;
import com.google.refine.io.FileProjectManager;
import com.google.refine.model.metadata.ProjectMetadata;
import com.google.refine.tests.RefineTest;
import com.google.refine.tests.util.TestUtils;
public class FileProjectManagerTests extends RefineTest {
protected class FileProjectManagerStub extends FileProjectManager {
protected FileProjectManagerStub(File dir) {
super(dir);
_projectsMetadata.put(1234L, mock(ProjectMetadata.class));
}
}
@Test
public void serializeFileProjectManager() {
FileProjectManager manager = new FileProjectManagerStub(workspaceDir);
String json = "{\n" +
" \"preferences\" : {\n" +
" \"entries\" : {\n" +
" \"scripting.expressions\" : {\n" +
" \"class\" : \"com.google.refine.preference.TopList\",\n" +
" \"list\" : [ ],\n" +
" \"top\" : 100\n" +
" },\n" +
" \"scripting.starred-expressions\" : {\n" +
" \"class\" : \"com.google.refine.preference.TopList\",\n" +
" \"list\" : [ ],\n" +
" \"top\" : 2147483647\n" +
" }\n" +
" }\n" +
" },\n" +
" \"projectIDs\" : [ 1234 ]\n" +
" }";
TestUtils.isSerializedTo(manager, json);
}
}

View File

@ -7,19 +7,22 @@ import org.json.JSONObject;
import org.testng.annotations.Test;
import com.google.refine.preference.PreferenceStore;
import com.google.refine.tests.RefineTest;
import com.google.refine.tests.util.TestUtils;
public class PreferenceStoreTests {
public static String json = "{"
+ "\"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\":[]}"
+ "}}";
@Test
public void serializePreferenceStore() {
String json = "{"
+ "\"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\":[]}"
+ "}}";
String jsonAfter = "{"
+ "\"entries\":{"
+ " \"reconciliation.standardServices\":["