Merge pull request #1755 from OpenRefine/jackson-serialization

Jackson serialization
This commit is contained in:
Antonin Delpeuch 2018-12-01 23:56:50 +00:00 committed by GitHub
commit 5639f1b2f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
551 changed files with 9671 additions and 64895 deletions

View File

@ -153,18 +153,13 @@
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId> <artifactId>jackson-core</artifactId>
<version>2.1.3</version> <version>2.9.7</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.codehaus.jackson</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core-asl</artifactId> <artifactId>jackson-annotations</artifactId>
<version>1.9.13</version> <version>2.9.7</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>

View File

@ -39,13 +39,13 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.ProjectMetadata;
import com.google.refine.RefineServlet; import com.google.refine.RefineServlet;
import com.google.refine.commands.HttpUtilities; import com.google.refine.commands.HttpUtilities;
import com.google.refine.extension.database.model.DatabaseColumn; import com.google.refine.extension.database.model.DatabaseColumn;
@ -55,7 +55,6 @@ import com.google.refine.importing.ImportingController;
import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingJob;
import com.google.refine.importing.ImportingManager; import com.google.refine.importing.ImportingManager;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.metadata.ProjectMetadata;
import com.google.refine.util.JSONUtilities; import com.google.refine.util.JSONUtilities;
import com.google.refine.util.ParsingUtilities; import com.google.refine.util.ParsingUtilities;
@ -140,8 +139,8 @@ public class DatabaseImportController implements ImportingController {
} }
JSONObject result = new JSONObject(); ObjectNode result = ParsingUtilities.mapper.createObjectNode();
JSONObject options = new JSONObject(); ObjectNode options = ParsingUtilities.mapper.createObjectNode();
JSONUtilities.safePut(result, "status", "ok"); JSONUtilities.safePut(result, "status", "ok");
JSONUtilities.safePut(result, OPTIONS_KEY, options); JSONUtilities.safePut(result, OPTIONS_KEY, options);
@ -191,7 +190,7 @@ public class DatabaseImportController implements ImportingController {
job.updating = true; job.updating = true;
try { try {
JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject( ObjectNode optionObj = ParsingUtilities.evaluateJsonStringToObjectNode(
request.getParameter("options")); request.getParameter("options"));
List<Exception> exceptions = new LinkedList<Exception>(); List<Exception> exceptions = new LinkedList<Exception>();
@ -207,35 +206,28 @@ public class DatabaseImportController implements ImportingController {
optionObj, optionObj,
exceptions exceptions
); );
// String exStr = getExceptionString(exceptions);
// logger.info("exceptions::" + exStr);
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
try { try {
writer.object(); writer.writeStartObject();
if (exceptions.size() == 0) { if (exceptions.size() == 0) {
job.project.update(); // update all internal models, indexes, caches, etc. job.project.update(); // update all internal models, indexes, caches, etc.
writer.key("status"); writer.writeStringField("status", "ok");
writer.value("ok");
} else { } else {
writer.key("status"); writer.writeStringField("status", "error");
writer.value("error"); writer.writeStringField("message", getExceptionString(exceptions));
writer.key("message");
writer.value(getExceptionString(exceptions));
// writer.array();
// writeErrors(writer, exceptions);
// writer.endArray();
} }
writer.endObject(); writer.writeEndObject();
} catch (JSONException e) { } catch (IOException e) {
throw new ServletException(e); throw new ServletException(e);
} finally { } finally {
writer.flush();
writer.close();
w.flush(); w.flush();
w.close(); w.close();
} }
} catch (JSONException e) { } catch (IOException e) {
throw new ServletException(e); throw new ServletException(e);
} finally { } finally {
job.touch(); job.touch();
@ -271,7 +263,7 @@ public class DatabaseImportController implements ImportingController {
ProjectMetadata metadata, ProjectMetadata metadata,
final ImportingJob job, final ImportingJob job,
int limit, int limit,
JSONObject options, ObjectNode options,
List<Exception> exceptions) throws DatabaseServiceException{ List<Exception> exceptions) throws DatabaseServiceException{
@ -329,7 +321,7 @@ public class DatabaseImportController implements ImportingController {
job.updating = true; job.updating = true;
try { try {
final JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject( final ObjectNode optionObj = ParsingUtilities.evaluateJsonStringToObjectNode(
request.getParameter("options")); request.getParameter("options"));
final List<Exception> exceptions = new LinkedList<Exception>(); final List<Exception> exceptions = new LinkedList<Exception>();
@ -378,7 +370,7 @@ public class DatabaseImportController implements ImportingController {
}.start(); }.start();
HttpUtilities.respond(response, "ok", "done"); HttpUtilities.respond(response, "ok", "done");
} catch (JSONException e) { } catch (IOException e) {
throw new ServletException(e); throw new ServletException(e);
} }
} }
@ -400,7 +392,7 @@ public class DatabaseImportController implements ImportingController {
ProjectMetadata metadata, ProjectMetadata metadata,
final ImportingJob job, final ImportingJob job,
int limit, int limit,
JSONObject options, ObjectNode options,
List<Exception> exceptions) throws DatabaseServiceException{ List<Exception> exceptions) throws DatabaseServiceException{

View File

@ -35,13 +35,9 @@ import java.util.Properties;
import javax.servlet.ServletConfig; import javax.servlet.ServletConfig;
import org.json.JSONException;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.refine.Jsonizable;
import edu.mit.simile.butterfly.ButterflyModuleImpl; import edu.mit.simile.butterfly.ButterflyModuleImpl;

View File

@ -34,13 +34,13 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.io.FileProjectManager; import com.google.refine.io.FileProjectManager;

View File

@ -36,16 +36,17 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.codehaus.jackson.map.ObjectMapper;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
//import com.google.refine.ProjectManager; //import com.google.refine.ProjectManager;
import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseConfiguration;
import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseService;
import com.google.refine.extension.database.DatabaseServiceException; import com.google.refine.extension.database.DatabaseServiceException;
import com.google.refine.extension.database.model.DatabaseInfo; import com.google.refine.extension.database.model.DatabaseInfo;
import com.google.refine.util.ParsingUtilities;
public class ConnectCommand extends DatabaseCommand { public class ConnectCommand extends DatabaseCommand {
@ -66,7 +67,7 @@ public class ConnectCommand extends DatabaseCommand {
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json"); response.setHeader("Content-Type", "application/json");
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
ObjectMapper mapperObj = new ObjectMapper(); ObjectMapper mapperObj = new ObjectMapper();
try { try {
@ -74,22 +75,20 @@ public class ConnectCommand extends DatabaseCommand {
.connect(databaseConfiguration); .connect(databaseConfiguration);
String databaseInfoString = mapperObj.writeValueAsString(databaseInfo); String databaseInfoString = mapperObj.writeValueAsString(databaseInfo);
response.setStatus(HttpStatus.SC_OK); response.setStatus(HttpStatus.SC_OK);
writer.object(); writer.writeStartObject();
writer.key("code"); writer.writeStringField("code", "ok");
writer.value("ok"); writer.writeStringField("databaseInfo", databaseInfoString);
writer.key("databaseInfo"); writer.writeEndObject();
writer.value(databaseInfoString);
writer.endObject();
} catch (DatabaseServiceException e) { } catch (DatabaseServiceException e) {
logger.error("ConnectCommand::Post::DatabaseServiceException::{}", e); logger.error("ConnectCommand::Post::DatabaseServiceException::{}", e);
sendError(HttpStatus.SC_UNAUTHORIZED,response, writer, e); sendError(HttpStatus.SC_UNAUTHORIZED,response, e);
}catch (Exception e) { }catch (Exception e) {
logger.error("ConnectCommand::Post::Exception::{}", e); logger.error("ConnectCommand::Post::Exception::{}", e);
sendError(HttpStatus.SC_UNAUTHORIZED,response, writer, e); sendError(HttpStatus.SC_UNAUTHORIZED,response, e);
} finally { } finally {
// w.flush(); writer.flush();
writer.close();
w.close(); w.close();
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -33,7 +33,6 @@ import java.io.IOException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -82,7 +81,7 @@ public abstract class DatabaseCommand extends Command {
* @param e * @param e
* @throws IOException * @throws IOException
*/ */
protected void sendError(int status, HttpServletResponse response, JSONWriter writer, Exception e) protected void sendError(int status, HttpServletResponse response, Exception e)
throws IOException { throws IOException {
//logger.info("sendError::{}", writer); //logger.info("sendError::{}", writer);
@ -97,7 +96,7 @@ public abstract class DatabaseCommand extends Command {
* @param e * @param e
* @throws IOException * @throws IOException
*/ */
protected void sendError(int status, HttpServletResponse response, JSONWriter writer, DatabaseServiceException e) protected void sendError(int status, HttpServletResponse response, DatabaseServiceException e)
throws IOException { throws IOException {
String message = ""; String message = "";

View File

@ -36,16 +36,17 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.codehaus.jackson.map.ObjectMapper;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
//import com.google.refine.ProjectManager; //import com.google.refine.ProjectManager;
import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseConfiguration;
import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseService;
import com.google.refine.extension.database.DatabaseServiceException; import com.google.refine.extension.database.DatabaseServiceException;
import com.google.refine.extension.database.model.DatabaseInfo; import com.google.refine.extension.database.model.DatabaseInfo;
import com.google.refine.util.ParsingUtilities;
public class ExecuteQueryCommand extends DatabaseCommand { public class ExecuteQueryCommand extends DatabaseCommand {
@ -69,7 +70,7 @@ public class ExecuteQueryCommand extends DatabaseCommand {
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json"); response.setHeader("Content-Type", "application/json");
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
try { try {
DatabaseInfo databaseInfo = DatabaseService.get(databaseConfiguration.getDatabaseType()) DatabaseInfo databaseInfo = DatabaseService.get(databaseConfiguration.getDatabaseType())
@ -84,22 +85,22 @@ public class ExecuteQueryCommand extends DatabaseCommand {
} }
writer.object(); writer.writeStartObject();
writer.key("code"); writer.writeStringField("code", "ok");
writer.value("ok"); writer.writeStringField("QueryResult", jsonStr);
writer.key("QueryResult"); writer.writeEndObject();
writer.value(jsonStr);
writer.endObject();
} catch (DatabaseServiceException e) { } catch (DatabaseServiceException e) {
logger.error("QueryCommand::Post::DatabaseServiceException::{}", e); logger.error("QueryCommand::Post::DatabaseServiceException::{}", e);
sendError(HttpStatus.SC_BAD_REQUEST, response, writer, e); sendError(HttpStatus.SC_BAD_REQUEST, response, e);
} catch (Exception e) { } catch (Exception e) {
logger.error("QueryCommand::Post::Exception::{}", e); logger.error("QueryCommand::Post::Exception::{}", e);
sendError(HttpStatus.SC_BAD_REQUEST,response, writer, e); sendError(HttpStatus.SC_BAD_REQUEST,response, e);
} finally { } finally {
writer.flush();
writer.close();
w.close(); w.close();
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -37,13 +37,14 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.json.JSONException;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseConfiguration;
import com.google.refine.extension.database.DatabaseUtils; import com.google.refine.extension.database.DatabaseUtils;
import com.google.refine.util.ParsingUtilities;
public class SavedConnectionCommand extends DatabaseCommand { public class SavedConnectionCommand extends DatabaseCommand {
@ -117,54 +118,41 @@ public class SavedConnectionCommand extends DatabaseCommand {
* @throws IOException * @throws IOException
* @throws JSONException * @throws JSONException
*/ */
private void writeSavedConnectionResponse(HttpServletResponse response, DatabaseConfiguration savedConnection) throws IOException, JSONException { private void writeSavedConnectionResponse(HttpServletResponse response, DatabaseConfiguration savedConnection) throws IOException {
Writer w = response.getWriter(); Writer w = response.getWriter();
try { try {
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
writer.object(); writer.writeStartObject();
writer.key(DatabaseUtils.SAVED_CONNECTION_KEY); writer.writeArrayFieldStart(DatabaseUtils.SAVED_CONNECTION_KEY);
writer.array();
writer.object(); writer.writeStartObject();
writer.key("connectionName"); writer.writeStringField("connectionName", savedConnection.getConnectionName());
writer.value(savedConnection.getConnectionName());
writer.key("databaseType"); writer.writeStringField("databaseType", savedConnection.getDatabaseType());
writer.value(savedConnection.getDatabaseType());
writer.key("databaseHost"); writer.writeStringField("databaseHost", savedConnection.getDatabaseHost());
writer.value(savedConnection.getDatabaseHost());
writer.key("databasePort"); writer.writeNumberField("databasePort", savedConnection.getDatabasePort());
writer.value(savedConnection.getDatabasePort());
writer.key("databaseName"); writer.writeStringField("databaseName", savedConnection.getDatabaseName());
writer.value(savedConnection.getDatabaseName());
writer.key("databasePassword");
//
String dbPasswd = savedConnection.getDatabasePassword(); String dbPasswd = savedConnection.getDatabasePassword();
if(dbPasswd != null && !dbPasswd.isEmpty()) { if(dbPasswd != null && !dbPasswd.isEmpty()) {
dbPasswd = DatabaseUtils.decrypt(savedConnection.getDatabasePassword()); dbPasswd = DatabaseUtils.decrypt(savedConnection.getDatabasePassword());
//logger.info("Decrypted Password::" + dbPasswd);
} }
writer.value(dbPasswd); writer.writeStringField("databasePassword", dbPasswd);
//
// writer.value(savedConnection.getDatabasePassword()); writer.writeStringField("databaseSchema", savedConnection.getDatabaseSchema());
writer.key("databaseSchema"); writer.writeStringField("databaseUser", savedConnection.getDatabaseUser());
writer.value(savedConnection.getDatabaseSchema());
writer.key("databaseUser"); writer.writeEndObject();
writer.value(savedConnection.getDatabaseUser()); writer.writeEndArray();
writer.endObject(); writer.writeEndObject();
writer.endArray(); writer.flush();
writer.close();
writer.endObject();
}finally { }finally {
w.flush(); w.flush();
@ -178,59 +166,52 @@ public class SavedConnectionCommand extends DatabaseCommand {
* @throws IOException * @throws IOException
* @throws JSONException * @throws JSONException
*/ */
private void writeSavedConnectionResponse(HttpServletResponse response) throws IOException, JSONException { private void writeSavedConnectionResponse(HttpServletResponse response) throws IOException {
Writer w = response.getWriter(); Writer w = response.getWriter();
try { try {
List<DatabaseConfiguration> savedConnections = DatabaseUtils.getSavedConnections(); List<DatabaseConfiguration> savedConnections = DatabaseUtils.getSavedConnections();
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
writer.object(); writer.writeStartObject();
writer.key(DatabaseUtils.SAVED_CONNECTION_KEY); writer.writeArrayFieldStart(DatabaseUtils.SAVED_CONNECTION_KEY);
writer.array();
int size = savedConnections.size(); int size = savedConnections.size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
writer.object(); writer.writeStartObject();
DatabaseConfiguration dbConfig = (DatabaseConfiguration) savedConnections.get(i); DatabaseConfiguration dbConfig = (DatabaseConfiguration) savedConnections.get(i);
writer.key("connectionName"); writer.writeStringField("connectionName", dbConfig.getConnectionName());
writer.value(dbConfig.getConnectionName());
writer.key("databaseType"); writer.writeStringField("databaseType", dbConfig.getDatabaseType());
writer.value(dbConfig.getDatabaseType());
writer.key("databaseHost"); writer.writeStringField("databaseHost", dbConfig.getDatabaseHost());
writer.value(dbConfig.getDatabaseHost());
writer.key("databasePort"); writer.writeNumberField("databasePort", dbConfig.getDatabasePort());
writer.value(dbConfig.getDatabasePort());
writer.key("databaseName"); writer.writeStringField("databaseName", dbConfig.getDatabaseName());
writer.value(dbConfig.getDatabaseName());
writer.key("databasePassword");
String dbPasswd = dbConfig.getDatabasePassword(); String dbPasswd = dbConfig.getDatabasePassword();
if(dbPasswd != null && !dbPasswd.isEmpty()) { if(dbPasswd != null && !dbPasswd.isEmpty()) {
dbPasswd = DatabaseUtils.decrypt(dbConfig.getDatabasePassword()); dbPasswd = DatabaseUtils.decrypt(dbConfig.getDatabasePassword());
} }
// writer.value(dbConfig.getDatabasePassword()); // writer.value(dbConfig.getDatabasePassword());
writer.value(dbPasswd); writer.writeStringField("databasePassword", dbPasswd);
writer.key("databaseSchema"); writer.writeStringField("databaseSchema", dbConfig.getDatabaseSchema());
writer.value(dbConfig.getDatabaseSchema());
writer.key("databaseUser"); writer.writeStringField("databaseUser", dbConfig.getDatabaseUser());
writer.value(dbConfig.getDatabaseUser());
writer.endObject(); writer.writeEndObject();
} }
writer.endArray(); writer.writeEndArray();
writer.endObject(); writer.writeEndObject();
writer.flush();
writer.close();
// logger.info("Saved Connection Get Response sent"); // logger.info("Saved Connection Get Response sent");
} finally { } finally {
w.flush(); w.flush();

View File

@ -36,13 +36,15 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseConfiguration;
import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseService;
import com.google.refine.extension.database.DatabaseServiceException; import com.google.refine.extension.database.DatabaseServiceException;
import com.google.refine.util.ParsingUtilities;
@ -69,7 +71,7 @@ public class TestConnectCommand extends DatabaseCommand {
response.setHeader("Content-Type", "application/json"); response.setHeader("Content-Type", "application/json");
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
try { try {
@ -77,20 +79,18 @@ public class TestConnectCommand extends DatabaseCommand {
.testConnection(databaseConfiguration); .testConnection(databaseConfiguration);
response.setStatus(HttpStatus.SC_OK); response.setStatus(HttpStatus.SC_OK);
writer.object(); writer.writeStartObject();
writer.key("connectionResult"); writer.writeBooleanField("connectionResult", connectionTestResult);
writer.value(connectionTestResult); writer.writeStringField("code", "ok");
writer.key("code"); writer.writeEndObject();
writer.value("ok");
writer.endObject();
} catch (DatabaseServiceException e) { } catch (DatabaseServiceException e) {
logger.error("TestConnectCommand::Post::DatabaseServiceException::{}", e); logger.error("TestConnectCommand::Post::DatabaseServiceException::{}", e);
sendError(HttpStatus.SC_UNAUTHORIZED,response, writer, e); sendError(HttpStatus.SC_UNAUTHORIZED,response, e);
} finally { } finally {
// writer.endObject(); writer.flush();
// w.flush(); writer.close();
w.close(); w.close();
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -36,16 +36,17 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.codehaus.jackson.map.ObjectMapper;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
//import com.google.refine.ProjectManager; //import com.google.refine.ProjectManager;
import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseConfiguration;
import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseService;
import com.google.refine.extension.database.DatabaseServiceException; import com.google.refine.extension.database.DatabaseServiceException;
import com.google.refine.extension.database.model.DatabaseInfo; import com.google.refine.extension.database.model.DatabaseInfo;
import com.google.refine.util.ParsingUtilities;
public class TestQueryCommand extends DatabaseCommand { public class TestQueryCommand extends DatabaseCommand {
@ -70,7 +71,7 @@ public class TestQueryCommand extends DatabaseCommand {
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json"); response.setHeader("Content-Type", "application/json");
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
try { try {
DatabaseInfo databaseInfo = DatabaseService.get(dbConfig.getDatabaseType()) DatabaseInfo databaseInfo = DatabaseService.get(dbConfig.getDatabaseType())
@ -83,22 +84,22 @@ public class TestQueryCommand extends DatabaseCommand {
logger.debug("TestQueryCommand::Post::Result::{} " ,jsonStr); logger.debug("TestQueryCommand::Post::Result::{} " ,jsonStr);
} }
writer.object(); writer.writeStartObject();
writer.key("code"); writer.writeStringField("code", "ok");
writer.value("ok"); writer.writeStringField("QueryResult", jsonStr);
writer.key("QueryResult"); writer.writeEndObject();
writer.value(jsonStr);
writer.endObject();
} catch (DatabaseServiceException e) { } catch (DatabaseServiceException e) {
logger.error("TestQueryCommand::Post::DatabaseServiceException::{}", e); logger.error("TestQueryCommand::Post::DatabaseServiceException::{}", e);
sendError(HttpStatus.SC_BAD_REQUEST, response, writer, e); sendError(HttpStatus.SC_BAD_REQUEST, response, e);
} catch (Exception e) { } catch (Exception e) {
logger.error("TestQueryCommand::Post::Exception::{}", e); logger.error("TestQueryCommand::Post::Exception::{}", e);
sendError(HttpStatus.SC_BAD_REQUEST,response, writer, e); sendError(HttpStatus.SC_BAD_REQUEST,response, e);
} finally { } finally {
writer.flush();
writer.close();
w.close(); w.close();
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -12,8 +12,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.testng.Assert; import org.testng.Assert;
@ -24,7 +22,9 @@ import org.testng.annotations.Optional;
import org.testng.annotations.Parameters; import org.testng.annotations.Parameters;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.ProjectMetadata;
import com.google.refine.RefineServlet; import com.google.refine.RefineServlet;
import com.google.refine.extension.database.mysql.MySQLDatabaseService; import com.google.refine.extension.database.mysql.MySQLDatabaseService;
import com.google.refine.extension.database.stub.RefineDbServletStub; import com.google.refine.extension.database.stub.RefineDbServletStub;
@ -32,7 +32,7 @@ import com.google.refine.importing.ImportingJob;
import com.google.refine.importing.ImportingManager; import com.google.refine.importing.ImportingManager;
import com.google.refine.io.FileProjectManager; import com.google.refine.io.FileProjectManager;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.ParsingUtilities;
@ -60,7 +60,7 @@ public class DatabaseImportControllerTest extends DBExtensionTests{
private DatabaseImportController SUT = null; private DatabaseImportController SUT = null;
@BeforeMethod @BeforeMethod
public void setUp() throws JSONException, IOException { public void setUp() throws IOException {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
File dir = DBExtensionTestUtils.createTempDirectory("OR_DBExtension_Test_WorkspaceDir"); File dir = DBExtensionTestUtils.createTempDirectory("OR_DBExtension_Test_WorkspaceDir");
@ -102,10 +102,9 @@ public class DatabaseImportControllerTest extends DBExtensionTests{
SUT.doGet(request, response); SUT.doGet(request, response);
String result = sw.getBuffer().toString().trim(); String result = sw.getBuffer().toString().trim();
JSONObject json = new JSONObject(result); ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
String code = json.get("status").asText();
String code = json.getString("status"); String message = json.get("message").asText();
String message = json.getString("message");
Assert.assertNotNull(code); Assert.assertNotNull(code);
Assert.assertNotNull(message); Assert.assertNotNull(message);
Assert.assertEquals(code, "error"); Assert.assertEquals(code, "error");
@ -119,7 +118,7 @@ public class DatabaseImportControllerTest extends DBExtensionTests{
} }
@Test @Test
public void testDoPostInvalidSubCommand() throws IOException, ServletException, JSONException { public void testDoPostInvalidSubCommand() throws IOException, ServletException {
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw); PrintWriter pw = new PrintWriter(sw);
when(request.getQueryString()).thenReturn( when(request.getQueryString()).thenReturn(
@ -130,10 +129,10 @@ public class DatabaseImportControllerTest extends DBExtensionTests{
SUT.doPost(request, response); SUT.doPost(request, response);
String result = sw.getBuffer().toString().trim(); String result = sw.getBuffer().toString().trim();
JSONObject json = new JSONObject(result); ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
String code = json.getString("status"); String code = json.get("status").asText();
String message = json.getString("message"); String message = json.get("message").asText();
Assert.assertNotNull(code); Assert.assertNotNull(code);
Assert.assertNotNull(message); Assert.assertNotNull(message);
Assert.assertEquals(code, "error"); Assert.assertEquals(code, "error");
@ -143,7 +142,7 @@ public class DatabaseImportControllerTest extends DBExtensionTests{
@Test @Test
public void testDoPostInitializeParser() throws ServletException, IOException, JSONException { public void testDoPostInitializeParser() throws ServletException, IOException {
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw); PrintWriter pw = new PrintWriter(sw);
@ -155,15 +154,15 @@ public class DatabaseImportControllerTest extends DBExtensionTests{
SUT.doPost(request, response); SUT.doPost(request, response);
String result = sw.getBuffer().toString().trim(); String result = sw.getBuffer().toString().trim();
JSONObject json = new JSONObject(result); ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
String status = json.getString("status"); String status = json.get("status").asText();
//System.out.println("json::" + json); //System.out.println("json::" + json);
Assert.assertEquals(status, "ok"); Assert.assertEquals(status, "ok");
} }
@Test @Test
public void testDoPostParsePreview() throws IOException, ServletException, JSONException { public void testDoPostParsePreview() throws IOException, ServletException {
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw); PrintWriter pw = new PrintWriter(sw);
@ -188,15 +187,15 @@ public class DatabaseImportControllerTest extends DBExtensionTests{
SUT.doPost(request, response); SUT.doPost(request, response);
String result = sw.getBuffer().toString().trim(); String result = sw.getBuffer().toString().trim();
JSONObject json = new JSONObject(result); ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
String status = json.getString("status"); String status = json.get("status").asText();
//System.out.println("json::" + json); //System.out.println("json::" + json);
Assert.assertEquals(status, "ok"); Assert.assertEquals(status, "ok");
} }
@Test @Test
public void testDoPostCreateProject() throws IOException, ServletException, JSONException { public void testDoPostCreateProject() throws IOException, ServletException {
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw); PrintWriter pw = new PrintWriter(sw);
@ -222,9 +221,9 @@ public class DatabaseImportControllerTest extends DBExtensionTests{
SUT.doPost(request, response); SUT.doPost(request, response);
String result = sw.getBuffer().toString().trim(); String result = sw.getBuffer().toString().trim();
JSONObject json = new JSONObject(result); ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
String status = json.getString("status"); String status = json.get("status").asText();
//System.out.println("json::" + json); //System.out.println("json::" + json);
Assert.assertEquals(status, "ok"); Assert.assertEquals(status, "ok");
} }

View File

@ -11,8 +11,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.testng.Assert; import org.testng.Assert;
@ -21,10 +19,12 @@ import org.testng.annotations.Optional;
import org.testng.annotations.Parameters; import org.testng.annotations.Parameters;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.extension.database.DBExtensionTests; import com.google.refine.extension.database.DBExtensionTests;
import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseConfiguration;
import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseService;
import com.google.refine.extension.database.mysql.MySQLDatabaseService; import com.google.refine.extension.database.mysql.MySQLDatabaseService;
import com.google.refine.util.ParsingUtilities;
@Test(groups = { "requiresMySQL" }) @Test(groups = { "requiresMySQL" })
@ -67,7 +67,7 @@ public class ConnectCommandTest extends DBExtensionTests {
@Test @Test
public void testDoPost() throws IOException, ServletException, JSONException { public void testDoPost() throws IOException, ServletException {
when(request.getParameter("databaseType")).thenReturn(MySQLDatabaseService.DB_NAME); when(request.getParameter("databaseType")).thenReturn(MySQLDatabaseService.DB_NAME);
when(request.getParameter("databaseServer")).thenReturn(testDbConfig.getDatabaseHost()); when(request.getParameter("databaseServer")).thenReturn(testDbConfig.getDatabaseHost());
@ -85,12 +85,12 @@ public class ConnectCommandTest extends DBExtensionTests {
connectCommand.doPost(request, response); connectCommand.doPost(request, response);
String result = sw.getBuffer().toString().trim(); String result = sw.getBuffer().toString().trim();
JSONObject json = new JSONObject(result); ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
String code = json.getString("code"); String code = json.get("code").asText();
Assert.assertEquals(code, "ok"); Assert.assertEquals(code, "ok");
String databaseInfo = json.getString("databaseInfo"); String databaseInfo = json.get("databaseInfo").asText();
Assert.assertNotNull(databaseInfo); Assert.assertNotNull(databaseInfo);
} }

View File

@ -10,8 +10,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.testng.Assert; import org.testng.Assert;
@ -20,10 +18,12 @@ import org.testng.annotations.Optional;
import org.testng.annotations.Parameters; import org.testng.annotations.Parameters;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.extension.database.DBExtensionTests; import com.google.refine.extension.database.DBExtensionTests;
import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseConfiguration;
import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseService;
import com.google.refine.extension.database.mysql.MySQLDatabaseService; import com.google.refine.extension.database.mysql.MySQLDatabaseService;
import com.google.refine.util.ParsingUtilities;
@Test(groups = { "requiresMySQL" }) @Test(groups = { "requiresMySQL" })
public class ExecuteQueryCommandTest extends DBExtensionTests { public class ExecuteQueryCommandTest extends DBExtensionTests {
@ -63,7 +63,7 @@ public class ExecuteQueryCommandTest extends DBExtensionTests {
} }
@Test @Test
public void testDoPost() throws IOException, ServletException, JSONException { public void testDoPost() throws IOException, ServletException {
when(request.getParameter("databaseType")).thenReturn(testDbConfig.getDatabaseType()); when(request.getParameter("databaseType")).thenReturn(testDbConfig.getDatabaseType());
when(request.getParameter("databaseServer")).thenReturn(testDbConfig.getDatabaseHost()); when(request.getParameter("databaseServer")).thenReturn(testDbConfig.getDatabaseHost());
@ -84,12 +84,12 @@ public class ExecuteQueryCommandTest extends DBExtensionTests {
executeQueryCommand.doPost(request, response); executeQueryCommand.doPost(request, response);
String result = sw.getBuffer().toString().trim(); String result = sw.getBuffer().toString().trim();
JSONObject json = new JSONObject(result); ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
String code = json.getString("code"); String code = json.get("code").asText();
Assert.assertEquals(code, "ok"); Assert.assertEquals(code, "ok");
String queryResult = json.getString("QueryResult"); String queryResult = json.get("QueryResult").asText();
Assert.assertNotNull(queryResult); Assert.assertNotNull(queryResult);
} }

View File

@ -11,9 +11,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.testng.Assert; import org.testng.Assert;
@ -24,7 +21,10 @@ import org.testng.annotations.Optional;
import org.testng.annotations.Parameters; import org.testng.annotations.Parameters;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.ProjectMetadata;
import com.google.refine.RefineServlet; import com.google.refine.RefineServlet;
import com.google.refine.extension.database.DBExtensionTestUtils; import com.google.refine.extension.database.DBExtensionTestUtils;
import com.google.refine.extension.database.DBExtensionTests; import com.google.refine.extension.database.DBExtensionTests;
@ -35,7 +35,7 @@ import com.google.refine.extension.database.stub.RefineDbServletStub;
import com.google.refine.importing.ImportingManager; import com.google.refine.importing.ImportingManager;
import com.google.refine.io.FileProjectManager; import com.google.refine.io.FileProjectManager;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.metadata.ProjectMetadata; import com.google.refine.util.ParsingUtilities;
public class SavedConnectionCommandTest extends DBExtensionTests{ public class SavedConnectionCommandTest extends DBExtensionTests{
@ -59,7 +59,7 @@ public class SavedConnectionCommandTest extends DBExtensionTests{
private SavedConnectionCommand SUT = null; private SavedConnectionCommand SUT = null;
@BeforeMethod @BeforeMethod
public void setUp() throws JSONException, IOException { public void setUp() throws IOException {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
File dir = DBExtensionTestUtils.createTempDirectory("OR_DBExtension_Test_WorkspaceDir"); File dir = DBExtensionTestUtils.createTempDirectory("OR_DBExtension_Test_WorkspaceDir");
@ -136,7 +136,7 @@ public class SavedConnectionCommandTest extends DBExtensionTests{
} }
@Test @Test
public void testDoPost() throws IOException, ServletException, JSONException { public void testDoPost() throws IOException, ServletException {
when(request.getParameter("connectionName")).thenReturn("test-db-name"); when(request.getParameter("connectionName")).thenReturn("test-db-name");
when(request.getParameter("databaseType")).thenReturn(MySQLDatabaseService.DB_NAME); when(request.getParameter("databaseType")).thenReturn(MySQLDatabaseService.DB_NAME);
@ -155,18 +155,18 @@ public class SavedConnectionCommandTest extends DBExtensionTests{
String result = sw.getBuffer().toString().trim(); String result = sw.getBuffer().toString().trim();
JSONObject json = new JSONObject(result); ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
JSONArray savedConnections = json.getJSONArray("savedConnections"); ArrayNode savedConnections = (ArrayNode) json.get("savedConnections");
Assert.assertNotNull(savedConnections); Assert.assertNotNull(savedConnections);
int len = savedConnections.length(); int len = savedConnections.size();
Assert.assertEquals(len, 1); Assert.assertEquals(len, 1);
} }
@Test @Test
public void testDoGet() throws IOException, ServletException, JSONException { public void testDoGet() throws IOException, ServletException {
String testDbName = "testLocalDb"; String testDbName = "testLocalDb";
//add saved connection //add saved connection
saveDatabaseConfiguration(testDbName); saveDatabaseConfiguration(testDbName);
@ -187,21 +187,20 @@ public class SavedConnectionCommandTest extends DBExtensionTests{
SUT.doGet(request, response); SUT.doGet(request, response);
JSONObject json = new JSONObject(sw.getBuffer().toString().trim()); ObjectNode json = ParsingUtilities.mapper.readValue(sw.getBuffer().toString().trim(), ObjectNode.class);
JSONArray savedConnections = json.getJSONArray("savedConnections"); ArrayNode savedConnections = (ArrayNode) json.get("savedConnections");
Assert.assertNotNull(savedConnections); Assert.assertNotNull(savedConnections);
Assert.assertEquals(savedConnections.length(), 1); Assert.assertEquals(savedConnections.size(), 1);
JSONObject sc = (JSONObject)savedConnections.get(0); ObjectNode sc = (ObjectNode)savedConnections.get(0);
// System.out.println("sc" + sc); String connName = sc.get("connectionName").asText();
String connName = sc.getString("connectionName");
Assert.assertEquals(connName, testDbName); Assert.assertEquals(connName, testDbName);
} }
@Test @Test
public void testDoPut() throws IOException, ServletException, JSONException { public void testDoPut() throws IOException, ServletException {
String testDbName = "testLocalDb"; String testDbName = "testLocalDb";
saveDatabaseConfiguration(testDbName); saveDatabaseConfiguration(testDbName);
@ -223,15 +222,15 @@ public class SavedConnectionCommandTest extends DBExtensionTests{
SUT.doPut(request, response); SUT.doPut(request, response);
JSONObject json = new JSONObject(sw.getBuffer().toString().trim()); ObjectNode json = ParsingUtilities.mapper.readValue(sw.getBuffer().toString().trim(), ObjectNode.class);
JSONArray savedConnections = json.getJSONArray("savedConnections"); ArrayNode savedConnections = (ArrayNode) json.get("savedConnections");
Assert.assertNotNull(savedConnections); Assert.assertNotNull(savedConnections);
Assert.assertEquals(savedConnections.length(), 1); Assert.assertEquals(savedConnections.size(), 1);
JSONObject sc = (JSONObject)savedConnections.get(0); ObjectNode sc = (ObjectNode)savedConnections.get(0);
System.out.println("sc" + sc); System.out.println("sc" + sc);
String newDbHost = sc.getString("databaseHost"); String newDbHost = sc.get("databaseHost").asText();
Assert.assertEquals(newDbHost, newHost); Assert.assertEquals(newDbHost, newHost);
} }
@ -249,11 +248,11 @@ public class SavedConnectionCommandTest extends DBExtensionTests{
when(request.getParameter("connectionName")).thenReturn(testDbName); when(request.getParameter("connectionName")).thenReturn(testDbName);
SUT.doDelete(request, response); SUT.doDelete(request, response);
JSONObject json = new JSONObject(sw.getBuffer().toString().trim()); ObjectNode json = ParsingUtilities.mapper.readValue(sw.getBuffer().toString().trim(), ObjectNode.class);
JSONArray savedConnections = json.getJSONArray("savedConnections"); ArrayNode savedConnections = (ArrayNode) json.get("savedConnections");
Assert.assertNotNull(savedConnections); Assert.assertNotNull(savedConnections);
Assert.assertEquals(savedConnections.length(), 0); Assert.assertEquals(savedConnections.size(), 0);
} catch (Exception e) { } catch (Exception e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
@ -279,7 +278,7 @@ public class SavedConnectionCommandTest extends DBExtensionTests{
// String result = sw.getBuffer().toString().trim(); // String result = sw.getBuffer().toString().trim();
JSONObject json = new JSONObject(); ObjectNode json = ParsingUtilities.mapper.createObjectNode();
Assert.assertNotNull(json); Assert.assertNotNull(json);

View File

@ -10,8 +10,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.testng.Assert; import org.testng.Assert;
@ -20,10 +18,12 @@ import org.testng.annotations.Optional;
import org.testng.annotations.Parameters; import org.testng.annotations.Parameters;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.extension.database.DBExtensionTests; import com.google.refine.extension.database.DBExtensionTests;
import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseConfiguration;
import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseService;
import com.google.refine.extension.database.mysql.MySQLDatabaseService; import com.google.refine.extension.database.mysql.MySQLDatabaseService;
import com.google.refine.util.ParsingUtilities;
@Test(groups = { "requiresMySQL" }) @Test(groups = { "requiresMySQL" })
@ -66,7 +66,7 @@ public class TestConnectCommandTest extends DBExtensionTests{
@Test @Test
public void testDoPost() throws IOException, ServletException, JSONException { public void testDoPost() throws IOException, ServletException {
when(request.getParameter("databaseType")).thenReturn(MySQLDatabaseService.DB_NAME); when(request.getParameter("databaseType")).thenReturn(MySQLDatabaseService.DB_NAME);
when(request.getParameter("databaseServer")).thenReturn(testDbConfig.getDatabaseHost()); when(request.getParameter("databaseServer")).thenReturn(testDbConfig.getDatabaseHost());
@ -86,9 +86,9 @@ public class TestConnectCommandTest extends DBExtensionTests{
connectCommand.doPost(request, response); connectCommand.doPost(request, response);
String result = sw.getBuffer().toString().trim(); String result = sw.getBuffer().toString().trim();
JSONObject json = new JSONObject(result); ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
String code = json.getString("code"); String code = json.get("code").asText();
Assert.assertEquals(code, "ok"); Assert.assertEquals(code, "ok");
} }

View File

@ -10,8 +10,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.testng.Assert; import org.testng.Assert;
@ -20,10 +18,12 @@ import org.testng.annotations.Optional;
import org.testng.annotations.Parameters; import org.testng.annotations.Parameters;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.extension.database.DBExtensionTests; import com.google.refine.extension.database.DBExtensionTests;
import com.google.refine.extension.database.DatabaseConfiguration; import com.google.refine.extension.database.DatabaseConfiguration;
import com.google.refine.extension.database.DatabaseService; import com.google.refine.extension.database.DatabaseService;
import com.google.refine.extension.database.mysql.MySQLDatabaseService; import com.google.refine.extension.database.mysql.MySQLDatabaseService;
import com.google.refine.util.ParsingUtilities;
@Test(groups = { "requiresMySQL" }) @Test(groups = { "requiresMySQL" })
public class TestQueryCommandTest extends DBExtensionTests { public class TestQueryCommandTest extends DBExtensionTests {
@ -64,7 +64,7 @@ public class TestQueryCommandTest extends DBExtensionTests {
@Test @Test
public void testDoPost() throws IOException, ServletException, JSONException { public void testDoPost() throws IOException, ServletException {
when(request.getParameter("databaseType")).thenReturn(testDbConfig.getDatabaseType()); when(request.getParameter("databaseType")).thenReturn(testDbConfig.getDatabaseType());
when(request.getParameter("databaseServer")).thenReturn(testDbConfig.getDatabaseHost()); when(request.getParameter("databaseServer")).thenReturn(testDbConfig.getDatabaseHost());
@ -85,12 +85,12 @@ public class TestQueryCommandTest extends DBExtensionTests {
executeQueryCommand.doPost(request, response); executeQueryCommand.doPost(request, response);
String result = sw.getBuffer().toString().trim(); String result = sw.getBuffer().toString().trim();
JSONObject json = new JSONObject(result); ObjectNode json = ParsingUtilities.mapper.readValue(result, ObjectNode.class);
String code = json.getString("code"); String code = json.get("code").asText();
Assert.assertEquals(code, "ok"); Assert.assertEquals(code, "ok");
String queryResult = json.getString("QueryResult"); String queryResult = json.get("QueryResult").asText();
Assert.assertNotNull(queryResult); Assert.assertNotNull(queryResult);
} }

View File

@ -40,7 +40,6 @@ import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpResponse; import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpTransport; import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.refine.commands.Command; import com.google.refine.commands.Command;
public class DeAuthorizeCommand extends Command { public class DeAuthorizeCommand extends Command {

View File

@ -32,18 +32,17 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.json.JSONObject; import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.api.services.fusiontables.Fusiontables; import com.google.api.services.fusiontables.Fusiontables;
import com.google.api.services.fusiontables.model.Column; import com.google.api.services.fusiontables.model.Column;
import com.google.api.services.fusiontables.model.Sqlresponse; import com.google.api.services.fusiontables.model.Sqlresponse;
import com.google.api.services.fusiontables.model.Table; import com.google.api.services.fusiontables.model.Table;
import com.google.refine.ProjectMetadata;
import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importers.TabularImportingParserBase;
import com.google.refine.importers.TabularImportingParserBase.TableDataReader; import com.google.refine.importers.TabularImportingParserBase.TableDataReader;
import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingJob;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.metadata.ProjectMetadata;
import com.google.refine.util.JSONUtilities; import com.google.refine.util.JSONUtilities;
/** /**
@ -60,7 +59,7 @@ public class FusionTableImporter {
ProjectMetadata metadata, ProjectMetadata metadata,
final ImportingJob job, final ImportingJob job,
int limit, int limit,
JSONObject options, ObjectNode options,
List<Exception> exceptions) { List<Exception> exceptions) {
Fusiontables service = FusionTableHandler.getFusionTablesService(token); Fusiontables service = FusionTableHandler.getFusionTablesService(token);
@ -206,7 +205,7 @@ public class FusionTableImporter {
ProjectMetadata metadata, ProjectMetadata metadata,
final ImportingJob job, final ImportingJob job,
int limit, int limit,
JSONObject options, ObjectNode options,
List<Exception> exceptions) { List<Exception> exceptions) {
String docUrlString = JSONUtilities.getString(options, "docUrl", null); String docUrlString = JSONUtilities.getString(options, "docUrl", null);

View File

@ -4,13 +4,11 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.json.JSONObject; import com.fasterxml.jackson.databind.JsonNode;
import com.google.api.client.http.AbstractInputStreamContent; import com.google.api.client.http.AbstractInputStreamContent;
import com.google.api.client.http.ByteArrayContent; import com.google.api.client.http.ByteArrayContent;
import com.google.api.client.http.HttpResponseException; import com.google.api.client.http.HttpResponseException;
import com.google.api.services.fusiontables.Fusiontables; import com.google.api.services.fusiontables.Fusiontables;
import com.google.refine.exporters.TabularSerializer; import com.google.refine.exporters.TabularSerializer;
final class FusionTableSerializer implements TabularSerializer { final class FusionTableSerializer implements TabularSerializer {
@ -31,7 +29,7 @@ final class FusionTableSerializer implements TabularSerializer {
} }
@Override @Override
public void startFile(JSONObject options) { public void startFile(JsonNode options) {
} }
@Override @Override

View File

@ -6,20 +6,19 @@ import java.net.URL;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.model.Sheet; import com.google.api.services.sheets.v4.model.Sheet;
import com.google.api.services.sheets.v4.model.Spreadsheet; import com.google.api.services.sheets.v4.model.Spreadsheet;
import com.google.api.services.sheets.v4.model.ValueRange; import com.google.api.services.sheets.v4.model.ValueRange;
import com.google.refine.ProjectMetadata;
import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importers.TabularImportingParserBase;
import com.google.refine.importers.TabularImportingParserBase.TableDataReader; import com.google.refine.importers.TabularImportingParserBase.TableDataReader;
import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingJob;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.metadata.ProjectMetadata;
import com.google.refine.util.JSONUtilities; import com.google.refine.util.JSONUtilities;
public class GDataImporter { public class GDataImporter {
@ -31,7 +30,7 @@ public class GDataImporter {
ProjectMetadata metadata, ProjectMetadata metadata,
final ImportingJob job, final ImportingJob job,
int limit, int limit,
JSONObject options, ObjectNode options,
List<Exception> exceptions) throws IOException { List<Exception> exceptions) throws IOException {
String docType = JSONUtilities.getString(options, "docType", null); String docType = JSONUtilities.getString(options, "docType", null);
@ -64,7 +63,7 @@ public class GDataImporter {
ProjectMetadata metadata, ProjectMetadata metadata,
final ImportingJob job, final ImportingJob job,
int limit, int limit,
JSONObject options, ObjectNode options,
List<Exception> exceptions) { List<Exception> exceptions) {
String docUrlString = JSONUtilities.getString(options, "docUrl", null); String docUrlString = JSONUtilities.getString(options, "docUrl", null);
@ -100,7 +99,7 @@ public class GDataImporter {
URL docURL, URL docURL,
int worksheetIndex, int worksheetIndex,
int limit, int limit,
JSONObject options, ObjectNode options,
List<Exception> exceptions) { List<Exception> exceptions) {
try { try {

View File

@ -11,13 +11,12 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.api.services.drive.Drive; import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File; import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList; import com.google.api.services.drive.model.FileList;
@ -28,8 +27,8 @@ import com.google.api.services.fusiontables.model.TableList;
import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.model.Sheet; import com.google.api.services.sheets.v4.model.Sheet;
import com.google.api.services.sheets.v4.model.Spreadsheet; import com.google.api.services.sheets.v4.model.Spreadsheet;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.ProjectMetadata;
import com.google.refine.RefineServlet; import com.google.refine.RefineServlet;
import com.google.refine.commands.HttpUtilities; import com.google.refine.commands.HttpUtilities;
import com.google.refine.importing.DefaultImportingController; import com.google.refine.importing.DefaultImportingController;
@ -37,7 +36,6 @@ import com.google.refine.importing.ImportingController;
import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingJob;
import com.google.refine.importing.ImportingManager; import com.google.refine.importing.ImportingManager;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.metadata.ProjectMetadata;
import com.google.refine.util.JSONUtilities; import com.google.refine.util.JSONUtilities;
import com.google.refine.util.ParsingUtilities; import com.google.refine.util.ParsingUtilities;
@ -86,11 +84,10 @@ public class GDataImportingController implements ImportingController {
} }
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
try { try {
writer.object(); writer.writeStartObject();
writer.key("documents"); writer.writeArrayFieldStart("documents");
writer.array();
try { try {
listSpreadsheets(GoogleAPIExtension.getDriveService(token), writer); listSpreadsheets(GoogleAPIExtension.getDriveService(token), writer);
@ -98,50 +95,52 @@ public class GDataImportingController implements ImportingController {
} catch (Exception e) { } catch (Exception e) {
logger.error("doListDocuments exception:" + ExceptionUtils.getStackTrace(e)); logger.error("doListDocuments exception:" + ExceptionUtils.getStackTrace(e));
} finally { } finally {
writer.endArray(); writer.writeEndArray();
writer.endObject(); writer.writeEndObject();
} }
} catch (JSONException e) { } catch (IOException e) {
throw new ServletException(e); throw new ServletException(e);
} finally { } finally {
writer.flush();
writer.close();
w.flush(); w.flush();
w.close(); w.close();
} }
} }
private void listSpreadsheets(Drive drive, JSONWriter writer) private void listSpreadsheets(Drive drive, JsonGenerator writer)
throws IOException, JSONException { throws IOException {
com.google.api.services.drive.Drive.Files.List files = drive.files().list(); com.google.api.services.drive.Drive.Files.List files = drive.files().list();
files.setQ("mimeType = 'application/vnd.google-apps.spreadsheet'"); files.setQ("mimeType = 'application/vnd.google-apps.spreadsheet'");
files.setFields("nextPageToken, files(id, name, webViewLink, owners, modifiedTime)"); files.setFields("nextPageToken, files(id, name, webViewLink, owners, modifiedTime)");
FileList fileList = files.execute(); FileList fileList = files.execute();
for (File entry : fileList.getFiles()) { for (File entry : fileList.getFiles()) {
writer.object(); writer.writeStartObject();
writer.key("docId"); writer.value(entry.getId()); writer.writeStringField("docId", entry.getId());
writer.key("docLink"); writer.value(entry.getWebViewLink()); writer.writeStringField("docLink", entry.getWebViewLink());
writer.key("docSelfLink"); writer.value(entry.getWebViewLink()); writer.writeStringField("docSelfLink", entry.getWebViewLink());
writer.key("title"); writer.value(entry.getName()); writer.writeStringField("title", entry.getName());
writer.key("type"); writer.value("spreadsheet"); writer.writeStringField("type", "spreadsheet");
com.google.api.client.util.DateTime updated = entry.getModifiedTime(); com.google.api.client.util.DateTime updated = entry.getModifiedTime();
if (updated != null) { if (updated != null) {
writer.key("updated"); writer.value(updated.toString()); writer.writeStringField("updated", updated.toString());
} }
writer.key("authors"); writer.array(); writer.writeArrayFieldStart("authors");
for (User user : entry.getOwners()) { for (User user : entry.getOwners()) {
writer.value(user.getDisplayName()); writer.writeString(user.getDisplayName());
} }
writer.endArray(); writer.writeEndArray();
writer.endObject(); writer.writeEndObject();
} }
} }
private void listFusionTables(Fusiontables service, JSONWriter writer) private void listFusionTables(Fusiontables service, JsonGenerator writer)
throws IOException, JSONException { throws IOException {
Fusiontables.Table.List listTables = service.table().list(); Fusiontables.Table.List listTables = service.table().list();
TableList tablelist = listTables.execute(); TableList tablelist = listTables.execute();
@ -155,13 +154,13 @@ public class GDataImportingController implements ImportingController {
String link = "https://www.google.com/fusiontables/DataSource?docid=" + id; String link = "https://www.google.com/fusiontables/DataSource?docid=" + id;
// Add JSON object to our stream // Add JSON object to our stream
writer.object(); writer.writeStartObject();
writer.key("docId"); writer.value(id); writer.writeStringField("docId", id);
writer.key("docLink"); writer.value(link); writer.writeStringField("docLink", link);
writer.key("docSelfLink"); writer.value(link); writer.writeStringField("docSelfLink", link);
writer.key("title"); writer.value(name); writer.writeStringField("title", name);
writer.key("type"); writer.value("table"); writer.writeStringField("type", "table");
writer.endObject(); writer.writeEndObject();
} }
} }
@ -171,8 +170,8 @@ public class GDataImportingController implements ImportingController {
String token = TokenCookie.getToken(request); String token = TokenCookie.getToken(request);
String type = parameters.getProperty("docType"); String type = parameters.getProperty("docType");
String urlString = parameters.getProperty("docUrl"); String urlString = parameters.getProperty("docUrl");
JSONObject result = new JSONObject(); ObjectNode result = ParsingUtilities.mapper.createObjectNode();
JSONObject options = new JSONObject(); ObjectNode options = ParsingUtilities.mapper.createObjectNode();
JSONUtilities.safePut(result, "status", "ok"); JSONUtilities.safePut(result, "status", "ok");
JSONUtilities.safePut(result, "options", options); JSONUtilities.safePut(result, "options", options);
@ -181,7 +180,7 @@ public class GDataImportingController implements ImportingController {
JSONUtilities.safePut(options, "storeBlankCellsAsNulls", true); JSONUtilities.safePut(options, "storeBlankCellsAsNulls", true);
if ("spreadsheet".equals(type)) { if ("spreadsheet".equals(type)) {
JSONArray worksheets = new JSONArray(); ArrayNode worksheets = ParsingUtilities.mapper.createArrayNode();
// extract spreadSheetId from URL // extract spreadSheetId from URL
String spreadSheetId = GoogleAPIExtension.extractSpreadSheetId(urlString); String spreadSheetId = GoogleAPIExtension.extractSpreadSheetId(urlString);
@ -192,7 +191,7 @@ public class GDataImportingController implements ImportingController {
List<Sheet> worksheetEntries = List<Sheet> worksheetEntries =
getWorksheetEntriesForDoc(token, spreadSheetId); getWorksheetEntriesForDoc(token, spreadSheetId);
for (Sheet sheet : worksheetEntries) { for (Sheet sheet : worksheetEntries) {
JSONObject worksheetO = new JSONObject(); ObjectNode worksheetO = ParsingUtilities.mapper.createObjectNode();
JSONUtilities.safePut(worksheetO, "name", sheet.getProperties().getTitle()); JSONUtilities.safePut(worksheetO, "name", sheet.getProperties().getTitle());
JSONUtilities.safePut(worksheetO, "rows", sheet.getProperties().getGridProperties().getRowCount()); JSONUtilities.safePut(worksheetO, "rows", sheet.getProperties().getGridProperties().getRowCount());
JSONUtilities.safePut(worksheetO, "link", JSONUtilities.safePut(worksheetO, "link",
@ -234,8 +233,7 @@ public class GDataImportingController implements ImportingController {
} }
job.updating = true; job.updating = true;
try { ObjectNode optionObj = ParsingUtilities.evaluateJsonStringToObjectNode(
JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject(
request.getParameter("options")); request.getParameter("options"));
List<Exception> exceptions = new LinkedList<Exception>(); List<Exception> exceptions = new LinkedList<Exception>();
@ -253,36 +251,33 @@ public class GDataImportingController implements ImportingController {
); );
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
try { try {
writer.object(); writer.writeStartObject();
if (exceptions.size() == 0) { if (exceptions.size() == 0) {
job.project.update(); // update all internal models, indexes, caches, etc. job.project.update(); // update all internal models, indexes, caches, etc.
writer.key("status"); writer.value("ok"); writer.writeStringField("status", "ok");
} else { } else {
writer.key("status"); writer.value("error"); writer.writeStringField("status", "error");
writer.key("errors"); writer.writeArrayFieldStart("errors");
writer.array();
DefaultImportingController.writeErrors(writer, exceptions); DefaultImportingController.writeErrors(writer, exceptions);
writer.endArray(); writer.writeEndArray();
} }
writer.endObject(); writer.writeEndObject();
} catch (JSONException e) { } catch (IOException e) {
throw new ServletException(e); throw new ServletException(e);
} finally { } finally {
writer.flush();
writer.close();
w.flush(); w.flush();
w.close(); w.close();
} }
} catch (JSONException e) {
throw new ServletException(e);
} finally {
job.touch(); job.touch();
job.updating = false; job.updating = false;
} }
}
private void doCreateProject(HttpServletRequest request, HttpServletResponse response, Properties parameters) private void doCreateProject(HttpServletRequest request, HttpServletResponse response, Properties parameters)
throws ServletException, IOException { throws ServletException, IOException {
@ -297,8 +292,7 @@ public class GDataImportingController implements ImportingController {
} }
job.updating = true; job.updating = true;
try { final ObjectNode optionObj = ParsingUtilities.evaluateJsonStringToObjectNode(
final JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject(
request.getParameter("options")); request.getParameter("options"));
final List<Exception> exceptions = new LinkedList<Exception>(); final List<Exception> exceptions = new LinkedList<Exception>();
@ -346,8 +340,5 @@ public class GDataImportingController implements ImportingController {
}.start(); }.start();
HttpUtilities.respond(response, "ok", "done"); HttpUtilities.respond(response, "ok", "done");
} catch (JSONException e) {
throw new ServletException(e);
}
} }
} }

View File

@ -25,7 +25,6 @@ import com.google.api.services.drive.DriveScopes;
import com.google.api.services.fusiontables.FusiontablesScopes; import com.google.api.services.fusiontables.FusiontablesScopes;
import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.SheetsScopes; import com.google.api.services.sheets.v4.SheetsScopes;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.PreferenceStore;
import com.google.refine.util.ParsingUtilities; import com.google.refine.util.ParsingUtilities;

View File

@ -6,10 +6,10 @@ import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.model.AppendCellsRequest; import com.google.api.services.sheets.v4.model.AppendCellsRequest;
import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetRequest; import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetRequest;
@ -17,7 +17,6 @@ import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetResponse;
import com.google.api.services.sheets.v4.model.ExtendedValue; import com.google.api.services.sheets.v4.model.ExtendedValue;
import com.google.api.services.sheets.v4.model.Request; import com.google.api.services.sheets.v4.model.Request;
import com.google.api.services.sheets.v4.model.RowData; import com.google.api.services.sheets.v4.model.RowData;
import com.google.refine.exporters.TabularSerializer; import com.google.refine.exporters.TabularSerializer;
final class SpreadsheetSerializer implements TabularSerializer { final class SpreadsheetSerializer implements TabularSerializer {
@ -44,7 +43,7 @@ final class SpreadsheetSerializer implements TabularSerializer {
} }
@Override @Override
public void startFile(JSONObject options) { public void startFile(JsonNode options) {
} }

View File

@ -14,18 +14,17 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.apache.commons.codec.binary.Base64;
import com.fasterxml.jackson.core.JsonGenerator;
import com.google.api.client.http.FileContent; import com.google.api.client.http.FileContent;
import com.google.api.services.drive.Drive; import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File; import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.File.ContentHints; import com.google.api.services.drive.model.File.ContentHints;
import com.google.api.services.drive.model.File.ContentHints.Thumbnail; import com.google.api.services.drive.model.File.ContentHints.Thumbnail;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.commands.Command; import com.google.refine.commands.Command;
@ -34,6 +33,7 @@ import com.google.refine.commands.project.ExportRowsCommand;
import com.google.refine.exporters.CustomizableTabularExporterUtilities; import com.google.refine.exporters.CustomizableTabularExporterUtilities;
import com.google.refine.io.FileProjectManager; import com.google.refine.io.FileProjectManager;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.util.ParsingUtilities;
public class UploadCommand extends Command { public class UploadCommand extends Command {
static final Logger logger = LoggerFactory.getLogger("gdata_upload"); static final Logger logger = LoggerFactory.getLogger("gdata_upload");
@ -61,31 +61,33 @@ public class UploadCommand extends Command {
response.setHeader("Content-Type", "application/json"); response.setHeader("Content-Type", "application/json");
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
try { try {
writer.object(); writer.writeStartObject();
List<Exception> exceptions = new LinkedList<Exception>(); List<Exception> exceptions = new LinkedList<Exception>();
String url = upload(project, engine, params, token, name, exceptions); String url = upload(project, engine, params, token, name, exceptions);
if (url != null) { if (url != null) {
writer.key("status"); writer.value("ok"); writer.writeStringField("status", "ok");
writer.key("url"); writer.value(url); writer.writeStringField("url", url);
} else if (exceptions.size() == 0) { } else if (exceptions.size() == 0) {
writer.key("status"); writer.value("error"); writer.writeStringField("status", "error");
writer.key("message"); writer.value("No such format"); writer.writeStringField("message", "No such format");
} else { } else {
for (Exception e : exceptions) { for (Exception e : exceptions) {
logger.warn(e.getLocalizedMessage(), e); logger.warn(e.getLocalizedMessage(), e);
} }
writer.key("status"); writer.value("error"); writer.writeStringField("status", "error");
writer.key("message"); writer.value(exceptions.get(0).getLocalizedMessage()); writer.writeStringField("message", exceptions.get(0).getLocalizedMessage());
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
writer.key("status"); writer.value("error"); writer.writeStringField("status", "error");
writer.key("message"); writer.value(e.getMessage()); writer.writeStringField("message", e.getMessage());
} finally { } finally {
writer.endObject(); writer.writeEndObject();
writer.flush();
writer.close();
w.flush(); w.flush();
w.close(); w.close();
} }

View File

@ -37,15 +37,16 @@ import java.io.LineNumberReader;
import java.io.Reader; import java.io.Reader;
import java.util.List; import java.util.List;
import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.ProjectMetadata;
import com.google.refine.importers.TabularImportingParserBase; import com.google.refine.importers.TabularImportingParserBase;
import com.google.refine.importing.ImportingJob; import com.google.refine.importing.ImportingJob;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.metadata.ProjectMetadata;
import com.google.refine.util.JSONUtilities; import com.google.refine.util.JSONUtilities;
import com.google.refine.util.ParsingUtilities;
public class PCAxisImporter extends TabularImportingParserBase { public class PCAxisImporter extends TabularImportingParserBase {
static final Logger logger = LoggerFactory.getLogger(PCAxisImporter.class); static final Logger logger = LoggerFactory.getLogger(PCAxisImporter.class);
@ -55,9 +56,9 @@ public class PCAxisImporter extends TabularImportingParserBase {
} }
@Override @Override
public JSONObject createParserUIInitializationData( public ObjectNode createParserUIInitializationData(
ImportingJob job, List<JSONObject> fileRecords, String format) { ImportingJob job, List<ObjectNode> fileRecords, String format) {
JSONObject options = new JSONObject(); ObjectNode options = ParsingUtilities.mapper.createObjectNode();
JSONUtilities.safePut(options, "includeFileSources", fileRecords.size() > 1); JSONUtilities.safePut(options, "includeFileSources", fileRecords.size() > 1);
JSONUtilities.safePut(options, "skipDataLines", 0); JSONUtilities.safePut(options, "skipDataLines", 0);
JSONUtilities.safePut(options, "limit", -1); JSONUtilities.safePut(options, "limit", -1);
@ -72,7 +73,7 @@ public class PCAxisImporter extends TabularImportingParserBase {
String fileSource, String fileSource,
Reader reader, Reader reader,
int limit, int limit,
JSONObject options, ObjectNode options,
List<Exception> exceptions List<Exception> exceptions
) { ) {
LineNumberReader lnReader = new LineNumberReader(reader); LineNumberReader lnReader = new LineNumberReader(reader);

View File

@ -5,7 +5,9 @@ import java.io.Writer;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONWriter; import com.fasterxml.jackson.core.JsonGenerator;
import com.google.refine.util.ParsingUtilities;
public class CommandUtilities { public class CommandUtilities {
@ -21,11 +23,13 @@ public class CommandUtilities {
public static void respondError(HttpServletResponse response, String errorMessage) public static void respondError(HttpServletResponse response, String errorMessage)
throws IOException { throws IOException {
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
writer.object(); writer.writeStartObject();
writer.key("code"); writer.value("error"); writer.writeStringField("code", "error");
writer.key("message"); writer.value(errorMessage); writer.writeStringField("message", errorMessage);
writer.endObject(); writer.writeEndObject();
writer.flush();
writer.close();
w.flush(); w.flush();
w.close(); w.close();
} }

View File

@ -24,17 +24,18 @@
package org.openrefine.wikidata.commands; package org.openrefine.wikidata.commands;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.Writer;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONWriter;
import org.openrefine.wikidata.editing.ConnectionManager; import org.openrefine.wikidata.editing.ConnectionManager;
import com.fasterxml.jackson.core.JsonGenerator;
import com.google.refine.commands.Command; import com.google.refine.commands.Command;
import com.google.refine.util.ParsingUtilities;
public class LoginCommand extends Command { public class LoginCommand extends Command {
@ -53,20 +54,17 @@ public class LoginCommand extends Command {
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json"); response.setHeader("Content-Type", "application/json");
StringWriter sb = new StringWriter(2048); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(sb); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
try { writer.writeStartObject();
writer.object(); writer.writeBooleanField("logged_in", manager.isLoggedIn());
writer.key("logged_in"); writer.writeStringField("username", manager.getUsername());
writer.value(manager.isLoggedIn()); writer.writeEndObject();
writer.key("username"); writer.flush();
writer.value(manager.getUsername()); writer.close();
writer.endObject(); w.flush();
} catch (JSONException e) { w.close();
logger.error(e.getMessage());
}
respond(response, sb.toString());
} }
@Override @Override

View File

@ -0,0 +1,68 @@
package org.openrefine.wikidata.commands;
import java.util.List;
import org.openrefine.wikidata.qa.QAWarning;
import org.openrefine.wikidata.qa.QAWarning.Severity;
import org.openrefine.wikidata.updates.ItemUpdate;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class PreviewResults {
protected List<QAWarning> warnings;
protected Severity maxSeverity;
protected int nbWarnings;
protected int editCount;
protected List<ItemUpdate> editsPreview;
@JsonProperty("warnings")
public List<QAWarning> getWarnings() {
return warnings;
}
@JsonProperty("max_severity")
public Severity getMaxSeverity() {
return maxSeverity;
}
@JsonProperty("nb_warnings")
public int getNbWarnings() {
return nbWarnings;
}
@JsonProperty("edit_count")
public int getEditCount() {
return editCount;
}
@JsonProperty("edits_preview")
public List<ItemUpdate> getEditsPreview() {
return editsPreview;
}
protected PreviewResults(
List<QAWarning> warnings,
Severity maxSeverity,
int nbWarnings,
int editCount,
List<ItemUpdate> editsPreview) {
this.warnings = warnings;
this.maxSeverity = maxSeverity;
this.nbWarnings = nbWarnings;
this.editCount = editCount;
this.editsPreview = editsPreview;
}
@Override
public String toString() {
try {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
return super.toString();
}
}
}

View File

@ -27,29 +27,23 @@ package org.openrefine.wikidata.commands;
import static org.openrefine.wikidata.commands.CommandUtilities.respondError; import static org.openrefine.wikidata.commands.CommandUtilities.respondError;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter;
import java.util.List; import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONWriter;
import org.openrefine.wikidata.qa.EditInspector; import org.openrefine.wikidata.qa.EditInspector;
import org.openrefine.wikidata.qa.QAWarning;
import org.openrefine.wikidata.qa.QAWarningStore; import org.openrefine.wikidata.qa.QAWarningStore;
import org.openrefine.wikidata.schema.WikibaseSchema; import org.openrefine.wikidata.schema.WikibaseSchema;
import org.openrefine.wikidata.updates.ItemUpdate; import org.openrefine.wikidata.updates.ItemUpdate;
import org.openrefine.wikidata.updates.scheduler.WikibaseAPIUpdateScheduler; import org.openrefine.wikidata.updates.scheduler.WikibaseAPIUpdateScheduler;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.commands.Command; import com.google.refine.commands.Command;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.util.ParsingUtilities;
public class PreviewWikibaseSchemaCommand extends Command { public class PreviewWikibaseSchemaCommand extends Command {
@ -69,7 +63,7 @@ public class PreviewWikibaseSchemaCommand extends Command {
if (jsonString != null) { if (jsonString != null) {
try { try {
schema = WikibaseSchema.reconstruct(jsonString); schema = WikibaseSchema.reconstruct(jsonString);
} catch (JSONException e) { } catch (IOException e) {
respondError(response, "Wikibase schema could not be parsed."); respondError(response, "Wikibase schema could not be parsed.");
return; return;
} }
@ -87,50 +81,25 @@ public class PreviewWikibaseSchemaCommand extends Command {
Engine engine = getEngine(request, project); Engine engine = getEngine(request, project);
List<ItemUpdate> editBatch = schema.evaluate(project, engine, warningStore); List<ItemUpdate> editBatch = schema.evaluate(project, engine, warningStore);
StringWriter sb = new StringWriter(2048);
JSONWriter writer = new JSONWriter(sb);
writer.object();
{
// Inspect the edits and generate warnings // Inspect the edits and generate warnings
EditInspector inspector = new EditInspector(warningStore); EditInspector inspector = new EditInspector(warningStore);
inspector.inspect(editBatch); inspector.inspect(editBatch);
writer.key("warnings");
writer.array();
for (QAWarning warning : warningStore.getWarnings()) {
warning.write(writer, new Properties());
}
writer.endArray();
// Add max warning level
writer.key("max_severity");
writer.value(warningStore.getMaxSeverity().toString());
// this is not the length of the warnings array written before,
// but the total number of issues raised (before deduplication)
writer.key("nb_warnings");
writer.value(warningStore.getNbWarnings());
// Dump the first 10 edits, scheduled with the default scheduler // Dump the first 10 edits, scheduled with the default scheduler
WikibaseAPIUpdateScheduler scheduler = new WikibaseAPIUpdateScheduler(); WikibaseAPIUpdateScheduler scheduler = new WikibaseAPIUpdateScheduler();
List<ItemUpdate> nonNullEdits = scheduler.schedule(editBatch).stream() List<ItemUpdate> nonNullEdits = scheduler.schedule(editBatch).stream()
.filter(e -> !e.isNull()) .filter(e -> !e.isNull())
.collect(Collectors.toList()); .collect(Collectors.toList());
writer.key("edit_count");
writer.value(nonNullEdits.size());
List<ItemUpdate> firstEdits = nonNullEdits.stream() List<ItemUpdate> firstEdits = nonNullEdits.stream()
.limit(10) .limit(10)
.collect(Collectors.toList()); .collect(Collectors.toList());
ObjectMapper mapper = new ObjectMapper();
String firstEditsJson = mapper.writeValueAsString(firstEdits);
writer.key("edits_preview"); PreviewResults previewResults = new PreviewResults(
writer.value(new JSONArray(firstEditsJson)); warningStore.getWarnings(),
} warningStore.getMaxSeverity(),
warningStore.getNbWarnings(),
writer.endObject(); nonNullEdits.size(), firstEdits);
respondJSON(response, previewResults);
respond(response, sb.toString());
} catch (Exception e) { } catch (Exception e) {
respondException(response, e); respondException(response, e);
} }

View File

@ -23,6 +23,8 @@
******************************************************************************/ ******************************************************************************/
package org.openrefine.wikidata.commands; package org.openrefine.wikidata.commands;
import static org.openrefine.wikidata.commands.CommandUtilities.respondError;
import java.io.IOException; import java.io.IOException;
import java.util.Properties; import java.util.Properties;
@ -30,11 +32,8 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;
import org.openrefine.wikidata.operations.SaveWikibaseSchemaOperation; import org.openrefine.wikidata.operations.SaveWikibaseSchemaOperation;
import org.openrefine.wikidata.schema.WikibaseSchema; import org.openrefine.wikidata.schema.WikibaseSchema;
import static org.openrefine.wikidata.commands.CommandUtilities.respondError;
import com.google.refine.commands.Command; import com.google.refine.commands.Command;
import com.google.refine.model.AbstractOperation; import com.google.refine.model.AbstractOperation;
@ -57,15 +56,14 @@ public class SaveWikibaseSchemaCommand extends Command {
return; return;
} }
JSONObject json = ParsingUtilities.evaluateJsonStringToObject(jsonString); WikibaseSchema schema = ParsingUtilities.mapper.readValue(jsonString, WikibaseSchema.class);
WikibaseSchema schema = WikibaseSchema.reconstruct(json);
AbstractOperation op = new SaveWikibaseSchemaOperation(schema); AbstractOperation op = new SaveWikibaseSchemaOperation(schema);
Process process = op.createProcess(project, new Properties()); Process process = op.createProcess(project, new Properties());
performProcessAndRespond(request, response, project, process); performProcessAndRespond(request, response, project, process);
} catch (JSONException e) { } catch (IOException e) {
// We do not use respondException here because this is an expected // We do not use respondException here because this is an expected
// exception which happens every time a user tries to save an incomplete // exception which happens every time a user tries to save an incomplete
// schema - the exception should not be logged. // schema - the exception should not be logged.

View File

@ -25,16 +25,16 @@ package org.openrefine.wikidata.editing;
import java.io.IOException; import java.io.IOException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.wikidata.wdtk.wikibaseapi.ApiConnection; import org.wikidata.wdtk.wikibaseapi.ApiConnection;
import org.wikidata.wdtk.wikibaseapi.LoginFailedException; import org.wikidata.wdtk.wikibaseapi.LoginFailedException;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.PreferenceStore;
import com.google.refine.util.ParsingUtilities;
/** /**
* Manages a connection to Wikidata, with login credentials stored in the * Manages a connection to Wikidata, with login credentials stored in the
@ -72,16 +72,12 @@ public class ConnectionManager {
public void login(String username, String password, boolean rememberCredentials) { public void login(String username, String password, boolean rememberCredentials) {
if (rememberCredentials) { if (rememberCredentials) {
try { ArrayNode array = ParsingUtilities.mapper.createArrayNode();
JSONArray array = new JSONArray(); ObjectNode obj = ParsingUtilities.mapper.createObjectNode();
JSONObject obj = new JSONObject();
obj.put("username", username); obj.put("username", username);
obj.put("password", password); obj.put("password", password);
array.put(obj); array.add(obj);
prefStore.put(PREFERENCE_STORE_KEY, array); prefStore.put(PREFERENCE_STORE_KEY, array);
} catch (JSONException e) {
logger.error(e.getMessage());
}
} }
connection = ApiConnection.getWikidataApiConnection(); connection = ApiConnection.getWikidataApiConnection();
@ -93,33 +89,27 @@ public class ConnectionManager {
} }
public void restoreSavedConnection() { public void restoreSavedConnection() {
JSONObject savedCredentials = getStoredCredentials(); ObjectNode savedCredentials = getStoredCredentials();
if (savedCredentials != null) { if (savedCredentials != null) {
connection = ApiConnection.getWikidataApiConnection(); connection = ApiConnection.getWikidataApiConnection();
try { try {
connection.login(savedCredentials.getString("username"), savedCredentials.getString("password")); connection.login(savedCredentials.get("username").asText(), savedCredentials.get("password").asText());
} catch (LoginFailedException e) { } catch (LoginFailedException e) {
connection = null; connection = null;
} catch (JSONException e) {
connection = null;
} }
} }
} }
public JSONObject getStoredCredentials() { public ObjectNode getStoredCredentials() {
JSONArray array = (JSONArray) prefStore.get(PREFERENCE_STORE_KEY); ArrayNode array = (ArrayNode) prefStore.get(PREFERENCE_STORE_KEY);
if (array != null && array.length() > 0) { if (array != null && array.size() > 0 && array.get(0) instanceof ObjectNode) {
try { return (ObjectNode) array.get(0);
return array.getJSONObject(0);
} catch (JSONException e) {
logger.error(e.getMessage());
}
} }
return null; return null;
} }
public void logout() { public void logout() {
prefStore.put(PREFERENCE_STORE_KEY, new JSONArray()); prefStore.put(PREFERENCE_STORE_KEY, ParsingUtilities.mapper.createArrayNode());
if (connection != null) { if (connection != null) {
try { try {
connection.logout(); connection.logout();

View File

@ -23,13 +23,9 @@
******************************************************************************/ ******************************************************************************/
package org.openrefine.wikidata.editing; package org.openrefine.wikidata.editing;
import java.util.Properties; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.google.refine.Jsonizable;
/** /**
* This is just the necessary bits to store Wikidata credentials in OpenRefine's * This is just the necessary bits to store Wikidata credentials in OpenRefine's
@ -38,9 +34,11 @@ import com.google.refine.Jsonizable;
* @author Antonin Delpeuch * @author Antonin Delpeuch
* *
*/ */
class WikibaseCredentials implements Jsonizable { class WikibaseCredentials {
@JsonProperty("username")
private String username; private String username;
@JsonProperty("password")
private String password; private String password;
public WikibaseCredentials() { public WikibaseCredentials() {
@ -48,7 +46,12 @@ class WikibaseCredentials implements Jsonizable {
password = null; password = null;
} }
public WikibaseCredentials(String username, String password) { @JsonCreator
public WikibaseCredentials(
@JsonProperty("username")
String username,
@JsonProperty("password")
String password) {
this.username = username; this.username = username;
this.password = password; this.password = password;
} }
@ -65,22 +68,8 @@ class WikibaseCredentials implements Jsonizable {
return username != null && password != null && !"null".equals(username) && !"null".equals(password); return username != null && password != null && !"null".equals(username) && !"null".equals(password);
} }
@Override @JsonProperty("class")
public void write(JSONWriter writer, Properties options) public String getClassName() {
throws JSONException { return getClass().getName();
writer.object();
writer.key("class");
writer.value(this.getClass().getName());
writer.key("username");
writer.value(username);
writer.key("password");
writer.value(password);
writer.endObject();
} }
public static WikibaseCredentials load(JSONObject obj)
throws JSONException {
return new WikibaseCredentials(obj.getString("username"), obj.getString("password"));
}
} }

View File

@ -4,12 +4,12 @@ import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.util.Properties; import java.util.Properties;
import org.json.JSONWriter;
import org.openrefine.wikidata.schema.WikibaseSchema; import org.openrefine.wikidata.schema.WikibaseSchema;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.exporters.WriterExporter; import com.google.refine.exporters.WriterExporter;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.util.ParsingUtilities;
public class SchemaExporter implements WriterExporter { public class SchemaExporter implements WriterExporter {
@ -24,8 +24,7 @@ public class SchemaExporter implements WriterExporter {
if (schema == null) { if (schema == null) {
schema = new WikibaseSchema(); schema = new WikibaseSchema();
} }
JSONWriter jsonWriter = new JSONWriter(writer); ParsingUtilities.mapper.writeValue(writer, schema);
schema.write(jsonWriter, new Properties());
} }
} }

View File

@ -31,9 +31,6 @@ import java.util.Properties;
import java.util.Random; import java.util.Random;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.openrefine.wikidata.editing.ConnectionManager; import org.openrefine.wikidata.editing.ConnectionManager;
import org.openrefine.wikidata.editing.EditBatchProcessor; import org.openrefine.wikidata.editing.EditBatchProcessor;
import org.openrefine.wikidata.editing.NewItemLibrary; import org.openrefine.wikidata.editing.NewItemLibrary;
@ -46,16 +43,16 @@ import org.wikidata.wdtk.wikibaseapi.ApiConnection;
import org.wikidata.wdtk.wikibaseapi.WikibaseDataEditor; import org.wikidata.wdtk.wikibaseapi.WikibaseDataEditor;
import org.wikidata.wdtk.wikibaseapi.WikibaseDataFetcher; import org.wikidata.wdtk.wikibaseapi.WikibaseDataFetcher;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.EngineConfig;
import com.google.refine.history.Change; import com.google.refine.history.Change;
import com.google.refine.history.HistoryEntry; import com.google.refine.history.HistoryEntry;
import com.google.refine.model.AbstractOperation;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.operations.EngineDependentOperation; import com.google.refine.operations.EngineDependentOperation;
import com.google.refine.operations.OperationRegistry;
import com.google.refine.process.LongRunningProcess; import com.google.refine.process.LongRunningProcess;
import com.google.refine.process.Process; import com.google.refine.process.Process;
import com.google.refine.util.Pool; import com.google.refine.util.Pool;
@ -64,44 +61,46 @@ public class PerformWikibaseEditsOperation extends EngineDependentOperation {
static final Logger logger = LoggerFactory.getLogger(PerformWikibaseEditsOperation.class); static final Logger logger = LoggerFactory.getLogger(PerformWikibaseEditsOperation.class);
@JsonProperty("summary")
private String summary; private String summary;
public PerformWikibaseEditsOperation(EngineConfig engineConfig, String summary) { @JsonCreator
public PerformWikibaseEditsOperation(
@JsonProperty("engineConfig")
EngineConfig engineConfig,
@JsonProperty("summary")
String summary) {
super(engineConfig); super(engineConfig);
Validate.notNull(summary, "An edit summary must be provided."); Validate.notNull(summary, "An edit summary must be provided.");
Validate.notEmpty(summary, "An edit summary must be provided."); Validate.notEmpty(summary, "An edit summary must be provided.");
this.summary = summary; this.summary = summary;
} }
static public AbstractOperation reconstruct(Project project, JSONObject obj) /* The constructor above should be enough for deserialization,
throws Exception { * but for some unknown reason it can fail in certain cases
JSONObject engineConfig = obj.getJSONObject("engineConfig"); * (might be due to caching deserializers across threads?)
String summary = null; *
if (obj.has("summary")) { * So we sadly add a default constructor and a setter below.
summary = obj.getString("summary"); *
} * TODO delete the default constructor and setter, make summary final
return new PerformWikibaseEditsOperation( */
EngineConfig.reconstruct(engineConfig), summary); public PerformWikibaseEditsOperation() {
super(null);
} }
@Override @JsonProperty("engineConfig")
public void write(JSONWriter writer, Properties options) public void setEngineConfig(EngineConfig config) {
throws JSONException { this._engineConfig = config;
writer.object(); }
writer.key("op");
writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); @JsonProperty("summary")
writer.key("description"); public void setSummary(String summary) {
writer.value("Perform Wikibase edits"); this.summary = summary;
writer.key("summary");
writer.value(summary);
writer.key("engineConfig");
getEngineConfig().write(writer, options);
writer.endObject();
} }
@Override @Override
protected String getBriefDescription(Project project) { protected String getBriefDescription(Project project) {
return "Peform edits on Wikidata"; return "Perform Wikibase edits";
} }
@Override @Override

View File

@ -28,50 +28,53 @@ import java.io.LineNumberReader;
import java.io.Writer; import java.io.Writer;
import java.util.Properties; import java.util.Properties;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.openrefine.wikidata.schema.WikibaseSchema; import org.openrefine.wikidata.schema.WikibaseSchema;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.history.Change; import com.google.refine.history.Change;
import com.google.refine.history.HistoryEntry; import com.google.refine.history.HistoryEntry;
import com.google.refine.model.AbstractOperation; import com.google.refine.model.AbstractOperation;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.operations.OperationRegistry;
import com.google.refine.util.ParsingUtilities; import com.google.refine.util.ParsingUtilities;
import com.google.refine.util.Pool; import com.google.refine.util.Pool;
public class SaveWikibaseSchemaOperation extends AbstractOperation { public class SaveWikibaseSchemaOperation extends AbstractOperation {
final public String operationDescription = "Save Wikibase schema"; @JsonIgnore
final protected WikibaseSchema _schema; final public static String operationDescription = "Save Wikibase schema";
@JsonProperty("schema")
protected WikibaseSchema _schema;
public SaveWikibaseSchemaOperation(WikibaseSchema schema) { @JsonCreator
public SaveWikibaseSchemaOperation(
@JsonProperty("schema")
WikibaseSchema schema) {
this._schema = schema; this._schema = schema;
}
/* The constructor above should be enough for deserialization,
* but for some unknown reason it can fail in certain cases
* (might be due to caching deserializers across threads?)
*
* So we sadly add a default constructor and a setter below.
*
* TODO delete the default constructor and setter, make schema final
*/
public SaveWikibaseSchemaOperation() {
} }
static public AbstractOperation reconstruct(Project project, JSONObject obj) @JsonProperty("schema")
throws Exception { public void setSchema(WikibaseSchema schema) {
return new SaveWikibaseSchemaOperation(WikibaseSchema.reconstruct(obj.getJSONObject("schema"))); this._schema = schema;
}
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("op");
writer.value(OperationRegistry.s_opClassToName.get(this.getClass()));
writer.key("description");
writer.value(operationDescription);
writer.key("schema");
_schema.write(writer, options);
writer.endObject();
} }
@Override @Override
protected String getBriefDescription(Project project) { protected String getBriefDescription(Project project) {
return "Save Wikibase schema skelton"; return operationDescription;
} }
@Override @Override
@ -134,9 +137,9 @@ public class SaveWikibaseSchemaOperation extends AbstractOperation {
String value = line.substring(equal + 1); String value = line.substring(equal + 1);
if ("oldSchema".equals(field) && value.length() > 0) { if ("oldSchema".equals(field) && value.length() > 0) {
oldSchema = WikibaseSchema.reconstruct(ParsingUtilities.evaluateJsonStringToObject(value)); oldSchema = ParsingUtilities.mapper.readValue(value, WikibaseSchema.class);
} else if ("newSchema".equals(field) && value.length() > 0) { } else if ("newSchema".equals(field) && value.length() > 0) {
newSchema = WikibaseSchema.reconstruct(ParsingUtilities.evaluateJsonStringToObject(value)); newSchema = ParsingUtilities.mapper.readValue(value, WikibaseSchema.class);
} }
} }
@ -149,12 +152,7 @@ public class SaveWikibaseSchemaOperation extends AbstractOperation {
static protected void writeWikibaseSchema(WikibaseSchema s, Writer writer) static protected void writeWikibaseSchema(WikibaseSchema s, Writer writer)
throws IOException { throws IOException {
if (s != null) { if (s != null) {
JSONWriter jsonWriter = new JSONWriter(writer); ParsingUtilities.defaultWriter.writeValue(writer, s);
try {
s.write(jsonWriter, new Properties());
} catch (JSONException e) {
e.printStackTrace();
}
} }
} }
} }

View File

@ -28,7 +28,6 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.jsoup.helper.Validate; import org.jsoup.helper.Validate;
import org.openrefine.wikidata.utils.JacksonJsonizable;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
@ -42,7 +41,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* @author Antonin Delpeuch * @author Antonin Delpeuch
* *
*/ */
public class QAWarning extends JacksonJsonizable implements Comparable<QAWarning> { public class QAWarning implements Comparable<QAWarning> {
public enum Severity { public enum Severity {
INFO, // We just report something to the user but it is probably fine INFO, // We just report something to the user but it is probably fine

View File

@ -30,7 +30,6 @@ import org.jsoup.helper.Validate;
import org.openrefine.wikidata.schema.exceptions.SkipSchemaExpressionException; import org.openrefine.wikidata.schema.exceptions.SkipSchemaExpressionException;
import org.openrefine.wikidata.updates.ItemUpdate; import org.openrefine.wikidata.updates.ItemUpdate;
import org.openrefine.wikidata.updates.ItemUpdateBuilder; import org.openrefine.wikidata.updates.ItemUpdateBuilder;
import org.openrefine.wikidata.utils.JacksonJsonizable;
import org.wikidata.wdtk.datamodel.interfaces.ItemIdValue; import org.wikidata.wdtk.datamodel.interfaces.ItemIdValue;
import org.wikidata.wdtk.datamodel.interfaces.Statement; import org.wikidata.wdtk.datamodel.interfaces.Statement;
@ -48,7 +47,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) @JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
public class WbItemDocumentExpr extends JacksonJsonizable implements WbExpression<ItemUpdate> { public class WbItemDocumentExpr implements WbExpression<ItemUpdate> {
private WbExpression<? extends ItemIdValue> subject; private WbExpression<? extends ItemIdValue> subject;
private List<WbNameDescExpr> nameDescs; private List<WbNameDescExpr> nameDescs;

View File

@ -26,11 +26,7 @@ package org.openrefine.wikidata.schema;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.openrefine.wikidata.qa.QAWarningStore; import org.openrefine.wikidata.qa.QAWarningStore;
import org.openrefine.wikidata.schema.exceptions.SkipSchemaExpressionException; import org.openrefine.wikidata.schema.exceptions.SkipSchemaExpressionException;
import org.openrefine.wikidata.updates.ItemUpdate; import org.openrefine.wikidata.updates.ItemUpdate;
@ -38,18 +34,16 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.FilteredRows;
import com.google.refine.browsing.RowVisitor; import com.google.refine.browsing.RowVisitor;
import com.google.refine.model.OverlayModel; import com.google.refine.model.OverlayModel;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.Row; import com.google.refine.model.Row;
import com.google.refine.util.ParsingUtilities;
/** /**
* Main class representing a skeleton of Wikibase edits with OpenRefine columns * Main class representing a skeleton of Wikibase edits with OpenRefine columns
@ -63,6 +57,7 @@ public class WikibaseSchema implements OverlayModel {
final static Logger logger = LoggerFactory.getLogger("RdfSchema"); final static Logger logger = LoggerFactory.getLogger("RdfSchema");
@JsonProperty("itemDocuments")
protected List<WbItemDocumentExpr> itemDocumentExprs = new ArrayList<WbItemDocumentExpr>(); protected List<WbItemDocumentExpr> itemDocumentExprs = new ArrayList<WbItemDocumentExpr>();
protected String baseIri = "http://www.wikidata.org/entity/"; protected String baseIri = "http://www.wikidata.org/entity/";
@ -85,6 +80,7 @@ public class WikibaseSchema implements OverlayModel {
/** /**
* @return the site IRI of the Wikibase instance referenced by this schema * @return the site IRI of the Wikibase instance referenced by this schema
*/ */
@JsonIgnore
public String getBaseIri() { public String getBaseIri() {
return baseIri; return baseIri;
} }
@ -92,6 +88,7 @@ public class WikibaseSchema implements OverlayModel {
/** /**
* @return the list of document expressions for this schema * @return the list of document expressions for this schema
*/ */
@JsonIgnore
public List<WbItemDocumentExpr> getItemDocumentExpressions() { public List<WbItemDocumentExpr> getItemDocumentExpressions() {
return itemDocumentExprs; return itemDocumentExprs;
} }
@ -181,38 +178,11 @@ public class WikibaseSchema implements OverlayModel {
} }
} }
static public WikibaseSchema reconstruct(JSONObject o) static public WikibaseSchema reconstruct(String json) throws IOException {
throws JSONException { return ParsingUtilities.mapper.readValue(json, WikibaseSchema.class);
return reconstruct(o.toString());
} }
static public WikibaseSchema reconstruct(String json) throws JSONException { static public WikibaseSchema load(Project project, String obj)
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.readValue(json, WikibaseSchema.class);
} catch (JsonParseException e) {
throw new JSONException(e.toString());
} catch (JsonMappingException e) {
throw new JSONException(e.toString());
} catch (IOException e) {
throw new JSONException(e.toString());
}
}
@Override
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("itemDocuments");
writer.array();
for (WbItemDocumentExpr changeExpr : itemDocumentExprs) {
changeExpr.write(writer, options);
}
writer.endArray();
writer.endObject();
}
static public WikibaseSchema load(Project project, JSONObject obj)
throws Exception { throws Exception {
return reconstruct(obj); return reconstruct(obj);
} }

View File

@ -27,6 +27,8 @@ import java.util.List;
import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue; import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue;
import com.fasterxml.jackson.annotation.JsonProperty;
/** /**
* An entity id value that also comes with a label and possibly types. * An entity id value that also comes with a label and possibly types.
* *
@ -47,6 +49,7 @@ public interface PrefetchedEntityIdValue extends EntityIdValue {
* *
* @return the preferred label of the entity * @return the preferred label of the entity
*/ */
@JsonProperty("label")
public String getLabel(); public String getLabel();
/** /**
@ -56,5 +59,6 @@ public interface PrefetchedEntityIdValue extends EntityIdValue {
* *
* Empty lists should be returned for * Empty lists should be returned for
*/ */
@JsonProperty("types")
public List<String> getTypes(); public List<String> getTypes();
} }

View File

@ -33,6 +33,7 @@ import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue;
import org.wikidata.wdtk.datamodel.interfaces.ValueVisitor; import org.wikidata.wdtk.datamodel.interfaces.ValueVisitor;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.model.Recon; import com.google.refine.model.Recon;
@ -72,6 +73,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue {
return !isMatched(); return !isMatched();
} }
@JsonProperty("label")
public String getLabel() { public String getLabel() {
if (isMatched()) { if (isMatched()) {
return _recon.match.name; return _recon.match.name;
@ -80,6 +82,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue {
} }
} }
@JsonProperty("types")
public List<String> getTypes() { public List<String> getTypes() {
if (isMatched()) { if (isMatched()) {
return Arrays.asList(_recon.match.types); return Arrays.asList(_recon.match.types);
@ -89,6 +92,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue {
} }
@Override @Override
@JsonProperty("entityType")
public abstract String getEntityType(); public abstract String getEntityType();
/** /**
@ -96,6 +100,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue {
* *
* @return the reconciliation id of the reconciled cell * @return the reconciliation id of the reconciled cell
*/ */
@JsonProperty("reconInternalId")
public long getReconInternalId() { public long getReconInternalId() {
return getRecon().id; return getRecon().id;
} }
@ -114,6 +119,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue {
* Returns the id of the reconciled item * Returns the id of the reconciled item
*/ */
@Override @Override
@JsonProperty("id")
public String getId() { public String getId() {
if (isMatched()) { if (isMatched()) {
return _recon.match.id; return _recon.match.id;
@ -126,6 +132,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue {
} }
@Override @Override
@JsonProperty("siteIri")
public String getSiteIri() { public String getSiteIri() {
if (isMatched()) { if (isMatched()) {
return _recon.identifierSpace; return _recon.identifierSpace;
@ -135,6 +142,7 @@ public abstract class ReconEntityIdValue implements PrefetchedEntityIdValue {
} }
@Override @Override
@JsonProperty("iri")
public String getIri() { public String getIri() {
return getSiteIri() + getId(); return getSiteIri() + getId();
} }

View File

@ -30,6 +30,8 @@ import org.wikidata.wdtk.datamodel.helpers.Hash;
import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue; import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue;
import org.wikidata.wdtk.datamodel.interfaces.ValueVisitor; import org.wikidata.wdtk.datamodel.interfaces.ValueVisitor;
import com.fasterxml.jackson.annotation.JsonProperty;
/** /**
* An EntityIdValue that we have obtained from a suggest widget in the schema * An EntityIdValue that we have obtained from a suggest widget in the schema
* alignment dialog. * alignment dialog.
@ -50,26 +52,31 @@ public abstract class SuggestedEntityIdValue implements PrefetchedEntityIdValue
} }
@Override @Override
@JsonProperty("id")
public String getId() { public String getId() {
return _id; return _id;
} }
@Override @Override
@JsonProperty("siteIri")
public String getSiteIri() { public String getSiteIri() {
return _siteIRI; return _siteIRI;
} }
@Override @Override
@JsonProperty("label")
public String getLabel() { public String getLabel() {
return _label; return _label;
} }
@Override @Override
@JsonProperty("types")
public List<String> getTypes() { public List<String> getTypes() {
return new ArrayList<>(); return new ArrayList<>();
} }
@Override @Override
@JsonProperty("iri")
public String getIri() { public String getIri() {
return getSiteIri() + getId(); return getSiteIri() + getId();
} }

View File

@ -1,79 +0,0 @@
/*******************************************************************************
* MIT License
*
* Copyright (c) 2018 Antonin Delpeuch
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
******************************************************************************/
package org.openrefine.wikidata.utils;
import java.io.IOException;
import java.util.Properties;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.refine.Jsonizable;
/**
* This class is inefficient because it serializes the object to string and then
* deserializes it back. Unfortunately, this is the only simple way to bridge
* Jackson to org.json. This conversion should be removed when (if ?) we migrate
* OpenRefine a better JSON library.
*
* @author Antonin Delpeuch
*
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class JacksonJsonizable implements Jsonizable {
@Override
public void write(JSONWriter writer, Properties options)
throws JSONException {
ObjectMapper mapper = new ObjectMapper();
try {
writer.value(new JSONObject(mapper.writeValueAsString(this)));
} catch (JsonProcessingException e) {
throw new JSONException(e.toString());
}
}
public static <T> T fromJSONClass(JSONObject obj, Class<T> klass)
throws JSONException {
ObjectMapper mapper = new ObjectMapper();
String json = obj.toString();
try {
return mapper.readValue(json, klass);
} catch (JsonParseException e) {
throw new JSONException(e.toString());
} catch (JsonMappingException e) {
throw new JSONException(e.toString());
} catch (IOException e) {
throw new JSONException(e.toString());
}
}
}

View File

@ -33,7 +33,6 @@ import java.io.StringWriter;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.openrefine.wikidata.testing.TestingData; import org.openrefine.wikidata.testing.TestingData;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
@ -52,8 +51,7 @@ public abstract class CommandTest extends RefineTest {
protected Command command = null; protected Command command = null;
@BeforeMethod(alwaysRun = true) @BeforeMethod(alwaysRun = true)
public void setUpProject() public void setUpProject() {
throws JSONException {
project = createCSVProject(TestingData.inceptionWithNewCsv); project = createCSVProject(TestingData.inceptionWithNewCsv);
TestingData.reconcileInceptionCells(project); TestingData.reconcileInceptionCells(project);
request = mock(HttpServletRequest.class); request = mock(HttpServletRequest.class);

View File

@ -6,15 +6,13 @@ import java.io.IOException;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import org.json.JSONException;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
public class LoginCommandTest extends CommandTest { public class LoginCommandTest extends CommandTest {
@BeforeMethod @BeforeMethod
public void SetUp() public void SetUp() {
throws JSONException {
command = new LoginCommand(); command = new LoginCommand();
} }

View File

@ -31,35 +31,31 @@ import java.io.IOException;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Assert;
import org.openrefine.wikidata.testing.TestingData;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.util.ParsingUtilities; import com.google.refine.util.ParsingUtilities;
public class PreviewWikibaseSchemaCommandTest extends SchemaCommandTest { public class PreviewWikibaseSchemaCommandTest extends SchemaCommandTest {
@BeforeMethod @BeforeMethod
public void SetUp() public void SetUp() {
throws JSONException {
command = new PreviewWikibaseSchemaCommand(); command = new PreviewWikibaseSchemaCommand();
} }
@Test @Test
public void testValidSchema() public void testValidSchema()
throws JSONException, IOException, ServletException { throws IOException, ServletException {
String schemaJson = jsonFromFile("schema/inception.json").toString(); String schemaJson = jsonFromFile("schema/inception.json").toString();
when(request.getParameter("schema")).thenReturn(schemaJson); when(request.getParameter("schema")).thenReturn(schemaJson);
command.doPost(request, response); command.doPost(request, response);
JSONObject response = ParsingUtilities.evaluateJsonStringToObject(writer.toString()); ObjectNode response = ParsingUtilities.evaluateJsonStringToObjectNode(writer.toString());
JSONArray edits = response.getJSONArray("edits_preview"); ArrayNode edits = (ArrayNode) response.get("edits_preview");
assertEquals(3, edits.length()); assertEquals(3, edits.size());
} }
} }

View File

@ -32,6 +32,8 @@ import javax.servlet.ServletException;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.refine.util.ParsingUtilities;
public abstract class SchemaCommandTest extends CommandTest { public abstract class SchemaCommandTest extends CommandTest {
@Test @Test
@ -48,6 +50,6 @@ public abstract class SchemaCommandTest extends CommandTest {
when(request.getParameter("schema")).thenReturn("{bogus json"); when(request.getParameter("schema")).thenReturn("{bogus json");
command.doPost(request, response); command.doPost(request, response);
assertEquals("{\"code\":\"error\",\"message\":\"Wikibase schema could not be parsed.\"}", writer.toString()); assertEquals("error", ParsingUtilities.mapper.readTree(writer.toString()).get("code").asText());
} }
} }

View File

@ -31,8 +31,6 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Properties; import java.util.Properties;
import org.json.JSONException;
import org.json.JSONObject;
import org.openrefine.wikidata.schema.WikibaseSchema; import org.openrefine.wikidata.schema.WikibaseSchema;
import org.openrefine.wikidata.testing.TestingData; import org.openrefine.wikidata.testing.TestingData;
import org.openrefine.wikidata.updates.ItemUpdate; import org.openrefine.wikidata.updates.ItemUpdate;
@ -67,10 +65,10 @@ public class QuickStatementsExporterTest extends RefineTest {
@Test @Test
public void testSimpleProject() public void testSimpleProject()
throws JSONException, IOException { throws IOException {
Project project = this.createCSVProject(TestingData.inceptionWithNewCsv); Project project = this.createCSVProject(TestingData.inceptionWithNewCsv);
TestingData.reconcileInceptionCells(project); TestingData.reconcileInceptionCells(project);
JSONObject serialized = TestingData.jsonFromFile("schema/inception.json"); String serialized = TestingData.jsonFromFile("schema/inception.json");
WikibaseSchema schema = WikibaseSchema.reconstruct(serialized); WikibaseSchema schema = WikibaseSchema.reconstruct(serialized);
project.overlayModels.put("wikibaseSchema", schema); project.overlayModels.put("wikibaseSchema", schema);
Engine engine = new Engine(project); Engine engine = new Engine(project);

View File

@ -1,7 +1,5 @@
package org.openrefine.wikidata.exporters; package org.openrefine.wikidata.exporters;
import static org.openrefine.wikidata.testing.JacksonSerializationTest.assertJsonEquals;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Properties; import java.util.Properties;
@ -11,6 +9,7 @@ import org.testng.annotations.Test;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.tests.RefineTest; import com.google.refine.tests.RefineTest;
import com.google.refine.tests.util.TestUtils;
public class SchemaExporterTest extends RefineTest { public class SchemaExporterTest extends RefineTest {
@ -24,7 +23,7 @@ public class SchemaExporterTest extends RefineTest {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
Properties properties = new Properties(); Properties properties = new Properties();
exporter.export(project, properties, engine, writer); exporter.export(project, properties, engine, writer);
assertJsonEquals("{\"itemDocuments\":[]}", writer.toString()); TestUtils.assertEqualAsJson("{\"itemDocuments\":[]}", writer.toString());
} }
} }

View File

@ -32,9 +32,6 @@ import java.io.StringReader;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Properties; import java.util.Properties;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.openrefine.wikidata.testing.JacksonSerializationTest;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -43,6 +40,8 @@ import com.google.refine.model.AbstractOperation;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.OperationRegistry;
import com.google.refine.tests.RefineTest; import com.google.refine.tests.RefineTest;
import com.google.refine.tests.util.TestUtils;
import com.google.refine.util.ParsingUtilities;
import com.google.refine.util.Pool; import com.google.refine.util.Pool;
import edu.mit.simile.butterfly.ButterflyModule; import edu.mit.simile.butterfly.ButterflyModule;
@ -68,18 +67,17 @@ public abstract class OperationTest extends RefineTest {
public abstract AbstractOperation reconstruct() public abstract AbstractOperation reconstruct()
throws Exception; throws Exception;
public abstract JSONObject getJson() public abstract String getJson()
throws Exception; throws Exception;
@Test @Test
public void testReconstruct() public void testReconstruct()
throws Exception { throws Exception {
JSONObject json = getJson(); String json = getJson();
AbstractOperation op = reconstruct(); AbstractOperation op = reconstruct();
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
JSONWriter jsonWriter = new JSONWriter(writer); ParsingUtilities.defaultWriter.writeValue(writer, op);
op.write(jsonWriter, new Properties()); TestUtils.assertEqualAsJson(json, writer.toString());
JacksonSerializationTest.assertJsonEquals(json.toString(), writer.toString());
} }
protected LineNumberReader makeReader(String input) { protected LineNumberReader makeReader(String input) {

View File

@ -27,7 +27,6 @@ import static org.junit.Assert.assertEquals;
import java.io.LineNumberReader; import java.io.LineNumberReader;
import org.json.JSONObject;
import org.openrefine.wikidata.testing.TestingData; import org.openrefine.wikidata.testing.TestingData;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -36,6 +35,7 @@ import com.google.refine.browsing.EngineConfig;
import com.google.refine.history.Change; import com.google.refine.history.Change;
import com.google.refine.model.AbstractOperation; import com.google.refine.model.AbstractOperation;
import com.google.refine.model.Recon; import com.google.refine.model.Recon;
import com.google.refine.util.ParsingUtilities;
public class PerformWikibaseEditsOperationTest extends OperationTest { public class PerformWikibaseEditsOperationTest extends OperationTest {
@ -47,19 +47,18 @@ public class PerformWikibaseEditsOperationTest extends OperationTest {
@Override @Override
public AbstractOperation reconstruct() public AbstractOperation reconstruct()
throws Exception { throws Exception {
JSONObject json = getJson(); return ParsingUtilities.mapper.readValue(getJson(), PerformWikibaseEditsOperation.class);
return PerformWikibaseEditsOperation.reconstruct(project, json);
} }
@Override @Override
public JSONObject getJson() public String getJson()
throws Exception { throws Exception {
return TestingData.jsonFromFile("operations/perform-edits.json"); return TestingData.jsonFromFile("operations/perform-edits.json");
} }
@Test(expectedExceptions=IllegalArgumentException.class) @Test(expectedExceptions=IllegalArgumentException.class)
public void testConstructor() { public void testConstructor() {
new PerformWikibaseEditsOperation(EngineConfig.reconstruct(new JSONObject("{}")), ""); new PerformWikibaseEditsOperation(EngineConfig.reconstruct("{}"), "");
} }
@Test @Test

View File

@ -28,7 +28,6 @@ import static org.junit.Assert.assertNull;
import java.io.LineNumberReader; import java.io.LineNumberReader;
import org.json.JSONObject;
import org.openrefine.wikidata.schema.WikibaseSchema; import org.openrefine.wikidata.schema.WikibaseSchema;
import org.openrefine.wikidata.testing.TestingData; import org.openrefine.wikidata.testing.TestingData;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
@ -36,6 +35,7 @@ import org.testng.annotations.Test;
import com.google.refine.history.Change; import com.google.refine.history.Change;
import com.google.refine.model.AbstractOperation; import com.google.refine.model.AbstractOperation;
import com.google.refine.util.ParsingUtilities;
public class SaveWikibaseSchemaOperationTest extends OperationTest { public class SaveWikibaseSchemaOperationTest extends OperationTest {
@ -47,11 +47,11 @@ public class SaveWikibaseSchemaOperationTest extends OperationTest {
@Override @Override
public AbstractOperation reconstruct() public AbstractOperation reconstruct()
throws Exception { throws Exception {
return SaveWikibaseSchemaOperation.reconstruct(project, getJson()); return ParsingUtilities.mapper.readValue(getJson(), SaveWikibaseSchemaOperation.class);
} }
@Override @Override
public JSONObject getJson() public String getJson()
throws Exception { throws Exception {
return TestingData.jsonFromFile("operations/save-schema.json"); return TestingData.jsonFromFile("operations/save-schema.json");
} }
@ -59,8 +59,8 @@ public class SaveWikibaseSchemaOperationTest extends OperationTest {
@Test @Test
public void testLoadChange() public void testLoadChange()
throws Exception { throws Exception {
JSONObject schemaJson = TestingData.jsonFromFile("schema/inception.json"); String schemaJson = TestingData.jsonFromFile("schema/inception.json");
String changeString = "newSchema=" + schemaJson.toString() + "\n" + "oldSchema=\n" + "/ec/"; String changeString = "newSchema=" + schemaJson + "\n" + "oldSchema=\n" + "/ec/";
WikibaseSchema schema = WikibaseSchema.reconstruct(schemaJson); WikibaseSchema schema = WikibaseSchema.reconstruct(schemaJson);
LineNumberReader reader = makeReader(changeString); LineNumberReader reader = makeReader(changeString);

View File

@ -26,16 +26,11 @@ package org.openrefine.wikidata.schema;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Properties;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.openrefine.wikidata.testing.TestingData; import org.openrefine.wikidata.testing.TestingData;
import org.openrefine.wikidata.updates.ItemUpdate; import org.openrefine.wikidata.updates.ItemUpdate;
import org.openrefine.wikidata.updates.ItemUpdateBuilder; import org.openrefine.wikidata.updates.ItemUpdateBuilder;
@ -52,13 +47,11 @@ import org.wikidata.wdtk.datamodel.interfaces.StatementRank;
import org.wikidata.wdtk.datamodel.interfaces.StringValue; import org.wikidata.wdtk.datamodel.interfaces.StringValue;
import org.wikidata.wdtk.datamodel.interfaces.TimeValue; import org.wikidata.wdtk.datamodel.interfaces.TimeValue;
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.EngineConfig;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.tests.RefineTest; import com.google.refine.tests.RefineTest;
import com.google.refine.util.ParsingUtilities; import com.google.refine.tests.util.TestUtils;
public class WikibaseSchemaTest extends RefineTest { public class WikibaseSchemaTest extends RefineTest {
@ -100,32 +93,25 @@ public class WikibaseSchemaTest extends RefineTest {
@Test @Test
public void testSerialize() public void testSerialize()
throws JSONException, IOException { throws IOException {
JSONObject serialized = TestingData.jsonFromFile("schema/history_of_medicine.json"); String serialized = TestingData.jsonFromFile("schema/history_of_medicine.json");
WikibaseSchema parsed = WikibaseSchema.reconstruct(serialized); WikibaseSchema parsed = WikibaseSchema.reconstruct(serialized);
StringWriter writer = new StringWriter(); TestUtils.isSerializedTo(parsed, TestingData.jsonFromFile("schema/history_of_medicine_normalized.json").toString());
JSONWriter jsonWriter = new JSONWriter(writer);
parsed.write(jsonWriter, new Properties());
writer.close();
JSONObject newSerialized = ParsingUtilities.evaluateJsonStringToObject(writer.toString());
// toString because it looks like JSONObject equality isn't great
assertEquals(TestingData.jsonFromFile("schema/history_of_medicine_normalized.json").toString(),
newSerialized.toString());
} }
@Test @Test
public void testDeserialize() public void testDeserialize()
throws JSONException, IOException { throws IOException {
// this json file was generated by an earlier version of the software // this json file was generated by an earlier version of the software
// it contains extra "type" fields that are now ignored. // it contains extra "type" fields that are now ignored.
JSONObject serialized = TestingData.jsonFromFile("schema/roarmap.json"); String serialized = TestingData.jsonFromFile("schema/roarmap.json");
WikibaseSchema.reconstruct(serialized); WikibaseSchema.reconstruct(serialized);
} }
@Test @Test
public void testEvaluate() public void testEvaluate()
throws JSONException, IOException { throws IOException {
JSONObject serialized = TestingData.jsonFromFile("schema/inception.json"); String serialized = TestingData.jsonFromFile("schema/inception.json");
WikibaseSchema schema = WikibaseSchema.reconstruct(serialized); WikibaseSchema schema = WikibaseSchema.reconstruct(serialized);
Engine engine = new Engine(project); Engine engine = new Engine(project);
List<ItemUpdate> updates = schema.evaluate(project, engine); List<ItemUpdate> updates = schema.evaluate(project, engine);
@ -137,8 +123,8 @@ public class WikibaseSchemaTest extends RefineTest {
assertEquals(expected, updates); assertEquals(expected, updates);
} }
@Test(expectedExceptions = JSONException.class) @Test(expectedExceptions = IOException.class)
public void testDeserializeEmpty() throws JSONException { public void testDeserializeEmpty() throws IOException {
String schemaJson = "{\"itemDocuments\":[{\"statementGroups\":[{\"statements\":[]}]," String schemaJson = "{\"itemDocuments\":[{\"statementGroups\":[{\"statements\":[]}],"
+"\"nameDescs\":[]}],\"wikibasePrefix\":\"http://www.wikidata.org/entity/\"}"; +"\"nameDescs\":[]}],\"wikibasePrefix\":\"http://www.wikidata.org/entity/\"}";
WikibaseSchema.reconstruct(schemaJson); WikibaseSchema.reconstruct(schemaJson);
@ -146,11 +132,11 @@ public class WikibaseSchemaTest extends RefineTest {
@Test @Test
public void testEvaluateRespectsFacets() public void testEvaluateRespectsFacets()
throws JSONException, IOException { throws IOException {
JSONObject serialized = TestingData.jsonFromFile("schema/inception.json"); String serialized = TestingData.jsonFromFile("schema/inception.json");
WikibaseSchema schema = WikibaseSchema.reconstruct(serialized); WikibaseSchema schema = WikibaseSchema.reconstruct(serialized);
Engine engine = new Engine(project); Engine engine = new Engine(project);
EngineConfig engineConfig = EngineConfig.reconstruct(new JSONObject("{\n" EngineConfig engineConfig = EngineConfig.reconstruct("{\n"
+ " \"mode\": \"row-based\",\n" + " \"mode\": \"row-based\",\n"
+ " \"facets\": [\n" + " \"facets\": [\n"
+ " {\n" + " {\n"
@ -163,7 +149,7 @@ public class WikibaseSchemaTest extends RefineTest {
+ " \"columnName\": \"reference\"\n" + " \"columnName\": \"reference\"\n"
+ " }\n" + " }\n"
+ " ]\n" + " ]\n"
+ " }")); + " }");
engine.initializeFromConfig(engineConfig); engine.initializeFromConfig(engineConfig);
List<ItemUpdate> updates = schema.evaluate(project, engine); List<ItemUpdate> updates = schema.evaluate(project, engine);
List<ItemUpdate> expected = new ArrayList<>(); List<ItemUpdate> expected = new ArrayList<>();

View File

@ -33,16 +33,19 @@ import com.fasterxml.jackson.core.JsonProcessingException;
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.google.refine.tests.util.TestUtils;
import com.google.refine.util.ParsingUtilities;
public class JacksonSerializationTest { public class JacksonSerializationTest {
private static ObjectMapper mapper = new ObjectMapper(); private static ObjectMapper mapper = ParsingUtilities.mapper;
public static void testSerialize(Object pojo, String expectedJson) { public static void testSerialize(Object pojo, String expectedJson) {
// Test that the pojo is correctly serialized // Test that the pojo is correctly serialized
try { try {
String actualJson = mapper.writeValueAsString(pojo); String actualJson = ParsingUtilities.defaultWriter.writeValueAsString(pojo);
assertJsonEquals(expectedJson, actualJson); TestUtils.assertEqualAsJson(expectedJson, actualJson);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
e.printStackTrace(); e.printStackTrace();
Assert.fail("Failed to serialize object"); Assert.fail("Failed to serialize object");
@ -66,15 +69,4 @@ public class JacksonSerializationTest {
testSerialize(pojo, json); testSerialize(pojo, json);
testDeserialize(targetClass, pojo, json); testDeserialize(targetClass, pojo, json);
} }
public static void assertJsonEquals(String expectedJson, String actualJson) {
JsonNode parsedExpectedJson;
try {
parsedExpectedJson = mapper.readValue(expectedJson, JsonNode.class);
JsonNode parsedActualJson = mapper.readValue(actualJson, JsonNode.class);
assertEquals(parsedExpectedJson, parsedActualJson);
} catch (IOException e) {
Assert.fail("Invalid JSON");
}
}
} }

View File

@ -25,13 +25,9 @@ package org.openrefine.wikidata.testing;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collections; import java.util.Collections;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.openrefine.wikidata.schema.WbLanguageConstant; import org.openrefine.wikidata.schema.WbLanguageConstant;
import org.openrefine.wikidata.schema.WbMonolingualExpr; import org.openrefine.wikidata.schema.WbMonolingualExpr;
import org.openrefine.wikidata.schema.WbStringConstant; import org.openrefine.wikidata.schema.WbStringConstant;
@ -48,7 +44,6 @@ import com.google.refine.model.Cell;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.Recon; import com.google.refine.model.Recon;
import com.google.refine.model.ReconCandidate; import com.google.refine.model.ReconCandidate;
import com.google.refine.util.ParsingUtilities;
public class TestingData { public class TestingData {
@ -133,11 +128,11 @@ public class TestingData {
return generateStatement(from, pid, to); return generateStatement(from, pid, to);
} }
public static JSONObject jsonFromFile(String filename) public static String jsonFromFile(String filename)
throws IOException, JSONException { throws IOException {
InputStream f = TestingData.class.getClassLoader().getResourceAsStream(filename); InputStream f = TestingData.class.getClassLoader().getResourceAsStream(filename);
String decoded = IOUtils.toString(f); String decoded = IOUtils.toString(f);
return ParsingUtilities.evaluateJsonStringToObject(decoded); return decoded.trim();
} }
public static void reconcileInceptionCells(Project project) { public static void reconcileInceptionCells(Project project) {

View File

@ -1,21 +0,0 @@
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -136,38 +136,6 @@
<goal>install-file</goal> <goal>install-file</goal>
</goals> </goals>
</execution> </execution>
<execution>
<id>install-tableschema</id>
<phase>process-resources</phase>
<configuration>
<file>${basedir}/lib-local/tableschema-java-1.0-SNAPSHOT.jar</file>
<repositoryLayout>default</repositoryLayout>
<groupId>io.frictionlessdata</groupId>
<artifactId>tableschema-java</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
<goals>
<goal>install-file</goal>
</goals>
</execution>
<execution>
<id>install-datapackage</id>
<phase>process-resources</phase>
<configuration>
<file>${basedir}/lib-local/datapackage-java-1.0-SNAPSHOT.jar</file>
<repositoryLayout>default</repositoryLayout>
<groupId>io.frictionlessdata</groupId>
<artifactId>datapackage-java</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
<goals>
<goal>install-file</goal>
</goals>
</execution>
<execution> <execution>
<id>install-opencsv</id> <id>install-opencsv</id>
<phase>process-resources</phase> <phase>process-resources</phase>
@ -308,20 +276,15 @@
<artifactId>rhino</artifactId> <artifactId>rhino</artifactId>
<version>1.7.10</version> <version>1.7.10</version>
</dependency> </dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160810</version>
</dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>2.9.1</version> <version>2.9.7</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId> <artifactId>jackson-annotations</artifactId>
<version>2.9.1</version> <version>2.9.7</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
@ -353,6 +316,11 @@
<artifactId>commons-collections</artifactId> <artifactId>commons-collections</artifactId>
<version>3.2.2</version> <version>3.2.2</version>
</dependency> </dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.5.1</version>
</dependency>
<dependency> <dependency>
<groupId>velocity</groupId> <groupId>velocity</groupId>
<artifactId>velocity</artifactId> <artifactId>velocity</artifactId>
@ -428,21 +396,6 @@
<artifactId>swc-parser-lazy</artifactId> <artifactId>swc-parser-lazy</artifactId>
<version>3.1.7</version> <version>3.1.7</version>
</dependency> </dependency>
<dependency>
<groupId>org.everit.json</groupId>
<artifactId>org.everit.json.schema</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>io.frictionlessdata</groupId>
<artifactId>datapackage-java</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.frictionlessdata</groupId>
<artifactId>tableschema-java</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>joda-time</groupId> <groupId>joda-time</groupId>
<artifactId>joda-time</artifactId> <artifactId>joda-time</artifactId>
@ -483,6 +436,11 @@
<artifactId>arithcode</artifactId> <artifactId>arithcode</artifactId>
<version>1.1</version> <version>1.1</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<!-- test dependencies --> <!-- test dependencies -->

View File

@ -1,213 +0,0 @@
{
"version": "1.0.0",
"errors": {
"io-error": {
"name": "IO Error",
"type": "source",
"context": "table",
"weight": 100,
"message": "The data source returned an IO Error of type {error_type}",
"description": "Data reading error because of IO error.\n\n How it could be resolved:\n - Fix path if it's not correct."
},
"http-error": {
"name": "HTTP Error",
"type": "source",
"context": "table",
"weight": 100,
"message": "The data source returned an HTTP error with a status code of {status_code}",
"description": "Data reading error because of HTTP error.\n\n How it could be resolved:\n - Fix url link if it's not correct."
},
"source-error": {
"name": "Source Error",
"type": "source",
"context": "table",
"weight": 100,
"message": "The data source has not supported or has inconsistent contents; no tabular data can be extracted",
"description": "Data reading error because of not supported or inconsistent contents.\n\n How it could be resolved:\n - Fix data contents (e.g. change JSON data to array or arrays/objects).\n - Set correct source settings in {validator}."
},
"scheme-error": {
"name": "Scheme Error",
"type": "source",
"context": "table",
"weight": 100,
"message": "The data source is in an unknown scheme; no tabular data can be extracted",
"description": "Data reading error because of incorrect scheme.\n\n How it could be resolved:\n - Fix data scheme (e.g. change scheme from `ftp` to `http`).\n - Set correct scheme in {validator}."
},
"format-error": {
"name": "Format Error",
"type": "source",
"context": "table",
"weight": 100,
"message": "The data source is in an unknown format; no tabular data can be extracted",
"description": "Data reading error because of incorrect format.\n\n How it could be resolved:\n - Fix data format (e.g. change file extension from `txt` to `csv`).\n - Set correct format in {validator}."
},
"encoding-error": {
"name": "Encoding Error",
"type": "source",
"context": "table",
"weight": 100,
"message": "The data source could not be successfully decoded with {encoding} encoding",
"description": "Data reading error because of an encoding problem.\n\n How it could be resolved:\n - Fix data source if it's broken.\n - Set correct encoding in {validator}."
},
"blank-header": {
"name": "Blank Header",
"type": "structure",
"context": "head",
"weight": 3,
"message": "Header in column {column_number} is blank",
"description": "A column in the header row is missing a value. Column names should be provided.\n\n How it could be resolved:\n - Add the missing column name to the first row of the data source.\n - If the first row starts with, or ends with a comma, remove it.\n - If this error should be ignored disable `blank-header` check in {validator}."
},
"duplicate-header": {
"name": "Duplicate Header",
"type": "structure",
"context": "head",
"weight": 3,
"message": "Header in column {column_number} is duplicated to header in column(s) {column_numbers}",
"description": "Two columns in the header row have the same value. Column names should be unique.\n\n How it could be resolved:\n - Add the missing column name to the first row of the data.\n - If the first row starts with, or ends with a comma, remove it.\n - If this error should be ignored disable `duplicate-header` check in {validator}."
},
"blank-row": {
"name": "Blank Row",
"type": "structure",
"context": "body",
"weight": 9,
"message": "Row {row_number} is completely blank",
"description": "This row is empty. A row should contain at least one value.\n\n How it could be resolved:\n - Delete the row.\n - If this error should be ignored disable `blank-row` check in {validator}."
},
"duplicate-row": {
"name": "Duplicate Row",
"type": "structure",
"context": "body",
"weight": 5,
"message": "Row {row_number} is duplicated to row(s) {row_numbers}",
"description": "The exact same data has been seen in another row.\n\n How it could be resolved:\n - If some of the data is incorrect, correct it.\n - If the whole row is an incorrect duplicate, remove it.\n - If this error should be ignored disable `duplicate-row` check in {validator}."
},
"extra-value": {
"name": "Extra Value",
"type": "structure",
"context": "body",
"weight": 9,
"message": "Row {row_number} has an extra value in column {column_number}",
"description": "This row has more values compared to the header row (the first row in the data source). A key concept is that all the rows in tabular data must have the same number of columns.\n\n How it could be resolved:\n - Check data has an extra comma between the values in this row.\n - If this error should be ignored disable `extra-value` check in {validator}."
},
"missing-value": {
"name": "Missing Value",
"type": "structure",
"context": "body",
"weight": 9,
"message": "Row {row_number} has a missing value in column {column_number}",
"description": "This row has less values compared to the header row (the first row in the data source). A key concept is that all the rows in tabular data must have the same number of columns.\n\n How it could be resolved:\n - Check data is not missing a comma between the values in this row.\n - If this error should be ignored disable `missing-value` check in {validator}."
},
"schema-error": {
"name": "Table Schema Error",
"type": "schema",
"context": "table",
"weight": 15,
"message": "Table Schema error: {error_message}",
"description": "Provided schema is not valid.\n\n How it could be resolved:\n - Update schema descriptor to be a valid descriptor\n - If this error should be ignored disable schema checks in {validator}."
},
"non-matching-header": {
"name": "Non-Matching Header",
"type": "schema",
"context": "head",
"weight": 9,
"message": "Header in column {column_number} doesn't match field name {field_name} in the schema",
"description": "One of the data source headers doesn't match the field name defined in the schema.\n\n How it could be resolved:\n - Rename header in the data source or field in the schema\n - If this error should be ignored disable `non-matching-header` check in {validator}."
},
"extra-header": {
"name": "Extra Header",
"type": "schema",
"context": "head",
"weight": 9,
"message": "There is an extra header in column {column_number}",
"description": "The first row of the data source contains header that doesn't exist in the schema.\n\n How it could be resolved:\n - Remove the extra column from the data source or add the missing field to the schema\n - If this error should be ignored disable `extra-header` check in {validator}."
},
"missing-header": {
"name": "Missing Header",
"type": "schema",
"context": "head",
"weight": 9,
"message": "There is a missing header in column {column_number}",
"description": "Based on the schema there should be a header that is missing in the first row of the data source.\n\n How it could be resolved:\n - Add the missing column to the data source or remove the extra field from the schema\n - If this error should be ignored disable `missing-header` check in {validator}."
},
"type-or-format-error": {
"name": "Type or Format Error",
"type": "schema",
"context": "body",
"weight": 9,
"message": "The value {value} in row {row_number} and column {column_number} is not type {field_type} and format {field_format}",
"description": "The value does not match the schema type and format for this field.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If this value is correct, adjust the type and/or format.\n - To ignore the error, disable the `type-or-format-error` check in {validator}. In this case all schema checks for row values will be ignored."
},
"required-constraint": {
"name": "Required Constraint",
"type": "schema",
"context": "body",
"weight": 9,
"message": "Column {column_number} is a required field, but row {row_number} has no value",
"description": "This field is a required field, but it contains no value.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove the `required` constraint from the schema.\n - If this error should be ignored disable `required-constraint` check in {validator}."
},
"pattern-constraint": {
"name": "Pattern Constraint",
"type": "schema",
"context": "body",
"weight": 7,
"message": "The value {value} in row {row_number} and column {column_number} does not conform to the pattern constraint of {constraint}",
"description": "This field value should conform to constraint pattern.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `pattern` constraint in the schema.\n - If this error should be ignored disable `pattern-constraint` check in {validator}."
},
"unique-constraint": {
"name": "Unique Constraint",
"type": "schema",
"context": "body",
"weight": 9,
"message": "Rows {row_numbers} has unique constraint violation in column {column_number}",
"description": "This field is a unique field but it contains a value that has been used in another row.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then the values in this column are not unique. Remove the `unique` constraint from the schema.\n - If this error should be ignored disable `unique-constraint` check in {validator}."
},
"enumerable-constraint": {
"name": "Enumerable Constraint",
"type": "schema",
"context": "body",
"weight": 7,
"message": "The value {value} in row {row_number} and column {column_number} does not conform to the given enumeration: {constraint}",
"description": "This field value should be equal to one of the values in the enumeration constraint.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `enum` constraint in the schema.\n - If this error should be ignored disable `enumerable-constraint` check in {validator}."
},
"minimum-constraint": {
"name": "Minimum Constraint",
"type": "schema",
"context": "body",
"weight": 7,
"message": "The value {value} in row {row_number} and column {column_number} does not conform to the minimum constraint of {constraint}",
"description": "This field value should be greater or equal than constraint value.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `minimum` constraint in the schema.\n - If this error should be ignored disable `minimum-constraint` check in {validator}."
},
"maximum-constraint": {
"name": "Maximum Constraint",
"type": "schema",
"context": "body",
"weight": 7,
"message": "The value {value} in row {row_number} and column {column_number} does not conform to the maximum constraint of {constraint}",
"description": "This field value should be less or equal than constraint value.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `maximum` constraint in the schema.\n - If this error should be ignored disable `maximum-constraint` check in {validator}."
},
"minimum-length-constraint": {
"name": "Minimum Length Constraint",
"type": "schema",
"context": "body",
"weight": 7,
"message": "The value {value} in row {row_number} and column {column_number} does not conform to the minimum length constraint of {constraint}",
"description": "A lenght of this field value should be greater or equal than schema constraint value.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `minimumLength` constraint in the schema.\n - If this error should be ignored disable `minimum-length-constraint` check in {validator}."
},
"maximum-length-constraint": {
"name": "Maximum Length Constraint",
"type": "schema",
"context": "body",
"weight": 7,
"message": "The value {value} in row {row_number} and column {column_number} does not conform to the maximum length constraint of {constraint}",
"description": "A lenght of this field value should be less or equal than schema constraint value.\n\n How it could be resolved:\n - If this value is not correct, update the value.\n - If value is correct, then remove or refine the `maximumLength` constraint in the schema.\n - If this error should be ignored disable `maximum-length-constraint` check in {validator}."
}
}
}

View File

@ -1,16 +0,0 @@
{
"image": "",
"license": "",
"last_updated": "",
"keywords": [],
"sources": [{
"web": "",
"name": "",
"title": ""
}],
"name": "",
"description": "",
"resources": [],
"title": "",
"version": ""
}

View File

@ -1,49 +0,0 @@
/*
Copyright 2010, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.google.refine;
import java.util.Properties;
import org.json.JSONException;
import org.json.JSONWriter;
/**
* Interface for streaming out JSON, either into HTTP responses or
* serialization files.
*
* @author dfhuynh
*/
public interface Jsonizable {
public void write(JSONWriter writer, Properties options) throws JSONException;
}

View File

@ -37,7 +37,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -46,20 +45,20 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.tools.tar.TarOutputStream; import org.apache.tools.tar.TarOutputStream;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.history.HistoryEntryManager; import com.google.refine.history.HistoryEntryManager;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.metadata.IMetadata;
import com.google.refine.model.metadata.ProjectMetadata;
import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.PreferenceStore;
import com.google.refine.preference.TopList; import com.google.refine.preference.TopList;
import com.google.refine.util.ParsingUtilities;
/** /**
* ProjectManager is responsible for loading and saving the workspace and projects. * ProjectManager is responsible for loading and saving the workspace and projects.
@ -76,6 +75,7 @@ public abstract class ProjectManager {
// Don't spend more than this much time saving projects if doing a quick save // Don't spend more than this much time saving projects if doing a quick save
static protected final int QUICK_SAVE_MAX_TIME = 1000 * 30; // 30 secs static protected final int QUICK_SAVE_MAX_TIME = 1000 * 30; // 30 secs
protected Map<Long, ProjectMetadata> _projectsMetadata; protected Map<Long, ProjectMetadata> _projectsMetadata;
protected Map<String, Integer> _projectsTags;// TagName, number of projects having that tag protected Map<String, Integer> _projectsTags;// TagName, number of projects having that tag
protected PreferenceStore _preferenceStore; protected PreferenceStore _preferenceStore;
@ -193,7 +193,7 @@ public abstract class ProjectManager {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }//FIXME what should be the behaviour if metadata is null? i.e. not found
Project project = getProject(id); Project project = getProject(id);
if (project != null && metadata != null && metadata.getModified().isAfter(project.getLastSave())) { if (project != null && metadata != null && metadata.getModified().isAfter(project.getLastSave())) {
@ -202,7 +202,8 @@ public abstract class ProjectManager {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }//FIXME what should be the behaviour if project is null? i.e. not found or loaded.
//FIXME what should happen if the metadata is found, but not the project? or vice versa?
} }
} }
@ -213,7 +214,7 @@ public abstract class ProjectManager {
* @param projectId * @param projectId
* @throws Exception * @throws Exception
*/ */
public abstract void saveMetadata(IMetadata metadata, long projectId) throws Exception; public abstract void saveMetadata(ProjectMetadata metadata, long projectId) throws Exception;
/** /**
* Save project to the data store * Save project to the data store
@ -266,19 +267,19 @@ public abstract class ProjectManager {
Project project = _projects.get(id); // don't call getProject() as that will load the project. Project project = _projects.get(id); // don't call getProject() as that will load the project.
if (project != null) { if (project != null) {
LocalDateTime projectLastSaveTime = project.getLastSave();
boolean hasUnsavedChanges = boolean hasUnsavedChanges =
!metadata.getModified().isBefore(projectLastSaveTime); metadata.getModified().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() >= project.getLastSave().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
// We use >= instead of just > to avoid the case where a newly created project // We use >= instead of just > to avoid the case where a newly created project
// has the same modified and last save times, resulting in the project not getting // has the same modified and last save times, resulting in the project not getting
// saved at all. // saved at all.
if (hasUnsavedChanges) { if (hasUnsavedChanges) {
long msecsOverdue = ChronoUnit.MILLIS.between(projectLastSaveTime, startTimeOfSave); long msecsOverdue = startTimeOfSave.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - project.getLastSave().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
records.add(new SaveRecord(project, msecsOverdue)); records.add(new SaveRecord(project, msecsOverdue));
} else if (!project.getProcessManager().hasPending() } else if (!project.getProcessManager().hasPending()
&& ChronoUnit.MILLIS.between(projectLastSaveTime, startTimeOfSave) > PROJECT_FLUSH_DELAY) { && startTimeOfSave.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - project.getLastSave().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() > PROJECT_FLUSH_DELAY) {
/* /*
* It's been a while since the project was last saved and it hasn't been * It's been a while since the project was last saved and it hasn't been
@ -309,9 +310,12 @@ public abstract class ProjectManager {
"Saving some modified projects ..." "Saving some modified projects ..."
); );
for (int i = 0;i < records.size() && for (int i = 0;
(allModified || (ChronoUnit.MILLIS.between(startTimeOfSave, LocalDateTime.now()) < QUICK_SAVE_MAX_TIME)); i < records.size() &&
(allModified || (LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() -
startTimeOfSave.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() < QUICK_SAVE_MAX_TIME));
i++) { i++) {
try { try {
saveProject(records.get(i).project); saveProject(records.get(i).project);
} catch (Exception e) { } catch (Exception e) {
@ -342,6 +346,7 @@ public abstract class ProjectManager {
/** /**
* Gets the InterProjectModel from memory * Gets the InterProjectModel from memory
*/ */
@JsonIgnore
public InterProjectModel getInterProjectModel() { public InterProjectModel getInterProjectModel() {
return _interProjectModel; return _interProjectModel;
} }
@ -349,7 +354,7 @@ public abstract class ProjectManager {
/** /**
* Gets the project metadata from memory * Gets the project metadata from memory
* Requires that the metadata has already been loaded from the data store. * Requires that the metadata has already been loaded from the data store
* @param id * @param id
* @return * @return
*/ */
@ -394,7 +399,7 @@ public abstract class ProjectManager {
* @param placeHolderJsonObj * @param placeHolderJsonObj
* @return * @return
*/ */
private boolean isValidUserMetadataDefinition(JSONObject placeHolderJsonObj) { private boolean isValidUserMetadataDefinition(ObjectNode placeHolderJsonObj) {
return (placeHolderJsonObj != null && return (placeHolderJsonObj != null &&
placeHolderJsonObj.has("name") && placeHolderJsonObj.has("name") &&
placeHolderJsonObj.has("display")); placeHolderJsonObj.has("display"));
@ -405,51 +410,46 @@ public abstract class ProjectManager {
return; return;
// place holder // place holder
JSONArray userMetadataPreference = null; ArrayNode userMetadataPreference = null;
// actual metadata for project // actual metadata for project
JSONArray jsonObjArray = metadata.getUserMetadata(); ArrayNode jsonObjArray = metadata.getUserMetadata();
initDisplay(jsonObjArray); initDisplay(jsonObjArray);
try {
String userMeta = (String)_preferenceStore.get(PreferenceStore.USER_METADATA_KEY); String userMeta = (String)_preferenceStore.get(PreferenceStore.USER_METADATA_KEY);
if (userMeta == null) if (userMeta == null)
return; return;
userMetadataPreference = new JSONArray(userMeta); userMetadataPreference = ParsingUtilities.mapper.createArrayNode();
} catch (JSONException e1) {
logger.warn("wrong definition of userMetadata format. Please use form [{\"name\": \"client name\", \"display\":true}, {\"name\": \"progress\", \"display\":false}]");
logger.error(ExceptionUtils.getStackTrace(e1));
}
for (int index = 0; index < userMetadataPreference.length(); index++) { for (int index = 0; index < userMetadataPreference.size(); index++) {
try {
boolean found = false; boolean found = false;
JSONObject placeHolderJsonObj = userMetadataPreference.getJSONObject(index); ObjectNode placeHolderJsonObj = (ObjectNode) userMetadataPreference.get(index);
if (!isValidUserMetadataDefinition(placeHolderJsonObj)) { if (!isValidUserMetadataDefinition(placeHolderJsonObj)) {
logger.warn("Skipped invalid user metadata definition" + placeHolderJsonObj.toString()); logger.warn("Skipped invalid user metadata definition" + placeHolderJsonObj.toString());
continue; continue;
} }
for (int i = 0; i < jsonObjArray.length(); i++) { for (int i = 0; i < jsonObjArray.size(); i++) {
JSONObject jsonObj = jsonObjArray.getJSONObject(i); JsonNode jsonObj = jsonObjArray.get(i);
if (jsonObj.getString("name").equals(placeHolderJsonObj.getString("name"))) { if (!(jsonObj instanceof ObjectNode)) {
continue;
}
ObjectNode node = (ObjectNode)jsonObj;
if (node.get("name").asText("").equals(placeHolderJsonObj.get("name").asText(""))) {
found = true; found = true;
jsonObj.put("display", placeHolderJsonObj.get("display")); node.put("display", placeHolderJsonObj.get("display"));
break; break;
} }
} }
if (!found) { if (!found) {
placeHolderJsonObj.put("value", ""); placeHolderJsonObj.put("value", "");
metadata.getUserMetadata().put(placeHolderJsonObj); metadata.getUserMetadata().add(placeHolderJsonObj);
logger.info("Put the placeholder {} for project {}", logger.info("Put the placeholder {} for project {}",
placeHolderJsonObj.getString("name"), placeHolderJsonObj.get("name").asText(""),
metadata.getName()); metadata.getName());
} }
} catch (JSONException e) {
logger.warn("Exception when mergeEmptyUserMetadata",e);
}
} }
} }
@ -457,13 +457,11 @@ public abstract class ProjectManager {
* honor the meta data preference * honor the meta data preference
* @param jsonObjArray * @param jsonObjArray
*/ */
private void initDisplay(JSONArray jsonObjArray) { private void initDisplay(ArrayNode jsonObjArray) {
for (int index = 0; index < jsonObjArray.length(); index++) { for (int index = 0; index < jsonObjArray.size(); index++) {
try { if (jsonObjArray.get(index) instanceof ObjectNode) {
JSONObject projectMetaJsonObj = jsonObjArray.getJSONObject(index); ObjectNode projectMetaJsonObj = (ObjectNode) jsonObjArray.get(index);
projectMetaJsonObj.put("display", false); projectMetaJsonObj.put("display", false);
} catch (JSONException e) {
logger.error(ExceptionUtils.getStackTrace(e));
} }
} }
} }
@ -472,7 +470,7 @@ public abstract class ProjectManager {
* Gets all the project Metadata currently held in memory. * Gets all the project Metadata currently held in memory.
* @return * @return
*/ */
@JsonIgnore
public Map<Long, ProjectMetadata> getAllProjectMetadata() { public Map<Long, ProjectMetadata> getAllProjectMetadata() {
for(Project project : _projects.values()) { for(Project project : _projects.values()) {
mergeEmptyUserMetadata(project.getMetadata()); mergeEmptyUserMetadata(project.getMetadata());
@ -486,11 +484,11 @@ public abstract class ProjectManager {
* *
* @return * @return
*/ */
@JsonIgnore
public Map<String, Integer> getAllProjectTags() { public Map<String, Integer> getAllProjectTags() {
return _projectsTags; return _projectsTags;
} }
/** /**
* Gets the required project from the data store * Gets the required project from the data store
* If project does not already exist in memory, it is loaded from the data store * If project does not already exist in memory, it is loaded from the data store
@ -517,6 +515,7 @@ public abstract class ProjectManager {
* Gets the preference store * Gets the preference store
* @return * @return
*/ */
@JsonProperty("preferences")
public PreferenceStore getPreferenceStore() { public PreferenceStore getPreferenceStore() {
return _preferenceStore; return _preferenceStore;
} }
@ -525,6 +524,7 @@ public abstract class ProjectManager {
* Gets all expressions from the preference store * Gets all expressions from the preference store
* @return * @return
*/ */
@JsonIgnore
public List<String> getExpressions() { public List<String> getExpressions() {
return ((TopList) _preferenceStore.get("scripting.expressions")).getList(); return ((TopList) _preferenceStore.get("scripting.expressions")).getList();
} }
@ -533,6 +533,7 @@ public abstract class ProjectManager {
* The history entry manager deals with changes * The history entry manager deals with changes
* @return manager for handling history * @return manager for handling history
*/ */
@JsonIgnore
public abstract HistoryEntryManager getHistoryEntryManager(); public abstract HistoryEntryManager getHistoryEntryManager();
@ -596,9 +597,8 @@ public abstract class ProjectManager {
* *
* @param ps * @param ps
*/ */
public static void preparePreferenceStore(PreferenceStore ps) { static protected void preparePreferenceStore(PreferenceStore ps) {
ps.put("scripting.expressions", new TopList(s_expressionHistoryMax)); ps.put("scripting.expressions", new TopList(s_expressionHistoryMax));
ps.put("scripting.starred-expressions", new TopList(Integer.MAX_VALUE)); ps.put("scripting.starred-expressions", new TopList(Integer.MAX_VALUE));
} }
} }

View File

@ -0,0 +1,376 @@
/*
Copyright 2010, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.google.refine;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.preference.PreferenceStore;
import com.google.refine.util.JsonViews;
import com.google.refine.util.ParsingUtilities;
public class ProjectMetadata {
public final static String DEFAULT_FILE_NAME = "metadata.json";
public final static String TEMP_FILE_NAME = "metadata.temp.json";
public final static String OLD_FILE_NAME = "metadata.old.json";
@JsonProperty("created")
private final LocalDateTime _created;
@JsonProperty("modified")
private LocalDateTime _modified;
@JsonIgnore
private LocalDateTime written = null;
@JsonProperty("name")
private String _name = "";
@JsonProperty("password")
@JsonView(JsonViews.SaveMode.class)
private String _password = "";
@JsonProperty("encoding")
@JsonView(JsonViews.SaveMode.class)
private String _encoding = "";
@JsonProperty("encodingConfidence")
@JsonView(JsonViews.SaveMode.class)
private int _encodingConfidence;
@JsonProperty("tags")
private String[] _tags = new String[0];
@JsonProperty("creator")
private String _creator = "";
@JsonProperty("contributors")
private String _contributors = "";
@JsonProperty("subject")
private String _subject = ""; // Several refine projects may be linked
@JsonProperty("description")
private String _description = ""; // free form of comment
@JsonProperty("rowCount")
private int _rowCount; // at the creation. Essential for cleaning old projects too heavy
@JsonProperty("title")
private String _title = "";
@JsonProperty("version")
private String _version = "";
@JsonProperty("license")
private String license = "";
@JsonProperty("homepage")
private String homepage = "";
@JsonProperty("image")
private String image = "";
// import options is an array for 1-n data sources
@JsonProperty("importOptionMetadata")
private ArrayNode _importOptionMetadata = ParsingUtilities.mapper.createArrayNode();
// user metadata
@JsonIgnore
private ArrayNode _userMetadata = ParsingUtilities.mapper.createArrayNode();
@JsonProperty("customMetadata")
private Map<String, Serializable> _customMetadata = new HashMap<String, Serializable>();
@JsonProperty("preferences")
@JsonView(JsonViews.SaveMode.class)
private PreferenceStore _preferenceStore = new PreferenceStore();
private final static Logger logger = LoggerFactory.getLogger("project_metadata");
protected ProjectMetadata(LocalDateTime date) {
_created = date;
preparePreferenceStore(_preferenceStore);
}
public ProjectMetadata() {
this(LocalDateTime.now());
_modified = _created;
}
public ProjectMetadata(LocalDateTime created, LocalDateTime modified, String name) {
this(created);
_modified = modified;
_name = name;
}
@JsonIgnore
public boolean isDirty() {
return written == null || _modified.isAfter(written);
}
static protected void preparePreferenceStore(PreferenceStore ps) {
ProjectManager.preparePreferenceStore(ps);
// Any project specific preferences?
}
@JsonIgnore
public LocalDateTime getCreated() {
return _created;
}
@JsonIgnore
public void setName(String name) {
this._name = name;
updateModified();
}
@JsonIgnore
public String getName() {
return _name;
}
@JsonIgnore
public void setEncoding(String encoding) {
this._encoding = encoding;
updateModified();
}
@JsonIgnore
public String getEncoding() {
return _encoding;
}
@JsonIgnore
public void setEncodingConfidence(int confidence) {
this._encodingConfidence = confidence;
updateModified();
}
@JsonIgnore
public void setEncodingConfidence(String confidence) {
if (confidence != null) {
this.setEncodingConfidence(Integer.parseInt(confidence));
}
}
@JsonIgnore
public int getEncodingConfidence() {
return _encodingConfidence;
}
@JsonIgnore
public void setTags(String[] tags) {
if (tags != null) {
List<String> tmpTags = new ArrayList<String>(tags.length);
for (String tag : tags) {
if (tag != null) {
String trimmedTag = tag.trim();
if (!trimmedTag.isEmpty()) {
tmpTags.add(trimmedTag);
}
}
}
this._tags = tmpTags.toArray(new String[tmpTags.size()]);
} else {
this._tags = tags;
}
updateModified();
}
@JsonIgnore
public String[] getTags() {
if (_tags == null) this._tags = new String[0];
return _tags;
}
@JsonIgnore
public void setPassword(String password) {
this._password = password;
updateModified();
}
@JsonIgnore
public String getPassword() {
return _password;
}
@JsonIgnore
public LocalDateTime getModified() {
return _modified;
}
@JsonIgnore
public void updateModified() {
_modified = LocalDateTime.now();
}
@JsonIgnore
public PreferenceStore getPreferenceStore() {
return _preferenceStore;
}
@JsonIgnore
public Serializable getCustomMetadata(String key) {
return _customMetadata.get(key);
}
public void setCustomMetadata(String key, Serializable value) {
if (value == null) {
_customMetadata.remove(key);
} else {
_customMetadata.put(key, value);
}
updateModified();
}
@JsonIgnore
public ArrayNode getImportOptionMetadata() {
return _importOptionMetadata;
}
@JsonIgnore
public void setImportOptionMetadata(ArrayNode jsonArray) {
_importOptionMetadata = jsonArray;
updateModified();
}
public void appendImportOptionMetadata(ObjectNode options) {
_importOptionMetadata.add(options);
updateModified();
}
@JsonIgnore
public String getCreator() {
return _creator;
}
@JsonIgnore
public void setCreator(String creator) {
this._creator = creator;
updateModified();
}
@JsonIgnore
public String getContributors() {
return _contributors;
}
@JsonIgnore
public void setContributors(String contributors) {
this._contributors = contributors;
updateModified();
}
@JsonIgnore
public String getSubject() {
return _subject;
}
@JsonIgnore
public void setSubject(String subject) {
this._subject = subject;
updateModified();
}
@JsonIgnore
public String getDescription() {
return _description;
}
@JsonIgnore
public void setDescription(String description) {
this._description = description;
updateModified();
}
@JsonIgnore
public int getRowCount() {
return _rowCount;
}
@JsonIgnore
public void setRowCount(int rowCount) {
this._rowCount = rowCount;
updateModified();
}
@JsonIgnore
public ArrayNode getUserMetadata() {
return _userMetadata;
}
@JsonProperty("userMetadata")
@JsonInclude(Include.NON_NULL)
public ArrayNode getUserMetadataJson() {
if (_userMetadata != null && _userMetadata.size() > 0) {
return _userMetadata;
}
return null;
}
@JsonIgnore
public void setUserMetadata(ArrayNode userMetadata) {
this._userMetadata = userMetadata;
}
private void updateUserMetadata(String metaName, String valueString) {
for (int i = 0; i < _userMetadata.size(); i++) {
ObjectNode obj = (ObjectNode)_userMetadata.get(i);
if (obj.get("name").asText("").equals(metaName)) {
obj.put("value", valueString);
}
}
}
public void setAnyField(String metaName, String valueString) {
Class<? extends ProjectMetadata> metaClass = this.getClass();
try {
Field metaField = metaClass.getDeclaredField("_" + metaName);
if (metaName.equals("tags")) {
metaField.set(this, valueString.split(","));
} else {
metaField.set(this, valueString);
}
} catch (NoSuchFieldException e) {
updateUserMetadata(metaName, valueString);
} catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
logger.error(ExceptionUtils.getFullStackTrace(e));
}
}
}

View File

@ -34,12 +34,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.browsing; package com.google.refine.browsing;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.util.Properties;
import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonCreator;
import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.Jsonizable;
import com.google.refine.util.StringUtils; import com.google.refine.util.StringUtils;
/** /**
@ -49,11 +46,18 @@ import com.google.refine.util.StringUtils;
* *
* Facet choices that are presented to the user as text are stored as decorated values. * Facet choices that are presented to the user as text are stored as decorated values.
*/ */
public class DecoratedValue implements Jsonizable { public class DecoratedValue {
@JsonProperty("v")
final public Object value; final public Object value;
@JsonProperty("l")
final public String label; final public String label;
public DecoratedValue(Object value, String label) { @JsonCreator
public DecoratedValue(
@JsonProperty("v")
Object value,
@JsonProperty("l")
String label) {
if (value instanceof OffsetDateTime) { if (value instanceof OffsetDateTime) {
this.value = StringUtils.toString(value); this.value = StringUtils.toString(value);
} else { } else {
@ -61,13 +65,4 @@ public class DecoratedValue implements Jsonizable {
} }
this.label = label; this.label = label;
} }
@Override
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("v"); writer.value(value);
writer.key("l"); writer.value(label);
writer.endObject();
}
} }

View File

@ -36,14 +36,10 @@ package com.google.refine.browsing;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonIgnore;
import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty;
import org.json.JSONWriter;
import com.google.refine.Jsonizable;
import com.google.refine.browsing.facets.Facet; import com.google.refine.browsing.facets.Facet;
import com.google.refine.browsing.util.ConjunctiveFilteredRecords; import com.google.refine.browsing.util.ConjunctiveFilteredRecords;
import com.google.refine.browsing.util.ConjunctiveFilteredRows; import com.google.refine.browsing.util.ConjunctiveFilteredRows;
@ -54,10 +50,13 @@ import com.google.refine.model.Row;
/** /**
* Faceted browsing engine. * Faceted browsing engine.
*/ */
public class Engine implements Jsonizable { public class Engine {
static public enum Mode { static public enum Mode {
@JsonProperty("row-based")
RowBased, RowBased,
@JsonProperty("record-based")
RecordBased RecordBased
} }
public final static String INCLUDE_DEPENDENT = "includeDependent"; public final static String INCLUDE_DEPENDENT = "includeDependent";
@ -65,8 +64,11 @@ public class Engine implements Jsonizable {
public final static String MODE_ROW_BASED = "row-based"; public final static String MODE_ROW_BASED = "row-based";
public final static String MODE_RECORD_BASED = "record-based"; public final static String MODE_RECORD_BASED = "record-based";
@JsonIgnore
protected Project _project; protected Project _project;
@JsonProperty("facets")
protected List<Facet> _facets = new LinkedList<Facet>(); protected List<Facet> _facets = new LinkedList<Facet>();
@JsonIgnore
protected EngineConfig _config = new EngineConfig(Collections.emptyList(), Mode.RowBased); protected EngineConfig _config = new EngineConfig(Collections.emptyList(), Mode.RowBased);
static public String modeToString(Mode mode) { static public String modeToString(Mode mode) {
@ -80,6 +82,7 @@ public class Engine implements Jsonizable {
_project = project; _project = project;
} }
@JsonProperty("engine-mode")
public Mode getMode() { public Mode getMode() {
return _config.getMode(); return _config.getMode();
} }
@ -87,6 +90,7 @@ public class Engine implements Jsonizable {
_config = new EngineConfig(_config.getFacetConfigs(), mode); _config = new EngineConfig(_config.getFacetConfigs(), mode);
} }
@JsonIgnore
public FilteredRows getAllRows() { public FilteredRows getAllRows() {
return new FilteredRows() { return new FilteredRows() {
@Override @Override
@ -108,6 +112,7 @@ public class Engine implements Jsonizable {
}; };
} }
@JsonIgnore
public FilteredRows getAllFilteredRows() { public FilteredRows getAllFilteredRows() {
return getFilteredRows(null); return getFilteredRows(null);
} }
@ -130,6 +135,7 @@ public class Engine implements Jsonizable {
throw new InternalError("Unknown mode."); throw new InternalError("Unknown mode.");
} }
@JsonIgnore
public FilteredRecords getAllRecords() { public FilteredRecords getAllRecords() {
return new FilteredRecords() { return new FilteredRecords() {
@Override @Override
@ -148,6 +154,7 @@ public class Engine implements Jsonizable {
}; };
} }
@JsonIgnore
public FilteredRecords getFilteredRecords() { public FilteredRecords getFilteredRecords() {
return getFilteredRecords(null); return getFilteredRecords(null);
} }
@ -168,12 +175,6 @@ public class Engine implements Jsonizable {
throw new InternalError("This method should not be called when the engine is not in record mode."); throw new InternalError("This method should not be called when the engine is not in record mode.");
} }
@Deprecated
public void initializeFromJSON(JSONObject o) throws JSONException {
EngineConfig config = EngineConfig.reconstruct(o);
initializeFromConfig(config);
}
public void initializeFromConfig(EngineConfig config) { public void initializeFromConfig(EngineConfig config) {
_config = config; _config = config;
_facets = config.getFacetConfigs().stream() _facets = config.getFacetConfigs().stream()
@ -181,7 +182,7 @@ public class Engine implements Jsonizable {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public void computeFacets() throws JSONException { public void computeFacets() {
if (_config.getMode().equals(Mode.RowBased)) { if (_config.getMode().equals(Mode.RowBased)) {
for (Facet facet : _facets) { for (Facet facet : _facets) {
FilteredRows filteredRows = getFilteredRows(facet); FilteredRows filteredRows = getFilteredRows(facet);
@ -198,19 +199,4 @@ public class Engine implements Jsonizable {
throw new InternalError("Unknown mode."); throw new InternalError("Unknown mode.");
} }
} }
@Override
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("facets");
writer.array();
for (Facet facet : _facets) {
facet.write(writer, options);
}
writer.endArray();
writer.key(MODE); writer.value(_config.getMode().equals(Mode.RowBased) ? MODE_ROW_BASED : MODE_RECORD_BASED);
writer.endObject();
}
} }

View File

@ -1,102 +1,50 @@
package com.google.refine.browsing; package com.google.refine.browsing;
import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Properties;
import org.json.JSONArray; import com.fasterxml.jackson.annotation.JsonCreator;
import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonProperty;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.google.refine.Jsonizable;
import com.google.refine.browsing.Engine.Mode; import com.google.refine.browsing.Engine.Mode;
import com.google.refine.browsing.facets.FacetConfig; import com.google.refine.browsing.facets.FacetConfig;
import com.google.refine.browsing.facets.ListFacet.ListFacetConfig; import com.google.refine.util.ParsingUtilities;
import com.google.refine.browsing.facets.RangeFacet.RangeFacetConfig;
import com.google.refine.browsing.facets.ScatterplotFacet.ScatterplotFacetConfig;
import com.google.refine.browsing.facets.TextSearchFacet.TextSearchFacetConfig;
import com.google.refine.browsing.facets.TimeRangeFacet.TimeRangeFacetConfig;
public class EngineConfig implements Jsonizable { public class EngineConfig {
protected final List<FacetConfig> _facets; protected final List<FacetConfig> _facets;
protected final Mode _mode; protected final Mode _mode;
public EngineConfig(List<FacetConfig> facets, Mode mode) { @JsonCreator
_facets = facets; public EngineConfig(
_mode = mode; @JsonProperty("facets")
List<FacetConfig> facets,
@JsonProperty("mode")
Mode mode) {
_facets = facets == null ? Collections.emptyList() : facets;
_mode = mode == null ? Mode.RowBased : mode;
} }
@JsonProperty("mode")
public Mode getMode() { public Mode getMode() {
return _mode; return _mode;
} }
@JsonProperty("facets")
public List<FacetConfig> getFacetConfigs() { public List<FacetConfig> getFacetConfigs() {
return _facets; return _facets;
} }
public static EngineConfig reconstruct(JSONObject o) { public static EngineConfig reconstruct(String json) {
if (o == null) { if(json == null) {
return new EngineConfig(Collections.emptyList(), Mode.RowBased); return new EngineConfig(Collections.emptyList(), Mode.RowBased);
} }
try {
List<FacetConfig> facets = new LinkedList<>(); return ParsingUtilities.mapper.readValue(json, EngineConfig.class);
if (o.has("facets") && !o.isNull("facets")) { } catch (IOException e) {
JSONArray a = o.getJSONArray("facets"); e.printStackTrace();
int length = a.length(); return null;
for (int i = 0; i < length; i++) {
JSONObject fo = a.getJSONObject(i);
String type = fo.has("type") ? fo.getString("type") : "list";
FacetConfig facet = null;
if ("list".equals(type)) {
facet = new ListFacetConfig();
} else if ("range".equals(type)) {
facet = new RangeFacetConfig();
} else if ("timerange".equals(type)) {
facet = new TimeRangeFacetConfig();
} else if ("scatterplot".equals(type)) {
facet = new ScatterplotFacetConfig();
} else if ("text".equals(type)) {
facet = new TextSearchFacetConfig();
}
if (facet != null) {
facet.initializeFromJSON(fo);
facets.add(facet);
} }
} }
} }
Mode mode = Mode.RowBased;
// for backward compatibility
if (o.has(Engine.INCLUDE_DEPENDENT) && !o.isNull(Engine.INCLUDE_DEPENDENT)) {
mode = o.getBoolean(Engine.INCLUDE_DEPENDENT) ? Mode.RecordBased : Mode.RowBased;
}
if (o.has(Engine.MODE) && !o.isNull(Engine.MODE)) {
mode = Engine.MODE_ROW_BASED.equals(o.getString(Engine.MODE)) ? Mode.RowBased : Mode.RecordBased;
}
return new EngineConfig(facets, mode);
}
@Override
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("facets");
writer.array();
for (FacetConfig facet : _facets) {
facet.write(writer, options);
}
writer.endArray();
writer.key(Engine.MODE); writer.value(_mode == Mode.RowBased ? Engine.MODE_ROW_BASED : Engine.MODE_RECORD_BASED);
writer.endObject();
}
}

View File

@ -33,7 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.browsing.facets; package com.google.refine.browsing.facets;
import com.google.refine.Jsonizable;
import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRecords;
import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.FilteredRows;
import com.google.refine.browsing.RecordFilter; import com.google.refine.browsing.RecordFilter;
@ -43,7 +42,7 @@ import com.google.refine.model.Project;
/** /**
* Interface of facets. * Interface of facets.
*/ */
public interface Facet extends Jsonizable { public interface Facet {
public RowFilter getRowFilter(Project project); public RowFilter getRowFilter(Project project);
public RecordFilter getRecordFilter(Project project); public RecordFilter getRecordFilter(Project project);

View File

@ -1,8 +1,9 @@
package com.google.refine.browsing.facets; package com.google.refine.browsing.facets;
import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.google.refine.Jsonizable; import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.google.refine.model.Project; import com.google.refine.model.Project;
@ -12,20 +13,30 @@ import com.google.refine.model.Project;
* of operations. It does not contain the actual values displayed by * of operations. It does not contain the actual values displayed by
* the facet. * the facet.
* *
* @author antonin * @author Antonin Delpeuch
* *
*/ */
public interface FacetConfig extends Jsonizable { @JsonTypeInfo(
/** use=JsonTypeInfo.Id.NAME,
* Reads the facet configuration from a JSON object (will be removed once we migrate to Jackson) include=JsonTypeInfo.As.PROPERTY,
* @param fo property="type")
*/ @JsonSubTypes({
public void initializeFromJSON(JSONObject fo); @Type(value = ListFacet.ListFacetConfig.class, name = "list"),
@Type(value = RangeFacet.RangeFacetConfig.class, name = "range"),
@Type(value = TimeRangeFacet.TimeRangeFacetConfig.class, name = "timerange"),
@Type(value = TextSearchFacet.TextSearchFacetConfig.class, name = "text"),
@Type(value = ScatterplotFacet.ScatterplotFacetConfig.class, name = "scatterplot") })
public interface FacetConfig {
/** /**
* Instantiates the given facet on a particular project. * Instantiates the given facet on a particular project.
* @param project * @param project
* @return a computed facet on the given project. * @return a computed facet on the given project.
*/ */
public Facet apply(Project project); public Facet apply(Project project);
/**
* The facet type as stored in json.
*/
@JsonProperty("type")
public String getJsonType();
} }

View File

@ -0,0 +1,35 @@
package com.google.refine.browsing.facets;
import java.io.IOException;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.databind.DatabindContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.google.refine.model.recon.ReconConfig;
public class FacetConfigResolver extends TypeIdResolverBase {
protected TypeFactory factory = TypeFactory.defaultInstance();
@Override
public Id getMechanism() {
return Id.NAME;
}
@Override
public String idFromValue(Object instance) {
return ((ReconConfig)instance).getMode();
}
@Override
public String idFromValueAndType(Object instance, Class<?> type) {
return ReconConfig.s_opClassToName.get(type);
}
@Override
public JavaType typeFromId(DatabindContext context, String id) throws IOException {
return factory.constructSimpleType(ReconConfig.getClassFromMode(id), new JavaType[0]);
}
}

View File

@ -35,13 +35,13 @@ package com.google.refine.browsing.facets;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.stream.Collectors;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.browsing.DecoratedValue; import com.google.refine.browsing.DecoratedValue;
import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRecords;
@ -57,84 +57,67 @@ import com.google.refine.expr.MetaParser;
import com.google.refine.expr.ParsingException; import com.google.refine.expr.ParsingException;
import com.google.refine.model.Column; import com.google.refine.model.Column;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.util.JSONUtilities;
public class ListFacet implements Facet { public class ListFacet implements Facet {
public static final String ERR_TOO_MANY_CHOICES = "Too many choices";
/**
* Wrapper to respect the serialization format
*/
public static class DecoratedValueWrapper {
@JsonProperty("v")
public final DecoratedValue value;
@JsonCreator
public DecoratedValueWrapper(
@JsonProperty("v") DecoratedValue value) {
this.value = value;
}
}
/* /*
* Configuration * Configuration
*/ */
public static class ListFacetConfig implements FacetConfig { public static class ListFacetConfig implements FacetConfig {
@JsonProperty("name")
public String name; public String name;
@JsonProperty("expression")
public String expression; public String expression;
@JsonProperty("columnName")
public String columnName; public String columnName;
@JsonProperty("invert")
public boolean invert; public boolean invert;
// If true, then facet won't show the blank and error choices // If true, then facet won't show the blank and error choices
@JsonProperty("omitBlank")
public boolean omitBlank; public boolean omitBlank;
@JsonProperty("omitError")
public boolean omitError; public boolean omitError;
@JsonIgnore
public List<DecoratedValue> selection = new LinkedList<>(); public List<DecoratedValue> selection = new LinkedList<>();
@JsonProperty("selectNumber")
public boolean selectNumber; public boolean selectNumber;
@JsonProperty("selectDateTime")
public boolean selectDateTime; public boolean selectDateTime;
@JsonProperty("selectBoolean")
public boolean selectBoolean; public boolean selectBoolean;
@JsonProperty("selectBlank")
public boolean selectBlank; public boolean selectBlank;
@JsonProperty("selectError")
public boolean selectError; public boolean selectError;
@Override @JsonProperty("selection")
public void write(JSONWriter writer, Properties options) public List<DecoratedValueWrapper> getWrappedSelection() {
throws JSONException { return selection.stream()
writer.object(); .map(e -> new DecoratedValueWrapper(e))
writer.key("type"); writer.value("list"); .collect(Collectors.toList());
writer.key("name"); writer.value(name);
writer.key("expression"); writer.value(expression);
writer.key("columnName"); writer.value(columnName);
writer.key("invert"); writer.value(invert);
writer.key("selection"); writer.array();
for (DecoratedValue choice : selection) {
writer.object();
writer.key("v");
choice.write(writer, options);
writer.endObject();
}
writer.endArray();
writer.key("selectNumber"); writer.value(selectNumber);
writer.key("selectDateTime"); writer.value(selectDateTime);
writer.key("selectBoolean"); writer.value(selectBoolean);
writer.key("omitBlank"); writer.value(omitBlank);
writer.key("selectBlank"); writer.value(selectBlank);
writer.key("omitError"); writer.value(omitError);
writer.key("selectError"); writer.value(selectError);
writer.endObject();
} }
@Override @JsonProperty("selection")
public void initializeFromJSON(JSONObject o) { public void setSelection(List<DecoratedValueWrapper> wrapped) {
name = o.getString("name"); selection = wrapped.stream()
expression = o.getString("expression"); .map(e -> e.value)
columnName = o.getString("columnName"); .collect(Collectors.toList());
invert = o.has("invert") && o.getBoolean("invert");
JSONArray a = o.getJSONArray("selection");
int length = a.length();
for (int i = 0; i < length; i++) {
JSONObject oc = a.getJSONObject(i);
JSONObject ocv = oc.getJSONObject("v");
DecoratedValue decoratedValue = new DecoratedValue(
ocv.get("v"), ocv.getString("l"));
selection.add(decoratedValue);
}
omitBlank = JSONUtilities.getBoolean(o, "omitBlank", false);
omitError = JSONUtilities.getBoolean(o, "omitError", false);
selectNumber = JSONUtilities.getBoolean(o, "selectNumber", false);
selectDateTime = JSONUtilities.getBoolean(o, "selectDateTime", false);
selectBoolean = JSONUtilities.getBoolean(o, "selectBoolean", false);
selectBlank = JSONUtilities.getBoolean(o, "selectBlank", false);
selectError = JSONUtilities.getBoolean(o, "selectError", false);
} }
@Override @Override
@ -143,6 +126,27 @@ public class ListFacet implements Facet {
facet.initializeFromConfig(this, project); facet.initializeFromConfig(this, project);
return facet; return facet;
} }
@Override
public String getJsonType() {
return "list";
}
}
/**
* Wrapper class for choice counts and selection status for blank and error
*/
public static class OtherChoice {
@JsonProperty("s")
boolean selected;
@JsonProperty("c")
int count;
public OtherChoice(
@JsonProperty("s") boolean selected,
@JsonProperty("c") int count) {
this.selected = selected;
this.count = count;
}
} }
ListFacetConfig _config = new ListFacetConfig(); ListFacetConfig _config = new ListFacetConfig();
@ -167,65 +171,69 @@ public class ListFacet implements Facet {
public ListFacet() { public ListFacet() {
} }
@Override @JsonProperty("name")
public void write(JSONWriter writer, Properties options) public String getName() {
throws JSONException { return _config.name;
writer.object();
writer.key("name"); writer.value(_config.name);
writer.key("expression"); writer.value(_config.expression);
writer.key("columnName"); writer.value(_config.columnName);
writer.key("invert"); writer.value(_config.invert);
if (_errorMessage != null) {
writer.key("error"); writer.value(_errorMessage);
} else if (_choices.size() > getLimit()) {
writer.key("error"); writer.value("Too many choices");
writer.key("choiceCount"); writer.value(_choices.size());
} else {
writer.key("choices"); writer.array();
for (NominalFacetChoice choice : _choices) {
choice.write(writer, options);
}
writer.endArray();
if (_config.selectNumber || _numberCount > 0) {
writer.key("numberChoice");
writer.object();
writer.key("s"); writer.value(_config.selectNumber);
writer.key("c"); writer.value(_numberCount);
writer.endObject();
}
if (_config.selectDateTime || _datetimeCount > 0) {
writer.key("datetimeChoice");
writer.object();
writer.key("s"); writer.value(_config.selectDateTime);
writer.key("c"); writer.value(_datetimeCount);
writer.endObject();
}
if (_config.selectBoolean || _booleanCount > 0) {
writer.key("booleanChoice");
writer.object();
writer.key("s"); writer.value(_config.selectBoolean);
writer.key("c"); writer.value(_booleanCount);
writer.endObject();
}
if (!_config.omitBlank && (_config.selectBlank || _blankCount > 0)) {
writer.key("blankChoice");
writer.object();
writer.key("s"); writer.value(_config.selectBlank);
writer.key("c"); writer.value(_blankCount);
writer.endObject();
}
if (!_config.omitError && (_config.selectError || _errorCount > 0)) {
writer.key("errorChoice");
writer.object();
writer.key("s"); writer.value(_config.selectError);
writer.key("c"); writer.value(_errorCount);
writer.endObject();
}
} }
writer.endObject(); @JsonProperty("columnName")
public String getColumnName() {
return _config.columnName;
}
@JsonProperty("expression")
public String getExpression() {
return _config.expression;
}
@JsonProperty("invert")
public boolean getInvert() {
return _config.invert;
}
@JsonProperty("error")
@JsonInclude(Include.NON_NULL)
public String getError() {
if (_errorMessage == null && _choices.size() > getLimit()) {
return ERR_TOO_MANY_CHOICES;
}
return _errorMessage;
}
@JsonProperty("choiceCount")
@JsonInclude(Include.NON_NULL)
public Integer getChoiceCount() {
if (_errorMessage == null && _choices.size() > getLimit()) {
return _choices.size();
}
return null;
}
@JsonProperty("choices")
@JsonInclude(Include.NON_NULL)
public List<NominalFacetChoice> getChoices() {
if (getError() == null) {
return _choices;
}
return null;
}
@JsonProperty("blankChoice")
@JsonInclude(Include.NON_NULL)
public OtherChoice getBlankChoice() {
if (getError() == null && !_config.omitBlank && (_config.selectBlank || _blankCount > 0)) {
return new OtherChoice(_config.selectBlank, _blankCount);
}
return null;
}
@JsonProperty("errorChoice")
@JsonInclude(Include.NON_NULL)
public OtherChoice getErrorChoice() {
if (getError() == null && !_config.omitError && (_config.selectError || _errorCount > 0)) {
return new OtherChoice(_config.selectError, _errorCount);
}
return null;
} }
protected int getLimit() { protected int getLimit() {

View File

@ -33,34 +33,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.browsing.facets; package com.google.refine.browsing.facets;
import java.util.Properties; import com.fasterxml.jackson.annotation.JsonProperty;
import org.json.JSONException;
import org.json.JSONWriter;
import com.google.refine.Jsonizable;
import com.google.refine.browsing.DecoratedValue; import com.google.refine.browsing.DecoratedValue;
/** /**
* Store a facet choice that has a decorated value, a count of matched rows, * Store a facet choice that has a decorated value, a count of matched rows,
* and a flag of whether it has been selected. * and a flag of whether it has been selected.
*/ */
public class NominalFacetChoice implements Jsonizable { public class NominalFacetChoice {
@JsonProperty("v")
final public DecoratedValue decoratedValue; final public DecoratedValue decoratedValue;
@JsonProperty("c")
public int count; public int count;
@JsonProperty("s")
public boolean selected; public boolean selected;
public NominalFacetChoice(DecoratedValue decoratedValue) { public NominalFacetChoice(DecoratedValue decoratedValue) {
this.decoratedValue = decoratedValue; this.decoratedValue = decoratedValue;
} }
@Override
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("v"); decoratedValue.write(writer, options);
writer.key("c"); writer.value(count);
writer.key("s"); writer.value(selected);
writer.endObject();
}
} }

View File

@ -33,12 +33,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.browsing.facets; package com.google.refine.browsing.facets;
import java.util.Properties; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonInclude;
import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonInclude.Include;
import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRecords;
import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.FilteredRows;
import com.google.refine.browsing.RecordFilter; import com.google.refine.browsing.RecordFilter;
@ -56,64 +55,70 @@ import com.google.refine.expr.MetaParser;
import com.google.refine.expr.ParsingException; import com.google.refine.expr.ParsingException;
import com.google.refine.model.Column; import com.google.refine.model.Column;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.util.JSONUtilities;
public class RangeFacet implements Facet { public class RangeFacet implements Facet {
public static final String ERR_NO_NUMERIC_VALUE_PRESENT = "No numeric value present.";
/* /*
* Configuration, from the client side * Configuration, from the client side
*/ */
public static class RangeFacetConfig implements FacetConfig { public static class RangeFacetConfig implements FacetConfig {
@JsonProperty("name")
protected String _name; // name of facet protected String _name; // name of facet
@JsonProperty("expression")
protected String _expression; // expression to compute numeric value(s) per row protected String _expression; // expression to compute numeric value(s) per row
@JsonProperty("columnName")
protected String _columnName; // column to base expression on, if any protected String _columnName; // column to base expression on, if any
@JsonProperty(FROM)
protected double _from; // the numeric selection protected double _from; // the numeric selection
@JsonProperty(TO)
protected double _to; protected double _to;
@JsonProperty("selectNumeric")
protected boolean _selectNumeric; // whether the numeric selection applies, default true protected boolean _selectNumeric; // whether the numeric selection applies, default true
@JsonProperty("selectNonNumeric")
protected boolean _selectNonNumeric; protected boolean _selectNonNumeric;
@JsonProperty("selectBlank")
protected boolean _selectBlank; protected boolean _selectBlank;
@JsonProperty("selectError")
protected boolean _selectError; protected boolean _selectError;
@JsonIgnore
protected boolean _selected; // false if we're certain that all rows will match protected boolean _selected; // false if we're certain that all rows will match
// and there isn't any filtering to do // and there isn't any filtering to do
@Override @JsonCreator
public void write(JSONWriter writer, Properties options) public RangeFacetConfig(
throws JSONException { @JsonProperty("name")
writer.object(); String name,
writer.key("type"); writer.value("range"); @JsonProperty("expression")
writer.key("name"); writer.value(_name); String expression,
writer.key("expression"); writer.value(_expression); @JsonProperty("columnName")
writer.key("columnName"); writer.value(_columnName); String columnName,
writer.key(FROM); writer.value(_from); @JsonProperty(FROM)
writer.key(TO); writer.value(_to); Double from,
writer.key("selectNumeric"); writer.value(_selectNumeric); @JsonProperty(TO)
writer.key("selectNonNumeric"); writer.value(_selectNonNumeric); Double to,
writer.key("selectError"); writer.value(_selectError); @JsonProperty("selectNumeric")
writer.key("selectBlank"); writer.value(_selectBlank); Boolean selectNumeric,
writer.endObject(); @JsonProperty("selectNonNumeric")
Boolean selectNonNumeric,
} @JsonProperty("selectBlank")
Boolean selectBlank,
@Override @JsonProperty("selectError")
public void initializeFromJSON(JSONObject o) { Boolean selectError) {
_name = o.getString("name"); _name = name;
_expression = o.getString("expression"); _expression = expression;
_columnName = o.getString("columnName"); _columnName = columnName;
if (o.has(FROM) || o.has(TO)) { _from = from == null ? 0 : from;
_from = o.has(FROM) ? o.getDouble(FROM) : 0; _to = to == null ? 0 : to;
_to = o.has(TO) ? o.getDouble(TO) : 0; _selectNumeric = selectNumeric == null ? true : selectNumeric;
_selected = true; _selectNonNumeric = selectNonNumeric == null ? true : selectNonNumeric;
} _selectBlank = selectBlank == null ? true : selectBlank;
_selectNumeric = JSONUtilities.getBoolean(o, "selectNumeric", true); _selectError = selectError == null ? true : selectError;
_selectNonNumeric = JSONUtilities.getBoolean(o, "selectNonNumeric", true); _selected = !_selectNumeric || !_selectNonNumeric || !_selectBlank || !_selectError || from != null || to != null;
_selectBlank = JSONUtilities.getBoolean(o, "selectBlank", true);
_selectError = JSONUtilities.getBoolean(o, "selectError", true);
if (!_selectNumeric || !_selectNonNumeric || !_selectBlank || !_selectError) {
_selected = true;
}
} }
@Override @Override
@ -122,8 +127,13 @@ public class RangeFacet implements Facet {
facet.initializeFromConfig(this, project); facet.initializeFromConfig(this, project);
return facet; return facet;
} }
@Override
public String getJsonType() {
return "range";
} }
RangeFacetConfig _config = new RangeFacetConfig(); }
RangeFacetConfig _config = null;
/* /*
* Derived configuration data * Derived configuration data
@ -141,14 +151,22 @@ public class RangeFacet implements Facet {
protected int[] _baseBins; protected int[] _baseBins;
protected int[] _bins; protected int[] _bins;
@JsonProperty("baseNumericCount")
protected int _baseNumericCount; protected int _baseNumericCount;
@JsonProperty("baseNonNumericCount")
protected int _baseNonNumericCount; protected int _baseNonNumericCount;
@JsonProperty("baseBlankCount")
protected int _baseBlankCount; protected int _baseBlankCount;
@JsonProperty("baseErrorCount")
protected int _baseErrorCount; protected int _baseErrorCount;
@JsonProperty("numericCount")
protected int _numericCount; protected int _numericCount;
@JsonProperty("nonNumericCount")
protected int _nonNumericCount; protected int _nonNumericCount;
@JsonProperty("blankCount")
protected int _blankCount; protected int _blankCount;
@JsonProperty("errorCount")
protected int _errorCount; protected int _errorCount;
public RangeFacet() { public RangeFacet() {
@ -159,52 +177,98 @@ public class RangeFacet implements Facet {
protected static final String TO = "to"; protected static final String TO = "to";
protected static final String FROM = "from"; protected static final String FROM = "from";
@Override @JsonProperty("name")
public void write(JSONWriter writer, Properties options) public String getName() {
throws JSONException { return _config._name;
}
writer.object(); @JsonProperty("expression")
writer.key("name"); writer.value(_config._name); public String getExpression() {
writer.key("expression"); writer.value(_config._expression); return _config._expression;
writer.key("columnName"); writer.value(_config._columnName); }
@JsonProperty("columnName")
public String getColumnName() {
return _config._columnName;
}
@JsonProperty("error")
@JsonInclude(Include.NON_NULL)
public String getError() {
if (_errorMessage != null) { if (_errorMessage != null) {
writer.key("error"); writer.value(_errorMessage); return _errorMessage;
} else { } else if (!isFiniteRange()) {
if (!Double.isInfinite(_min) && !Double.isInfinite(_max)) { return ERR_NO_NUMERIC_VALUE_PRESENT;
writer.key(MIN); writer.value(_min);
writer.key(MAX); writer.value(_max);
writer.key("step"); writer.value(_step);
writer.key("bins"); writer.array();
for (int b : _bins) {
writer.value(b);
} }
writer.endArray(); return null;
writer.key("baseBins"); writer.array();
for (int b : _baseBins) {
writer.value(b);
}
writer.endArray();
writer.key(FROM); writer.value(_config._from);
writer.key(TO); writer.value(_config._to);
} else {
writer.key("error"); writer.value("No numeric value present.");
} }
writer.key("baseNumericCount"); writer.value(_baseNumericCount); @JsonIgnore
writer.key("baseNonNumericCount"); writer.value(_baseNonNumericCount); public boolean isFiniteRange() {
writer.key("baseBlankCount"); writer.value(_baseBlankCount); return !Double.isInfinite(_min) && !Double.isInfinite(_max);
writer.key("baseErrorCount"); writer.value(_baseErrorCount);
writer.key("numericCount"); writer.value(_numericCount);
writer.key("nonNumericCount"); writer.value(_nonNumericCount);
writer.key("blankCount"); writer.value(_blankCount);
writer.key("errorCount"); writer.value(_errorCount);
} }
writer.endObject();
@JsonProperty(MIN)
@JsonInclude(Include.NON_NULL)
public Double getMin() {
if (getError() == null) {
return _min;
}
return null;
}
@JsonProperty(MAX)
@JsonInclude(Include.NON_NULL)
public Double getMax() {
if (getError() == null) {
return _max;
}
return null;
}
@JsonProperty("step")
@JsonInclude(Include.NON_NULL)
public Double getStep() {
if (getError() == null) {
return _step;
}
return null;
}
@JsonProperty("bins")
@JsonInclude(Include.NON_NULL)
public int[] getBins() {
if (getError() == null) {
return _bins;
}
return null;
}
@JsonProperty("baseBins")
@JsonInclude(Include.NON_NULL)
public int[] getBaseBins() {
if (getError() == null) {
return _baseBins;
}
return null;
}
@JsonProperty(FROM)
@JsonInclude(Include.NON_NULL)
public Double getFrom() {
if (getError() == null) {
return _config._from;
}
return null;
}
@JsonProperty(TO)
@JsonInclude(Include.NON_NULL)
public Double getTo() {
if (getError() == null) {
return _config._to;
}
return null;
} }
public void initializeFromConfig(RangeFacetConfig config, Project project) { public void initializeFromConfig(RangeFacetConfig config, Project project) {

View File

@ -40,17 +40,17 @@ import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage; import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Properties;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRecords;
import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.FilteredRows;
import com.google.refine.browsing.RecordFilter; import com.google.refine.browsing.RecordFilter;
@ -80,61 +80,64 @@ public class ScatterplotFacet implements Facet {
* Configuration, from the client side * Configuration, from the client side
*/ */
public static class ScatterplotFacetConfig implements FacetConfig { public static class ScatterplotFacetConfig implements FacetConfig {
@JsonProperty("name")
protected String name; // name of facet protected String name; // name of facet
@JsonProperty(X_EXPRESSION)
protected String expression_x; // expression to compute the x numeric value(s) per row protected String expression_x; // expression to compute the x numeric value(s) per row
@JsonProperty(Y_EXPRESSION)
protected String expression_y; // expression to compute the y numeric value(s) per row protected String expression_y; // expression to compute the y numeric value(s) per row
@JsonProperty(X_COLUMN_NAME)
protected String columnName_x; // column to base the x expression on, if any protected String columnName_x; // column to base the x expression on, if any
@JsonProperty(Y_COLUMN_NAME)
protected String columnName_y; // column to base the y expression on, if any protected String columnName_y; // column to base the y expression on, if any
@JsonProperty(SIZE)
protected int size; protected int size;
@JsonIgnore
protected int dim_x; protected int dim_x;
@JsonIgnore
protected int dim_y; protected int dim_y;
@JsonIgnore
protected String rotation_str; protected String rotation_str;
@JsonIgnore
protected int rotation; protected int rotation;
@JsonIgnore
protected double l; protected double l;
@JsonProperty(DOT)
protected double dot; protected double dot;
protected String color_str; @JsonIgnore
protected Color color; protected String color_str = "000000";
@JsonIgnore
protected Color getColor() {
return new Color(Integer.parseInt(color_str,16));
}
@JsonProperty(FROM_X)
protected double from_x; // the numeric selection for the x axis, from 0 to 1 protected double from_x; // the numeric selection for the x axis, from 0 to 1
@JsonProperty(TO_X)
protected double to_x; protected double to_x;
@JsonProperty(FROM_Y)
protected double from_y; // the numeric selection for the y axis, from 0 to 1 protected double from_y; // the numeric selection for the y axis, from 0 to 1
@JsonProperty(TO_Y)
protected double to_y; protected double to_y;
protected boolean selected; // false if we're certain that all rows will match // false if we're certain that all rows will match
// and there isn't any filtering to do // and there isn't any filtering to do
protected boolean isSelected() {
@Override return from_x > 0 || to_x < 1 || from_y > 0 || to_y < 1;
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("type"); writer.value("scatterplot");
writer.key(NAME); writer.value(name);
writer.key(X_COLUMN_NAME); writer.value(columnName_x);
writer.key(X_EXPRESSION); writer.value(expression_x);
writer.key(Y_COLUMN_NAME); writer.value(columnName_y);
writer.key(Y_EXPRESSION); writer.value(expression_y);
writer.key(SIZE); writer.value(size);
writer.key(DOT); writer.value(dot);
if(!rotation_str.isEmpty()) {
writer.key(ROTATION); writer.value(rotation_str);
} }
writer.key(DIM_X); writer.value(dim_x == LIN ? "lin" : "log");
writer.key(DIM_Y); writer.value(dim_y == LIN ? "lin" : "log"); @JsonProperty(DIM_X)
if(!"000000".equals(color_str)) { public String getDimX() {
writer.key(COLOR); writer.value(color_str); return dim_x == LIN ? "lin" : "log";
} }
writer.key(FROM_X); writer.value(from_x);
writer.key(TO_X); writer.value(to_x);
writer.key(FROM_Y); writer.value(from_y);
writer.key(TO_Y); writer.value(to_y);
writer.endObject();
@JsonProperty(DIM_Y)
public String getDimY() {
return dim_y == LIN ? "lin" : "log";
} }
@Override @Override
@ -144,45 +147,6 @@ public class ScatterplotFacet implements Facet {
return facet; return facet;
} }
@Override
public void initializeFromJSON(JSONObject o) {
name = o.getString(NAME);
l = size = (o.has(SIZE)) ? o.getInt(SIZE) : 100;
dot = (o.has(DOT)) ? o.getInt(DOT) : 0.5d;
dim_x = (o.has(DIM_X)) ? getAxisDim(o.getString(DIM_X)) : LIN;
if (o.has(FROM_X) && o.has(TO_X)) {
from_x = o.getDouble(FROM_X);
to_x = o.getDouble(TO_X);
selected = true;
} else {
from_x = 0;
to_x = 1;
}
dim_y = (o.has(DIM_Y)) ? getAxisDim(o.getString(DIM_Y)) : LIN;
if (o.has(FROM_Y) && o.has(TO_Y)) {
from_y = o.getDouble(FROM_Y);
to_y = o.getDouble(TO_Y);
selected = true;
} else {
from_y = 0;
to_y = 1;
}
rotation_str = (o.has(ROTATION) ? o.getString(ROTATION) : "");
rotation = getRotation(rotation_str);
color_str = (o.has(COLOR)) ? o.getString(COLOR) : "000000";
color = new Color(Integer.parseInt(color_str,16));
columnName_x = o.getString(X_COLUMN_NAME);
expression_x = o.getString(X_EXPRESSION);
columnName_y = o.getString(Y_COLUMN_NAME);
expression_y = o.getString(Y_EXPRESSION);
}
public static int getRotation(String rotation) { public static int getRotation(String rotation) {
rotation = rotation.toLowerCase(); rotation = rotation.toLowerCase();
if ("cw".equals(rotation) || "right".equals(rotation)) { if ("cw".equals(rotation) || "right".equals(rotation)) {
@ -193,6 +157,11 @@ public class ScatterplotFacet implements Facet {
return NO_ROTATION; return NO_ROTATION;
} }
} }
@Override
public String getJsonType() {
return "scatterplot";
}
} }
ScatterplotFacetConfig config; ScatterplotFacetConfig config;
@ -255,46 +224,116 @@ public class ScatterplotFacet implements Facet {
} }
} }
@Override @JsonProperty(NAME)
public void write(JSONWriter writer, Properties options) throws JSONException { public String getName() {
return config.name;
}
writer.object(); @JsonProperty(X_COLUMN_NAME)
public String getXColumnName() {
return config.columnName_x;
}
writer.key(NAME); writer.value(config.name); @JsonProperty(X_EXPRESSION)
writer.key(X_COLUMN_NAME); writer.value(config.columnName_x); public String getXExpression() {
writer.key(X_EXPRESSION); writer.value(config.expression_x); return config.expression_x;
writer.key(Y_COLUMN_NAME); writer.value(config.columnName_y); }
writer.key(Y_EXPRESSION); writer.value(config.expression_y);
writer.key(SIZE); writer.value(config.size);
writer.key(DOT); writer.value(config.dot);
writer.key(ROTATION); writer.value(config.rotation);
writer.key(DIM_X); writer.value(config.dim_x);
writer.key(DIM_Y); writer.value(config.dim_y);
writer.key(COLOR); writer.value(config.color_str);
@JsonProperty(Y_COLUMN_NAME)
public String getYColumnName() {
return config.columnName_y;
}
@JsonProperty(Y_EXPRESSION)
public String getYExpression() {
return config.expression_y;
}
@JsonProperty(SIZE)
public int getSize() {
return config.size;
}
@JsonProperty(DIM_X)
public int getDimX() {
return config.dim_x;
}
@JsonProperty(DIM_Y)
public int getDimY() {
return config.dim_y;
}
@JsonProperty(DOT)
public double getDot() {
return config.dot;
}
@JsonProperty(ROTATION)
public double getRotation() {
return config.rotation;
}
@JsonProperty(COLOR)
public String getColorString() {
return config.color_str;
}
@JsonProperty(IMAGE)
@JsonInclude(Include.NON_NULL)
public String getImage() {
if(IMAGE_URI) { if(IMAGE_URI) {
writer.key(IMAGE); writer.value(image); return image;
}
return null;
} }
if (errorMessage_x != null) { @JsonProperty(ERROR_X)
writer.key(ERROR_X); writer.value(errorMessage_x); @JsonInclude(Include.NON_NULL)
} else { public String getErrorX() {
if (!Double.isInfinite(min_x) && !Double.isInfinite(max_x)) { return errorMessage_x;
writer.key(FROM_X); writer.value(config.from_x);
writer.key(TO_X); writer.value(config.to_x);
}
} }
if (errorMessage_y != null) { @JsonProperty(FROM_X)
writer.key(ERROR_Y); writer.value(errorMessage_y); @JsonInclude(Include.NON_NULL)
} else { public Double getFromX() {
if (!Double.isInfinite(min_y) && !Double.isInfinite(max_y)) { if (errorMessage_x == null && !Double.isInfinite(min_x) && !Double.isInfinite(max_x)) {
writer.key(FROM_Y); writer.value(config.from_y); return config.from_x;
writer.key(TO_Y); writer.value(config.to_y);
} }
return null;
} }
writer.endObject(); @JsonProperty(TO_X)
@JsonInclude(Include.NON_NULL)
public Double getToX() {
if (errorMessage_x == null && !Double.isInfinite(min_x) && !Double.isInfinite(max_x)) {
return config.to_x;
}
return null;
}
@JsonProperty(ERROR_Y)
@JsonInclude(Include.NON_NULL)
public String getErrorY() {
return errorMessage_y;
}
@JsonProperty(FROM_Y)
@JsonInclude(Include.NON_NULL)
public Double getFromY() {
if (errorMessage_y == null && !Double.isInfinite(min_y) && !Double.isInfinite(max_y)) {
return config.from_y;
}
return null;
}
@JsonProperty(TO_Y)
@JsonInclude(Include.NON_NULL)
public Double getToY() {
if (errorMessage_y == null && !Double.isInfinite(min_y) && !Double.isInfinite(max_y)) {
return config.to_y;
}
return null;
} }
public void initializeFromConfig(ScatterplotFacetConfig configuration, Project project) { public void initializeFromConfig(ScatterplotFacetConfig configuration, Project project) {
@ -348,7 +387,7 @@ public class ScatterplotFacet implements Facet {
@Override @Override
public RowFilter getRowFilter(Project project) { public RowFilter getRowFilter(Project project) {
if (config.selected && if (config.isSelected() &&
eval_x != null && errorMessage_x == null && eval_x != null && errorMessage_x == null &&
eval_y != null && errorMessage_y == null) eval_y != null && errorMessage_y == null)
{ {
@ -393,7 +432,7 @@ public class ScatterplotFacet implements Facet {
if (index_x.isNumeric() && index_y.isNumeric()) { if (index_x.isNumeric() && index_y.isNumeric()) {
ScatterplotDrawingRowVisitor drawer = new ScatterplotDrawingRowVisitor( ScatterplotDrawingRowVisitor drawer = new ScatterplotDrawingRowVisitor(
columnIndex_x, columnIndex_y, min_x, max_x, min_y, max_y, columnIndex_x, columnIndex_y, min_x, max_x, min_y, max_y,
config.size, config.dim_x, config.dim_y, config.rotation, config.dot, config.color config.size, config.dim_x, config.dim_y, config.rotation, config.dot, config.getColor()
); );
filteredRows.accept(project, drawer); filteredRows.accept(project, drawer);
@ -424,7 +463,7 @@ public class ScatterplotFacet implements Facet {
if (index_x.isNumeric() && index_y.isNumeric()) { if (index_x.isNumeric() && index_y.isNumeric()) {
ScatterplotDrawingRowVisitor drawer = new ScatterplotDrawingRowVisitor( ScatterplotDrawingRowVisitor drawer = new ScatterplotDrawingRowVisitor(
columnIndex_x, columnIndex_y, min_x, max_x, min_y, max_y, columnIndex_x, columnIndex_y, min_x, max_x, min_y, max_y,
config.size, config.dim_x, config.dim_y, config.rotation, config.dot, config.color config.size, config.dim_x, config.dim_y, config.rotation, config.dot, config.getColor()
); );
filteredRecords.accept(project, drawer); filteredRecords.accept(project, drawer);

View File

@ -33,13 +33,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.browsing.facets; package com.google.refine.browsing.facets;
import java.util.Properties;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonProperty;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRecords;
import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.FilteredRows;
import com.google.refine.browsing.RecordFilter; import com.google.refine.browsing.RecordFilter;
@ -58,27 +54,19 @@ public class TextSearchFacet implements Facet {
* Configuration * Configuration
*/ */
public static class TextSearchFacetConfig implements FacetConfig { public static class TextSearchFacetConfig implements FacetConfig {
@JsonProperty("name")
protected String _name; protected String _name;
@JsonProperty("columnName")
protected String _columnName; protected String _columnName;
@JsonProperty("query")
protected String _query = null; protected String _query = null;
@JsonProperty("mode")
protected String _mode; protected String _mode;
@JsonProperty("caseSensitive")
protected boolean _caseSensitive; protected boolean _caseSensitive;
@JsonProperty("invert")
protected boolean _invert; protected boolean _invert;
@Override
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("name"); writer.value(_name);
writer.key("columnName"); writer.value(_columnName);
writer.key("query"); writer.value(_query);
writer.key("mode"); writer.value(_mode);
writer.key("caseSensitive"); writer.value(_caseSensitive);
writer.key("invert"); writer.value(_invert);
writer.key("type"); writer.value("text");
writer.endObject();
}
@Override @Override
public TextSearchFacet apply(Project project) { public TextSearchFacet apply(Project project) {
TextSearchFacet facet = new TextSearchFacet(); TextSearchFacet facet = new TextSearchFacet();
@ -87,15 +75,8 @@ public class TextSearchFacet implements Facet {
} }
@Override @Override
public void initializeFromJSON(JSONObject o) { public String getJsonType() {
_name = o.getString("name"); return "text";
_columnName = o.getString("columnName");
_mode = o.getString("mode");
_caseSensitive = o.getBoolean("caseSensitive");
if (!o.isNull("query")) {
_query = o.getString("query");
}
_invert = o.has("invert") && o.getBoolean("invert");
} }
} }
TextSearchFacetConfig _config = new TextSearchFacetConfig(); TextSearchFacetConfig _config = new TextSearchFacetConfig();
@ -110,18 +91,34 @@ public class TextSearchFacet implements Facet {
public TextSearchFacet() { public TextSearchFacet() {
} }
@Override @JsonProperty("name")
public void write(JSONWriter writer, Properties options) public String getName() {
throws JSONException { return _config._name;
}
writer.object(); @JsonProperty("columnName")
writer.key("name"); writer.value(_config._name); public String getColumnName() {
writer.key("columnName"); writer.value(_config._columnName); return _config._columnName;
writer.key("query"); writer.value(_config._query); }
writer.key("mode"); writer.value(_config._mode);
writer.key("caseSensitive"); writer.value(_config._caseSensitive); @JsonProperty("query")
writer.key("invert"); writer.value(_config._invert); public String getQuery() {
writer.endObject(); return _config._query;
}
@JsonProperty("mode")
public String getMode() {
return _config._mode;
}
@JsonProperty("caseSensitive")
public boolean isCaseSensitive() {
return _config._caseSensitive;
}
@JsonProperty("invert")
public boolean isInverted() {
return _config._invert;
} }
public void initializeFromConfig(TextSearchFacetConfig config, Project project) { public void initializeFromConfig(TextSearchFacetConfig config, Project project) {
@ -139,7 +136,7 @@ public class TextSearchFacet implements Facet {
_config._caseSensitive ? 0 : Pattern.CASE_INSENSITIVE); _config._caseSensitive ? 0 : Pattern.CASE_INSENSITIVE);
} catch (java.util.regex.PatternSyntaxException e) { } catch (java.util.regex.PatternSyntaxException e) {
PatternSyntaxExceptionParser err = new PatternSyntaxExceptionParser(e); PatternSyntaxExceptionParser err = new PatternSyntaxExceptionParser(e);
throw new JSONException(err.getUserMessage()); throw new IllegalArgumentException(err.getUserMessage());
} }
} else if (!_config._caseSensitive) { } else if (!_config._caseSensitive) {
_query = _query.toLowerCase(); _query = _query.toLowerCase();

View File

@ -33,12 +33,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.browsing.facets; package com.google.refine.browsing.facets;
import java.util.Properties; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonInclude.Include;
import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty;
import org.json.JSONWriter;
import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRecords;
import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.FilteredRows;
import com.google.refine.browsing.RecordFilter; import com.google.refine.browsing.RecordFilter;
@ -56,66 +54,39 @@ import com.google.refine.expr.MetaParser;
import com.google.refine.expr.ParsingException; import com.google.refine.expr.ParsingException;
import com.google.refine.model.Column; import com.google.refine.model.Column;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.util.JSONUtilities;
public class TimeRangeFacet implements Facet { public class TimeRangeFacet implements Facet {
/* /*
* Configuration, from the client side * Configuration, from the client side
*/ */
public static class TimeRangeFacetConfig implements FacetConfig { public static class TimeRangeFacetConfig implements FacetConfig {
@JsonProperty("name")
protected String _name; // name of facet protected String _name; // name of facet
@JsonProperty("expression")
protected String _expression; // expression to compute numeric value(s) per row protected String _expression; // expression to compute numeric value(s) per row
@JsonProperty("columnName")
protected String _columnName; // column to base expression on, if any protected String _columnName; // column to base expression on, if any
protected double _from; // the numeric selection @JsonProperty(FROM)
protected double _to; protected double _from = 0; // the numeric selection
@JsonProperty(TO)
protected double _to = 0;
@JsonProperty("selectTime")
protected boolean _selectTime; // whether the time selection applies, default true protected boolean _selectTime; // whether the time selection applies, default true
@JsonProperty("selectNonTime")
protected boolean _selectNonTime; protected boolean _selectNonTime;
@JsonProperty("selectBlank")
protected boolean _selectBlank; protected boolean _selectBlank;
@JsonProperty("selectError")
protected boolean _selectError; protected boolean _selectError;
protected boolean _selected; // false if we're certain that all rows will match // false if we're certain that all rows will match
// and there isn't any filtering to do // and there isn't any filtering to do
@JsonIgnore
@Override protected boolean isSelected() {
public void write(JSONWriter writer, Properties options) return _from != 0 || _to != 0 || !_selectTime || !_selectNonTime || !_selectBlank || !_selectError;
throws JSONException { };
writer.object();
writer.key("type"); writer.value("timerange");
writer.key("name"); writer.value(_name);
writer.key("expression"); writer.value(_expression);
writer.key("columnName"); writer.value(_columnName);
writer.key("selectTime"); writer.value(_selectTime);
writer.key("selectNonTime"); writer.value(_selectNonTime);
writer.key("selectBlank"); writer.value(_selectBlank);
writer.key("selectError"); writer.value(_selectError);
writer.key(FROM); writer.value((long)_from);
writer.key(TO); writer.value((long)_to);
writer.endObject();
}
@Override
public void initializeFromJSON(JSONObject o) throws JSONException {
_name = o.getString("name");
_expression = o.getString("expression");
_columnName = o.getString("columnName");
if (o.has(FROM) || o.has(TO)) {
_from = o.has(FROM) ? o.getDouble(FROM) : 0;
_to = o.has(TO) ? o.getDouble(TO) : 0;
_selected = true;
}
_selectTime = JSONUtilities.getBoolean(o, "selectTime", true);
_selectNonTime = JSONUtilities.getBoolean(o, "selectNonTime", true);
_selectBlank = JSONUtilities.getBoolean(o, "selectBlank", true);
_selectError = JSONUtilities.getBoolean(o, "selectError", true);
if (!_selectTime || !_selectNonTime || !_selectBlank || !_selectError) {
_selected = true;
}
}
@Override @Override
public TimeRangeFacet apply(Project project) { public TimeRangeFacet apply(Project project) {
@ -123,6 +94,11 @@ public class TimeRangeFacet implements Facet {
facet.initializeFromConfig(this, project); facet.initializeFromConfig(this, project);
return facet; return facet;
} }
@Override
public String getJsonType() {
return "timerange";
}
} }
protected TimeRangeFacetConfig _config; protected TimeRangeFacetConfig _config;
@ -142,14 +118,22 @@ public class TimeRangeFacet implements Facet {
/* /*
* Computed data * Computed data
*/ */
@JsonProperty("baseTimeCount")
protected int _baseTimeCount; protected int _baseTimeCount;
@JsonProperty("baseNonTimeCount")
protected int _baseNonTimeCount; protected int _baseNonTimeCount;
@JsonProperty("baseBlankCount")
protected int _baseBlankCount; protected int _baseBlankCount;
@JsonProperty("baseErrorCount")
protected int _baseErrorCount; protected int _baseErrorCount;
@JsonProperty("timeCount")
protected int _timeCount; protected int _timeCount;
@JsonProperty("nonTimeCount")
protected int _nonTimeCount; protected int _nonTimeCount;
@JsonProperty("blankCount")
protected int _blankCount; protected int _blankCount;
@JsonProperty("errorCount")
protected int _errorCount; protected int _errorCount;
protected static final String MIN = "min"; protected static final String MIN = "min";
@ -157,49 +141,85 @@ public class TimeRangeFacet implements Facet {
protected static final String TO = "to"; protected static final String TO = "to";
protected static final String FROM = "from"; protected static final String FROM = "from";
@Override @JsonProperty("name")
public void write(JSONWriter writer, Properties options) throws JSONException { public String getName() {
return _config._name;
writer.object();
writer.key("name"); writer.value(_config._name);
writer.key("expression"); writer.value(_config._expression);
writer.key("columnName"); writer.value(_config._columnName);
if (_errorMessage != null) {
writer.key("error"); writer.value(_errorMessage);
} else {
if (!Double.isInfinite(_min) && !Double.isInfinite(_max)) {
writer.key(MIN); writer.value(_min);
writer.key(MAX); writer.value(_max);
writer.key("step"); writer.value(_step);
writer.key("bins"); writer.array();
for (int b : _bins) {
writer.value(b);
}
writer.endArray();
writer.key("baseBins"); writer.array();
for (int b : _baseBins) {
writer.value(b);
}
writer.endArray();
writer.key(FROM); writer.value(_config._from);
writer.key(TO); writer.value(_config._to);
} }
writer.key("baseTimeCount"); writer.value(_baseTimeCount); @JsonProperty("expression")
writer.key("baseNonTimeCount"); writer.value(_baseNonTimeCount); public String getExpression() {
writer.key("baseBlankCount"); writer.value(_baseBlankCount); return _config._expression;
writer.key("baseErrorCount"); writer.value(_baseErrorCount);
writer.key("timeCount"); writer.value(_timeCount);
writer.key("nonTimeCount"); writer.value(_nonTimeCount);
writer.key("blankCount"); writer.value(_blankCount);
writer.key("errorCount"); writer.value(_errorCount);
} }
writer.endObject();
@JsonProperty("columnName")
public String getColumnName() {
return _config._columnName;
}
@JsonProperty("error")
@JsonInclude(Include.NON_NULL)
public String getError() {
return _errorMessage;
}
@JsonProperty(MIN)
@JsonInclude(Include.NON_NULL)
public Double getMin() {
if(getError() == null) {
return _min;
}
return null;
}
@JsonProperty(MAX)
@JsonInclude(Include.NON_NULL)
public Double getMax() {
if(getError() == null) {
return _max;
}
return null;
}
@JsonProperty("step")
@JsonInclude(Include.NON_NULL)
public Double getStep() {
return _step;
}
@JsonProperty("bins")
@JsonInclude(Include.NON_NULL)
public int[] getBins() {
if (getError() == null) {
return _bins;
}
return null;
}
@JsonProperty("baseBins")
@JsonInclude(Include.NON_NULL)
public int[] getBaseBins() {
if (getError() == null) {
return _baseBins;
}
return null;
}
@JsonProperty(FROM)
@JsonInclude(Include.NON_NULL)
public Double getFrom() {
if (getError() == null) {
return _config._from;
}
return null;
}
@JsonProperty(TO)
@JsonInclude(Include.NON_NULL)
public Double getTo() {
if (getError() == null) {
return _config._to;
}
return null;
} }
public void initializeFromConfig(TimeRangeFacetConfig config, Project project) { public void initializeFromConfig(TimeRangeFacetConfig config, Project project) {
@ -224,7 +244,7 @@ public class TimeRangeFacet implements Facet {
@Override @Override
public RowFilter getRowFilter(Project project) { public RowFilter getRowFilter(Project project) {
if (_eval != null && _errorMessage == null && _config._selected) { if (_eval != null && _errorMessage == null && _config.isSelected()) {
return new ExpressionTimeComparisonRowFilter( return new ExpressionTimeComparisonRowFilter(
getRowEvaluable(project), _config._selectTime, _config._selectNonTime, _config._selectBlank, _config._selectError) { getRowEvaluable(project), _config._selectTime, _config._selectNonTime, _config._selectBlank, _config._selectError) {
@ -294,7 +314,7 @@ public class TimeRangeFacet implements Facet {
_baseBlankCount = index.getBlankRowCount(); _baseBlankCount = index.getBlankRowCount();
_baseErrorCount = index.getErrorRowCount(); _baseErrorCount = index.getErrorRowCount();
if (_config._selected) { if (_config.isSelected()) {
_config._from = Math.max(_config._from, _min); _config._from = Math.max(_config._from, _min);
_config._to = Math.min(_config._to, _max); _config._to = Math.min(_config._to, _max);
} else { } else {

View File

@ -38,12 +38,11 @@ import java.time.OffsetDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.Properties; import java.util.Properties;
import org.json.JSONArray; import com.fasterxml.jackson.databind.node.ArrayNode;
import org.json.JSONException;
import com.google.refine.browsing.RowFilter; import com.google.refine.browsing.RowFilter;
import com.google.refine.expr.Evaluable; import com.google.refine.expr.Evaluable;
import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.ExpressionUtils;
import com.google.refine.expr.util.JsonValueConverter;
import com.google.refine.model.Cell; import com.google.refine.model.Cell;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.Row; import com.google.refine.model.Row;
@ -122,18 +121,14 @@ public class ExpressionEqualRowFilter implements RowFilter {
} }
} }
return false; return false;
} else if (value instanceof JSONArray) { } else if (value instanceof ArrayNode) {
JSONArray a = (JSONArray) value; ArrayNode a = (ArrayNode) value;
int l = a.length(); int l = a.size();
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
try { if (testValue(JsonValueConverter.convert(a.get(i)))) {
if (testValue(a.get(i))) {
return true; return true;
} }
} catch (JSONException e) {
// ignore
}
} }
return false; return false;
} // else, fall through } // else, fall through
@ -165,18 +160,14 @@ public class ExpressionEqualRowFilter implements RowFilter {
} }
} }
return true; return true;
} else if (value instanceof JSONArray) { } else if (value instanceof ArrayNode) {
JSONArray a = (JSONArray) value; ArrayNode a = (ArrayNode) value;
int l = a.length(); int l = a.size();
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
try { if (testValue(JsonValueConverter.convert(a.get(i)))) {
if (testValue(a.get(i))) {
return false; return false;
} }
} catch (JSONException e) {
// ignore
}
} }
return true; return true;
} // else, fall through } // else, fall through

View File

@ -36,12 +36,11 @@ package com.google.refine.browsing.filters;
import java.util.Collection; import java.util.Collection;
import java.util.Properties; import java.util.Properties;
import org.json.JSONArray; import com.fasterxml.jackson.databind.node.ArrayNode;
import org.json.JSONException;
import com.google.refine.browsing.RowFilter; import com.google.refine.browsing.RowFilter;
import com.google.refine.browsing.util.RowEvaluable; import com.google.refine.browsing.util.RowEvaluable;
import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.ExpressionUtils;
import com.google.refine.expr.util.JsonValueConverter;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.Row; import com.google.refine.model.Row;
@ -93,18 +92,14 @@ abstract public class ExpressionNumberComparisonRowFilter implements RowFilter {
} }
} }
return false; return false;
} else if (value instanceof JSONArray) { } else if (value instanceof ArrayNode) {
JSONArray a = (JSONArray) value; ArrayNode a = (ArrayNode) value;
int l = a.length(); int l = a.size();
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
try { if (checkValue(JsonValueConverter.convert(a.get(i)))) {
if (checkValue(a.get(i))) {
return true; return true;
} }
} catch (JSONException e) {
// ignore
}
} }
return false; return false;
} // else, fall through } // else, fall through

View File

@ -36,12 +36,11 @@ package com.google.refine.browsing.filters;
import java.util.Collection; import java.util.Collection;
import java.util.Properties; import java.util.Properties;
import org.json.JSONArray; import com.fasterxml.jackson.databind.node.ArrayNode;
import org.json.JSONException;
import com.google.refine.browsing.RowFilter; import com.google.refine.browsing.RowFilter;
import com.google.refine.expr.Evaluable; import com.google.refine.expr.Evaluable;
import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.ExpressionUtils;
import com.google.refine.expr.util.JsonValueConverter;
import com.google.refine.model.Cell; import com.google.refine.model.Cell;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.Row; import com.google.refine.model.Row;
@ -86,18 +85,14 @@ abstract public class ExpressionStringComparisonRowFilter implements RowFilter {
} }
} }
return invert; return invert;
} else if (value instanceof JSONArray) { } else if (value instanceof ArrayNode) {
JSONArray a = (JSONArray) value; ArrayNode a = (ArrayNode) value;
int l = a.length(); int l = a.size();
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
try { if (checkValue(JsonValueConverter.convert(a.get(i)).toString())) {
if (checkValue(a.get(i).toString())) {
return !invert; return !invert;
} }
} catch (JSONException e) {
// ignore
}
} }
return invert; return invert;
} else { } else {

View File

@ -0,0 +1,27 @@
package com.google.refine.clustering;
import java.io.Serializable;
import java.util.Comparator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class ClusteredEntry {
@JsonProperty("v")
protected final Serializable value;
@JsonProperty("c")
protected final int count;
public ClusteredEntry(
Serializable value,
int count) {
this.value = value;
this.count = count;
}
public static Comparator<ClusteredEntry> comparator = new Comparator<ClusteredEntry>() {
@Override
public int compare(ClusteredEntry o1, ClusteredEntry o2) {
return o2.count - o1.count;
}
};
}

View File

@ -33,12 +33,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.clustering; package com.google.refine.clustering;
import com.google.refine.Jsonizable;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.model.Column; import com.google.refine.model.Column;
import com.google.refine.model.Project; import com.google.refine.model.Project;
public abstract class Clusterer implements Jsonizable { public abstract class Clusterer {
protected Project _project; protected Project _project;
protected int _colindex; protected int _colindex;

View File

@ -1,8 +1,11 @@
package com.google.refine.clustering; package com.google.refine.clustering;
import org.json.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.google.refine.Jsonizable; import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.google.refine.clustering.binning.BinningClusterer.BinningClustererConfig;
import com.google.refine.clustering.knn.kNNClusterer.kNNClustererConfig;
import com.google.refine.model.Project; import com.google.refine.model.Project;
/** /**
@ -10,26 +13,37 @@ import com.google.refine.model.Project;
* @author Antonin Delpeuch * @author Antonin Delpeuch
* *
*/ */
public abstract class ClustererConfig implements Jsonizable { @JsonTypeInfo(
use=JsonTypeInfo.Id.NAME,
include=JsonTypeInfo.As.PROPERTY,
property="type")
@JsonSubTypes({
@Type(value = kNNClustererConfig.class, name = "knn"),
@Type(value = BinningClustererConfig.class, name = "binning") })
public abstract class ClustererConfig {
protected String columnName; protected String columnName;
/** @JsonProperty("column")
* Reads the configuration from a JSON payload (TODO: delete)
* @param o
*/
public void initializeFromJSON(JSONObject o) {
columnName = o.getString("column");
}
public String getColumnName() { public String getColumnName() {
return columnName; return columnName;
} }
@JsonProperty("column")
public void setColumnName(String name) {
columnName = name;
}
/** /**
* Instantiate the configuration on a particular project. * Instantiate the configuration on a particular project.
* @param project * @param project
* @return * @return
*/ */
public abstract Clusterer apply(Project project); public abstract Clusterer apply(Project project);
/**
* Type string used in Json serialization
*/
@JsonProperty("type")
public abstract String getType();
} }

View File

@ -41,19 +41,21 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Properties;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.stream.Collectors;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.refine.Jsonizable; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.FilteredRows;
import com.google.refine.browsing.RowVisitor; import com.google.refine.browsing.RowVisitor;
import com.google.refine.clustering.ClusteredEntry;
import com.google.refine.clustering.Clusterer; import com.google.refine.clustering.Clusterer;
import com.google.refine.clustering.ClustererConfig; import com.google.refine.clustering.ClustererConfig;
import com.google.refine.model.Cell; import com.google.refine.model.Cell;
@ -64,42 +66,38 @@ public class BinningClusterer extends Clusterer {
public static class BinningClustererConfig extends ClustererConfig { public static class BinningClustererConfig extends ClustererConfig {
@JsonIgnore
private String _keyerName; private String _keyerName;
@JsonIgnore
private Keyer _keyer; private Keyer _keyer;
private BinningParameters _parameters; @JsonIgnore
private BinningParameters _parameters = null;
@Override
public void initializeFromJSON(JSONObject o) {
super.initializeFromJSON(o);
_keyerName = o.getString("function");
_keyer = _keyers.get(_keyerName.toLowerCase());
if(o.has("params")) {
_parameters = BinningParameters.reconstruct(o.getJSONObject("params"));
} else {
_parameters = null;
}
}
@JsonIgnore
public Keyer getKeyer() { public Keyer getKeyer() {
return _keyer; return _keyer;
} }
@JsonProperty("function")
public void setKeyer(String keyerName) {
_keyerName = keyerName;
_keyer = _keyers.get(_keyerName.toLowerCase());
}
@JsonProperty("function")
public String getKeyerName() {
return _keyerName;
}
@JsonProperty("params")
@JsonInclude(Include.NON_NULL)
public BinningParameters getParameters() { public BinningParameters getParameters() {
return _parameters; return _parameters;
} }
@Override @JsonProperty("params")
public void write(JSONWriter writer, Properties options) public void setParameters(BinningParameters params) {
throws JSONException { _parameters = params;
writer.object();
writer.key("function"); writer.value(_keyerName);
writer.key("type"); writer.value("binning");
writer.key("column"); writer.value(getColumnName());
if(_parameters != null) {
writer.key("params");
_parameters.write(writer, options);
}
writer.endObject();
} }
@Override @Override
@ -109,27 +107,17 @@ public class BinningClusterer extends Clusterer {
return clusterer; return clusterer;
} }
}
public static class BinningParameters implements Jsonizable {
public int ngramSize;
@Override @Override
public void write(JSONWriter writer, Properties options) public String getType() {
throws JSONException { return "binning";
writer.object();
if(ngramSize > 0) {
writer.key("ngram-size");
writer.value(ngramSize);
}
writer.endObject();
} }
public static BinningParameters reconstruct(JSONObject o) {
BinningParameters parameters = new BinningParameters();
parameters.ngramSize = o.has("ngram-size") ? o.getInt("ngram-size") : 0;
return parameters;
} }
public static class BinningParameters {
@JsonProperty("ngram-size")
@JsonInclude(Include.NON_DEFAULT)
public int ngramSize = 0;
} }
protected Keyer _keyer; protected Keyer _keyer;
@ -255,25 +243,21 @@ public class BinningClusterer extends Clusterer {
Collections.sort(_clusters, new SizeComparator()); Collections.sort(_clusters, new SizeComparator());
} }
@Override protected static Map<String,Object> entryToMap(Entry<String,Integer> entry) {
public void write(JSONWriter writer, Properties options) throws JSONException { Map<String,Object> map = new HashMap<>();
EntriesComparator c = new EntriesComparator(); map.put("v", entry.getKey());
map.put("c", entry.getValue());
return map;
}
writer.array(); @JsonValue
for (Map<String,Integer> m : _clusters) { public List<List<ClusteredEntry>> getJsonRepresentation() {
if (m.size() > 1) { EntriesComparator c = new EntriesComparator();
writer.array(); return _clusters.stream()
List<Entry<String,Integer>> entries = new ArrayList<Entry<String,Integer>>(m.entrySet()); .map(m -> m.entrySet().stream()
Collections.sort(entries,c); .sorted(c)
for (Entry<String,Integer> e : entries) { .map(e -> new ClusteredEntry(e.getKey(), e.getValue()))
writer.object(); .collect(Collectors.toList()))
writer.key("v"); writer.value(e.getKey()); .collect(Collectors.toList());
writer.key("c"); writer.value(e.getValue());
writer.endObject();
}
writer.endArray();
}
}
writer.endArray();
} }
} }

View File

@ -37,7 +37,7 @@ import java.util.Iterator;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang.StringUtils;
public class FingerprintKeyer extends Keyer { public class FingerprintKeyer extends Keyer {

View File

@ -34,27 +34,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.clustering.knn; package com.google.refine.clustering.knn;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.refine.Jsonizable; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.FilteredRows;
import com.google.refine.browsing.RowVisitor; import com.google.refine.browsing.RowVisitor;
import com.google.refine.clustering.ClusteredEntry;
import com.google.refine.clustering.Clusterer; import com.google.refine.clustering.Clusterer;
import com.google.refine.clustering.ClustererConfig; import com.google.refine.clustering.ClustererConfig;
import com.google.refine.model.Cell; import com.google.refine.model.Cell;
@ -76,43 +74,39 @@ import edu.mit.simile.vicino.distances.PPMDistance;
public class kNNClusterer extends Clusterer { public class kNNClusterer extends Clusterer {
public static class kNNClustererConfig extends ClustererConfig { public static class kNNClustererConfig extends ClustererConfig {
@JsonIgnore
private String _distanceStr; private String _distanceStr;
@JsonIgnore
private Distance _distance; private Distance _distance;
private kNNClustererConfigParameters _parameters; @JsonIgnore
private kNNClustererConfigParameters _parameters = null;
@Override
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("function"); writer.value(_distanceStr);
writer.key("type"); writer.value("knn");
writer.key("column"); writer.value(getColumnName());
if(_parameters != null) {
writer.key("params");
_parameters.write(writer, options);
}
writer.endObject();
}
public void initializeFromJSON(JSONObject o) {
super.initializeFromJSON(o);
_distanceStr = o.getString("function");
_distance = _distances.get(_distanceStr.toLowerCase());
if(o.has("params")) {
_parameters = kNNClustererConfigParameters.reconstruct(o.getJSONObject("params"));
} else {
_parameters = null;
}
}
@JsonIgnore
public Distance getDistance() { public Distance getDistance() {
return _distance; return _distance;
} }
@JsonProperty("function")
public void setDistance(String distanceStr) {
_distanceStr = distanceStr;
_distance = _distances.get(_distanceStr.toLowerCase());
}
@JsonProperty("function")
public String getDistanceStr() {
return _distanceStr;
}
@JsonProperty("params")
public kNNClustererConfigParameters getParameters() { public kNNClustererConfigParameters getParameters() {
return _parameters; return _parameters;
} }
@JsonProperty("params")
public void setParameters(kNNClustererConfigParameters params) {
_parameters = params;
}
@Override @Override
public kNNClusterer apply(Project project) { public kNNClusterer apply(Project project) {
kNNClusterer clusterer = new kNNClusterer(); kNNClusterer clusterer = new kNNClusterer();
@ -120,34 +114,20 @@ public class kNNClusterer extends Clusterer {
return clusterer; return clusterer;
} }
@Override
public String getType() {
return "knn";
} }
public static class kNNClustererConfigParameters implements Jsonizable { }
public static class kNNClustererConfigParameters {
public static final double defaultRadius = 1.0d; public static final double defaultRadius = 1.0d;
public static final int defaultBlockingNgramSize = 6; public static final int defaultBlockingNgramSize = 6;
@JsonProperty("radius")
public double radius = defaultRadius; public double radius = defaultRadius;
@JsonProperty("blocking-ngram-size")
public int blockingNgramSize = defaultBlockingNgramSize; public int blockingNgramSize = defaultBlockingNgramSize;
@Override
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("radius"); writer.value(radius);
writer.key("blocking-ngram-size");
writer.value(blockingNgramSize);
writer.endObject();
}
public static kNNClustererConfigParameters reconstruct(JSONObject o) {
kNNClustererConfigParameters params = new kNNClustererConfigParameters();
if(o.has("radius")) {
params.radius = o.getDouble("radius");
}
if(o.has("blocking-ngram-size")) {
params.blockingNgramSize = o.getInt("blocking-ngram-size");
}
return params;
}
} }
private Distance _distance; private Distance _distance;
@ -278,28 +258,19 @@ public class kNNClusterer extends Clusterer {
} }
} }
@Override protected List<ClusteredEntry> getClusteredEntries(Set<Serializable> s) {
public void write(JSONWriter writer, Properties options) throws JSONException { return s.stream()
writer.array(); .map(e -> new ClusteredEntry(e, _counts.get(e)))
for (Set<Serializable> m : _clusters) { .sorted(ClusteredEntry.comparator)
if (m.size() > 1) { .collect(Collectors.toList());
Map<Serializable,Integer> internal_counts = new HashMap<Serializable,Integer>();
for (Serializable s : m) {
internal_counts.put(s,_counts.get(s));
} }
List<Entry<Serializable,Integer>> values = new ArrayList<Entry<Serializable,Integer>>(internal_counts.entrySet());
Collections.sort(values, new ValuesComparator()); @JsonValue
writer.array(); public List<List<ClusteredEntry>> getJsonRepresentation() {
for (Entry<Serializable,Integer> e : values) { return _clusters.stream()
writer.object(); .filter(m -> m.size() > 1)
writer.key("v"); writer.value(e.getKey()); .map(m -> getClusteredEntries(m))
writer.key("c"); writer.value(e.getValue()); .collect(Collectors.toList());
writer.endObject();
}
writer.endArray();
}
}
writer.endArray();
} }
private void count(Serializable s) { private void count(Serializable s) {

View File

@ -44,20 +44,18 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.VelocityContext; import org.apache.velocity.VelocityContext;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.refine.Jsonizable; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonGenerator;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.ProjectMetadata;
import com.google.refine.RefineServlet; import com.google.refine.RefineServlet;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.EngineConfig;
import com.google.refine.history.HistoryEntry; import com.google.refine.history.HistoryEntry;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.model.metadata.ProjectMetadata;
import com.google.refine.process.Process; import com.google.refine.process.Process;
import com.google.refine.util.ParsingUtilities; import com.google.refine.util.ParsingUtilities;
@ -116,20 +114,14 @@ public abstract class Command {
* @return * @return
* @throws JSONException * @throws JSONException
*/ */
static protected EngineConfig getEngineConfig(HttpServletRequest request) static protected EngineConfig getEngineConfig(HttpServletRequest request) {
throws JSONException {
if (request == null) { if (request == null) {
throw new IllegalArgumentException("parameter 'request' should not be null"); throw new IllegalArgumentException("parameter 'request' should not be null");
} }
String json = request.getParameter("engine"); String json = request.getParameter("engine");
try{
return (json == null) ? null : return (json == null) ? null :
EngineConfig.reconstruct(ParsingUtilities.evaluateJsonStringToObject(json)); EngineConfig.reconstruct(json);
} catch (JSONException e){
logger.debug( json + " could not be parsed to JSON");
return null;
}
} }
/** /**
@ -196,7 +188,7 @@ public abstract class Command {
* @return * @return
* @throws ServletException * @throws ServletException
*/ */
protected ProjectMetadata getMetadata(HttpServletRequest request) throws ServletException { protected ProjectMetadata getProjectMetadata(HttpServletRequest request) throws ServletException {
if (request == null) { if (request == null) {
throw new IllegalArgumentException("parameter 'request' should not be null"); throw new IllegalArgumentException("parameter 'request' should not be null");
} }
@ -223,19 +215,14 @@ public abstract class Command {
return def; return def;
} }
static protected JSONObject getJsonParameter(HttpServletRequest request, String name) { protected static class HistoryEntryResponse {
if (request == null) { @JsonProperty("code")
throw new IllegalArgumentException("parameter 'request' should not be null"); protected String getCode() { return "ok"; }
@JsonProperty("historyEntry")
protected HistoryEntry historyEntry;
protected HistoryEntryResponse(HistoryEntry entry) {
historyEntry = entry;
} }
String value = request.getParameter(name);
if (value != null) {
try {
return ParsingUtilities.evaluateJsonStringToObject(value);
} catch (JSONException e) {
logger.warn("error getting json parameter",e);
}
}
return null;
} }
static protected void performProcessAndRespond( static protected void performProcessAndRespond(
@ -244,23 +231,18 @@ public abstract class Command {
Project project, Project project,
Process process Process process
) throws Exception { ) throws Exception {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json");
HistoryEntry historyEntry = project.processManager.queueProcess(process); HistoryEntry historyEntry = project.processManager.queueProcess(process);
if (historyEntry != null) { if (historyEntry != null) {
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); ParsingUtilities.defaultWriter.writeValue(w, new HistoryEntryResponse(historyEntry));
Properties options = new Properties();
writer.object();
writer.key("code"); writer.value("ok");
writer.key("historyEntry"); historyEntry.write(writer, options);
writer.endObject();
w.flush(); w.flush();
w.close(); w.close();
} else { } else {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json");
respond(response, "{ \"code\" : \"pending\" }"); respond(response, "{ \"code\" : \"pending\" }");
} }
} }
@ -281,49 +263,37 @@ public abstract class Command {
} }
static protected void respond(HttpServletResponse response, String status, String message) static protected void respond(HttpServletResponse response, String status, String message)
throws IOException, JSONException { throws IOException {
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
writer.object(); writer.writeStartObject();
writer.key("status"); writer.value(status); writer.writeStringField("status", status);
writer.key("message"); writer.value(message); writer.writeStringField("message", message);
writer.endObject(); writer.writeEndObject();
writer.flush();
writer.close();
w.flush(); w.flush();
w.close(); w.close();
} }
static protected void respondJSON(HttpServletResponse response, Jsonizable o) static protected void respondJSON(HttpServletResponse response, Object o)
throws IOException, JSONException { throws IOException {
respondJSON(response, o, new Properties()); respondJSON(response, o, new Properties());
} }
static protected void respondJSON( static protected void respondJSON(
HttpServletResponse response, Jsonizable o, Properties options) HttpServletResponse response, Object o, Properties options)
throws IOException, JSONException { throws IOException {
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json"); response.setHeader("Content-Type", "application/json");
response.setHeader("Cache-Control", "no-cache"); response.setHeader("Cache-Control", "no-cache");
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); ParsingUtilities.defaultWriter.writeValue(w, o);
o.write(writer, options);
w.flush();
w.close();
}
static protected void respondJSONObject(
HttpServletResponse response, JSONObject o)
throws IOException, JSONException {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json");
response.setHeader("Cache-Control", "no-cache");
Writer w = response.getWriter();
w.append(o.toString());
w.flush(); w.flush();
w.close(); w.close();
} }
@ -337,10 +307,8 @@ public abstract class Command {
throw new ServletException("Response object can't be null"); throw new ServletException("Response object can't be null");
} }
try { response.setCharacterEncoding("UTF-8");
JSONObject o = new JSONObject(); response.setHeader("Content-Type", "application/json");
o.put("code", "error");
o.put("message", e.getMessage());
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw); PrintWriter pw = new PrintWriter(sw);
@ -348,14 +316,17 @@ public abstract class Command {
pw.flush(); pw.flush();
sw.flush(); sw.flush();
o.put("stack", sw.toString()); Writer w = response.getWriter();
JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
response.setCharacterEncoding("UTF-8"); writer.writeStartObject();
response.setHeader("Content-Type", "application/json"); writer.writeStringField("code", "error");
respond(response, o.toString()); writer.writeStringField("message", e.getMessage());
} catch (JSONException e1) { writer.writeStringField("stack", sw.toString());
e.printStackTrace(response.getWriter()); writer.writeEndObject();
} writer.flush();
writer.close();
w.flush();
w.close();
} }
protected void respondWithErrorPage( protected void respondWithErrorPage(

View File

@ -34,14 +34,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.commands; package com.google.refine.commands;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONWriter;
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;
@ -56,26 +55,16 @@ public class GetAllPreferencesCommand extends Command {
project.getMetadata().getPreferenceStore() : project.getMetadata().getPreferenceStore() :
ProjectManager.singleton.getPreferenceStore(); ProjectManager.singleton.getPreferenceStore();
try { Map<String, Object> map = new HashMap<>();
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json");
JSONWriter writer = new JSONWriter(response.getWriter());
writer.object();
for (String key : ps.getKeys()) { for (String key : ps.getKeys()) {
Object pref = ps.get(key); Object pref = ps.get(key);
if (pref == null || pref instanceof String || pref instanceof Number || pref instanceof Boolean) { if (pref == null || pref instanceof String || pref instanceof Number || pref instanceof Boolean) {
writer.key(key); map.put(key, pref);
writer.value(pref);
} }
} }
writer.endObject(); respondJSON(response, map);
} catch (JSONException e) {
respondException(response, e);
}
} }
} }

View File

@ -34,52 +34,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.commands; package com.google.refine.commands;
import java.io.IOException; import java.io.IOException;
import java.util.Properties;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonProperty;
import org.json.JSONWriter;
import com.google.refine.ProjectManager; import com.google.refine.ProjectManager;
import com.google.refine.model.Project;
import com.google.refine.preference.PreferenceStore; import com.google.refine.preference.PreferenceStore;
import com.google.refine.preference.TopList; import com.google.refine.preference.TopList;
public class GetPreferenceCommand extends Command { public class GetPreferenceCommand extends Command {
protected static class PreferenceValue {
@JsonProperty("value")
protected Object value;
protected PreferenceValue(Object pref) {
if (pref == null || pref instanceof String || pref instanceof Number || pref instanceof Boolean || pref instanceof TopList) {
value = pref;
} else {
value = pref.toString();
}
}
}
@Override @Override
public void doGet(HttpServletRequest request, HttpServletResponse response) public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { throws ServletException, IOException {
Project project = request.getParameter("project") != null ? getProject(request) : null;
PreferenceStore ps = ProjectManager.singleton.getPreferenceStore(); PreferenceStore ps = ProjectManager.singleton.getPreferenceStore();
String prefName = request.getParameter("name"); String prefName = request.getParameter("name");
Object pref = ps.get(prefName); Object pref = ps.get(prefName);
try { respondJSON(response, new PreferenceValue(pref));
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json");
JSONWriter writer = new JSONWriter(response.getWriter());
writer.object();
writer.key("value");
if (pref == null || pref instanceof String || pref instanceof Number || pref instanceof Boolean) {
writer.value(pref);
} else if (pref instanceof TopList) {
TopList tl = (TopList) pref;
tl.write(writer, new Properties());
} else {
writer.value(pref.toString());
}
writer.endObject();
} catch (JSONException e) {
respondException(response, e);
}
} }
} }

View File

@ -39,27 +39,24 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException; import com.fasterxml.jackson.annotation.JsonProperty;
import org.json.JSONObject;
import com.google.refine.RefineServlet; import com.google.refine.RefineServlet;
public class GetVersionCommand extends Command { public class GetVersionCommand extends Command {
protected class VersionResponse {
@JsonProperty("version")
public String version = RefineServlet.VERSION;
@JsonProperty("revision")
public String revision = RefineServlet.REVISION;
@JsonProperty("full_version")
public String full_version = RefineServlet.FULL_VERSION;
@JsonProperty("full_name")
public String full_name = RefineServlet.FULLNAME;
}
@Override @Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try { respondJSON(response, new VersionResponse());
JSONObject o = new JSONObject();
o.put("version", RefineServlet.VERSION);
o.put("revision", RefineServlet.REVISION);
o.put("full_version", RefineServlet.FULL_VERSION);
o.put("full_name", RefineServlet.FULLNAME);
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json");
respond(response, o.toString());
} catch (JSONException e) {
e.printStackTrace(response.getWriter());
}
} }
} }

View File

@ -37,6 +37,8 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.RefineServlet; import com.google.refine.RefineServlet;
abstract public class HttpHeadersSupport { abstract public class HttpHeadersSupport {
@ -44,8 +46,11 @@ abstract public class HttpHeadersSupport {
static final protected Map<String, HttpHeaderInfo> s_headers = new HashMap<String, HttpHeaderInfo>(); static final protected Map<String, HttpHeaderInfo> s_headers = new HashMap<String, HttpHeaderInfo>();
static public class HttpHeaderInfo { static public class HttpHeaderInfo {
@JsonIgnore
final public String name; final public String name;
@JsonProperty("header")
final public String header; final public String header;
@JsonProperty("defaultValue")
final public String defaultValue; final public String defaultValue;
HttpHeaderInfo(String header, String defaultValue) { HttpHeaderInfo(String header, String defaultValue) {

View File

@ -11,13 +11,10 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.VelocityContext; import org.apache.velocity.VelocityContext;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.refine.Jsonizable; import com.fasterxml.jackson.core.JsonGenerator;
import com.google.refine.RefineServlet; import com.google.refine.RefineServlet;
import com.google.refine.util.ParsingUtilities; import com.google.refine.util.ParsingUtilities;
@ -43,36 +40,32 @@ abstract public class HttpUtilities {
throws IOException { throws IOException {
Writer w = response.getWriter(); Writer w = response.getWriter();
try { JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
JSONWriter writer = new JSONWriter(w); writer.writeStartObject();
writer.object(); writer.writeStringField("status", status);
writer.key("status"); writer.value(status); writer.writeStringField("message", message);
writer.key("message"); writer.value(message); writer.writeEndObject();
writer.endObject(); writer.flush();
writer.close();
w.flush(); w.flush();
w.close(); w.close();
} catch (JSONException e) {
// This can never occue
}
} }
static public void respondJSON(HttpServletResponse response, Jsonizable o) static public void respondJSON(HttpServletResponse response, Object o)
throws IOException, JSONException { throws IOException {
respondJSON(response, o, new Properties()); respondJSON(response, o, new Properties());
} }
static public void respondJSON( static public void respondJSON(
HttpServletResponse response, Jsonizable o, Properties options) HttpServletResponse response, Object o, Properties options)
throws IOException, JSONException { throws IOException {
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json"); response.setHeader("Content-Type", "application/json");
Writer w = response.getWriter(); Writer w = response.getWriter();
JSONWriter writer = new JSONWriter(w); ParsingUtilities.defaultWriter.writeValue(w, o);
o.write(writer, options);
w.flush(); w.flush();
w.close(); w.close();
} }
@ -86,25 +79,26 @@ abstract public class HttpUtilities {
throw new ServletException("Response object can't be null"); throw new ServletException("Response object can't be null");
} }
try {
JSONObject o = new JSONObject();
o.put("code", "error");
o.put("message", e.getMessage());
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw); PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw); e.printStackTrace(pw);
pw.flush(); pw.flush();
sw.flush(); sw.flush();
o.put("stack", sw.toString());
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json"); response.setHeader("Content-Type", "application/json");
respond(response, o.toString());
} catch (JSONException e1) { Writer w = response.getWriter();
e.printStackTrace(response.getWriter()); JsonGenerator writer = ParsingUtilities.mapper.getFactory().createGenerator(w);
} writer.writeStartObject();
writer.writeStringField("code", "error");
writer.writeStringField("message", e.getMessage());
writer.writeStringField("stack", sw.toString());
writer.writeEndObject();
writer.flush();
writer.close();
w.flush();
w.close();
} }
static public void redirect(HttpServletResponse response, String url) throws IOException { static public void redirect(HttpServletResponse response, String url) throws IOException {
@ -123,21 +117,6 @@ abstract public class HttpUtilities {
return def; return def;
} }
static public JSONObject getJsonParameter(HttpServletRequest request, String name) {
if (request == null) {
throw new IllegalArgumentException("parameter 'request' should not be null");
}
String value = request.getParameter(name);
if (value != null) {
try {
return ParsingUtilities.evaluateJsonStringToObject(value);
} catch (JSONException e) {
logger.warn("Error getting json parameter", e);
}
}
return null;
}
static public void respondWithErrorPage( static public void respondWithErrorPage(
RefineServlet servlet, RefineServlet servlet,
HttpServletRequest request, HttpServletRequest request,

View File

@ -39,12 +39,11 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException; import com.fasterxml.jackson.databind.JsonNode;
import org.json.JSONTokener;
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
@ -52,18 +51,20 @@ public class SetPreferenceCommand extends Command {
throws ServletException, IOException { throws ServletException, IOException {
Project project = request.getParameter("project") != null ? getProject(request) : null; Project project = request.getParameter("project") != null ? getProject(request) : null;
PreferenceStore ps = ProjectManager.singleton.getPreferenceStore(); PreferenceStore ps = project != null ?
project.getMetadata().getPreferenceStore() :
ProjectManager.singleton.getPreferenceStore();
String prefName = request.getParameter("name"); String prefName = request.getParameter("name");
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

@ -42,14 +42,14 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import com.google.refine.commands.Command; import com.google.refine.commands.Command;
import com.google.refine.oauth.Credentials; import com.google.refine.oauth.Credentials;
import com.google.refine.oauth.OAuthUtilities; import com.google.refine.oauth.OAuthUtilities;
import com.google.refine.oauth.Provider; import com.google.refine.oauth.Provider;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
public class AuthorizeCommand extends Command { public class AuthorizeCommand extends Command {
private static final String OAUTH_VERIFIER_PARAM = "oauth_verifier"; private static final String OAUTH_VERIFIER_PARAM = "oauth_verifier";

View File

@ -39,17 +39,15 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.clustering.Clusterer; import com.google.refine.clustering.Clusterer;
import com.google.refine.clustering.ClustererConfig; import com.google.refine.clustering.ClustererConfig;
import com.google.refine.clustering.binning.BinningClusterer.BinningClustererConfig;
import com.google.refine.clustering.knn.kNNClusterer.kNNClustererConfig;
import com.google.refine.commands.Command; import com.google.refine.commands.Command;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.util.ParsingUtilities;
public class ComputeClustersCommand extends Command { public class ComputeClustersCommand extends Command {
@ -63,24 +61,15 @@ public class ComputeClustersCommand extends Command {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
Project project = getProject(request); Project project = getProject(request);
Engine engine = getEngine(request, project); Engine engine = getEngine(request, project);
JSONObject clusterer_conf = getJsonParameter(request,"clusterer"); String clusterer_conf = request.getParameter("clusterer");
ClustererConfig clustererConfig = ParsingUtilities.mapper.readValue(clusterer_conf, ClustererConfig.class);
String type = clusterer_conf.has("type") ? clusterer_conf.getString("type") : "binning";
ClustererConfig clustererConfig = null;
if ("knn".equals(type)) {
clustererConfig = new kNNClustererConfig();
} else {
clustererConfig = new BinningClustererConfig();
}
clustererConfig.initializeFromJSON(clusterer_conf);
Clusterer clusterer = clustererConfig.apply(project); Clusterer clusterer = clustererConfig.apply(project);
clusterer.computeClusters(engine); clusterer.computeClusters(engine);
respondJSON(response, clusterer); respondJSON(response, clusterer);
logger.info("computed clusters [{},{}] in {}ms", new Object[] { type, clusterer_conf.getString("function"), Long.toString(System.currentTimeMillis() - start) }); logger.info("computed clusters [{}] in {}ms", new Object[] { clustererConfig.getType(), Long.toString(System.currentTimeMillis() - start) });
} catch (Exception e) { } catch (Exception e) {
respondException(response, e); respondException(response, e);
} }

View File

@ -44,16 +44,14 @@ import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.browsing.Engine; import com.google.refine.browsing.Engine;
import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.FilteredRows;
import com.google.refine.browsing.facets.ScatterplotDrawingRowVisitor; import com.google.refine.browsing.facets.ScatterplotDrawingRowVisitor;
import com.google.refine.browsing.facets.ScatterplotFacet; import com.google.refine.browsing.facets.ScatterplotFacet;
import com.google.refine.browsing.facets.ScatterplotFacet.ScatterplotFacetConfig;
import com.google.refine.browsing.util.NumericBinIndex; import com.google.refine.browsing.util.NumericBinIndex;
import com.google.refine.commands.Command; import com.google.refine.commands.Command;
import com.google.refine.expr.Evaluable; import com.google.refine.expr.Evaluable;
@ -61,6 +59,7 @@ import com.google.refine.expr.MetaParser;
import com.google.refine.expr.ParsingException; import com.google.refine.expr.ParsingException;
import com.google.refine.model.Column; import com.google.refine.model.Column;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.util.ParsingUtilities;
public class GetScatterplotCommand extends Command { public class GetScatterplotCommand extends Command {
@ -75,7 +74,9 @@ public class GetScatterplotCommand extends Command {
Project project = getProject(request); Project project = getProject(request);
Engine engine = getEngine(request, project); Engine engine = getEngine(request, project);
JSONObject conf = getJsonParameter(request,"plotter"); PlotterConfig conf = ParsingUtilities.mapper.readValue(
request.getParameter("plotter"),
PlotterConfig.class);
response.setHeader("Content-Type", "image/png"); response.setHeader("Content-Type", "image/png");
@ -95,7 +96,32 @@ public class GetScatterplotCommand extends Command {
} }
} }
public void draw(OutputStream output, Project project, Engine engine, JSONObject o) throws IOException, JSONException { protected static class PlotterConfig {
@JsonProperty(ScatterplotFacet.SIZE)
public int size = 100;
@JsonProperty(ScatterplotFacet.DOT)
double dot = 100;
@JsonProperty(ScatterplotFacet.DIM_X)
public int dim_x = ScatterplotFacet.LIN;
@JsonProperty(ScatterplotFacet.DIM_Y)
public int dim_y = ScatterplotFacet.LIN;
@JsonProperty(ScatterplotFacet.ROTATION)
public int rotation = ScatterplotFacet.NO_ROTATION;
@JsonProperty(ScatterplotFacet.COLOR)
public String color_str = "000000";
@JsonProperty(ScatterplotFacet.BASE_COLOR)
public String base_color_str = null;
@JsonProperty(ScatterplotFacet.X_COLUMN_NAME)
public String columnName_x = "";
@JsonProperty(ScatterplotFacet.X_EXPRESSION)
public String expression_x = "value";
@JsonProperty(ScatterplotFacet.Y_COLUMN_NAME)
public String columnName_y = "";
@JsonProperty(ScatterplotFacet.Y_EXPRESSION)
public String expression_y = "value";
}
public void draw(OutputStream output, Project project, Engine engine, PlotterConfig o) throws IOException {
double min_x = 0; double min_x = 0;
double min_y = 0; double min_y = 0;
@ -108,26 +134,12 @@ public class GetScatterplotCommand extends Command {
Evaluable eval_x = null; Evaluable eval_x = null;
Evaluable eval_y = null; Evaluable eval_y = null;
int size = (o.has(ScatterplotFacet.SIZE)) ? o.getInt(ScatterplotFacet.SIZE) : 100; Color color = new Color(Integer.parseInt(o.color_str,16));
double dot = (o.has(ScatterplotFacet.DOT)) ? o.getDouble(ScatterplotFacet.DOT) : 100; Color base_color = o.base_color_str != null ? new Color(Integer.parseInt(o.base_color_str,16)) : null;
int dim_x = (o.has(ScatterplotFacet.DIM_X)) ? ScatterplotFacet.getAxisDim(o.getString(ScatterplotFacet.DIM_X)) : ScatterplotFacet.LIN; if (o.columnName_x.length() > 0) {
int dim_y = (o.has(ScatterplotFacet.DIM_Y)) ? ScatterplotFacet.getAxisDim(o.getString(ScatterplotFacet.DIM_Y)) : ScatterplotFacet.LIN; Column x_column = project.columnModel.getColumnByName(o.columnName_x);
int rotation = (o.has(ScatterplotFacet.ROTATION)) ? ScatterplotFacetConfig.getRotation(o.getString(ScatterplotFacet.ROTATION)) : ScatterplotFacet.NO_ROTATION;
String color_str = (o.has(ScatterplotFacet.COLOR)) ? o.getString(ScatterplotFacet.COLOR) : "000000";
Color color = new Color(Integer.parseInt(color_str,16));
String base_color_str = (o.has(ScatterplotFacet.BASE_COLOR)) ? o.getString(ScatterplotFacet.BASE_COLOR) : null;
Color base_color = base_color_str != null ? new Color(Integer.parseInt(base_color_str,16)) : null;
String columnName_x = o.getString(ScatterplotFacet.X_COLUMN_NAME);
String expression_x = (o.has(ScatterplotFacet.X_EXPRESSION)) ? o.getString(ScatterplotFacet.X_EXPRESSION) : "value";
if (columnName_x.length() > 0) {
Column x_column = project.columnModel.getColumnByName(columnName_x);
if (x_column != null) { if (x_column != null) {
columnIndex_x = x_column.getCellIndex(); columnIndex_x = x_column.getCellIndex();
} }
@ -136,16 +148,13 @@ public class GetScatterplotCommand extends Command {
} }
try { try {
eval_x = MetaParser.parse(expression_x); eval_x = MetaParser.parse(o.expression_x);
} catch (ParsingException e) { } catch (ParsingException e) {
logger.warn("error parsing expression", e); logger.warn("error parsing expression", e);
} }
String columnName_y = o.getString(ScatterplotFacet.Y_COLUMN_NAME); if (o.columnName_y.length() > 0) {
String expression_y = (o.has(ScatterplotFacet.Y_EXPRESSION)) ? o.getString(ScatterplotFacet.Y_EXPRESSION) : "value"; Column y_column = project.columnModel.getColumnByName(o.columnName_y);
if (columnName_y.length() > 0) {
Column y_column = project.columnModel.getColumnByName(columnName_y);
if (y_column != null) { if (y_column != null) {
columnIndex_y = y_column.getCellIndex(); columnIndex_y = y_column.getCellIndex();
} }
@ -154,7 +163,7 @@ public class GetScatterplotCommand extends Command {
} }
try { try {
eval_y = MetaParser.parse(expression_y); eval_y = MetaParser.parse(o.expression_y);
} catch (ParsingException e) { } catch (ParsingException e) {
logger.warn("error parsing expression", e); logger.warn("error parsing expression", e);
} }
@ -162,20 +171,18 @@ public class GetScatterplotCommand extends Command {
NumericBinIndex index_x = null; NumericBinIndex index_x = null;
NumericBinIndex index_y = null; NumericBinIndex index_y = null;
String col_x_name = o.getString(ScatterplotFacet.X_COLUMN_NAME); Column column_x = project.columnModel.getColumnByName(o.columnName_x);
Column column_x = project.columnModel.getColumnByName(col_x_name);
if (column_x != null) { if (column_x != null) {
columnIndex_x = column_x.getCellIndex(); columnIndex_x = column_x.getCellIndex();
index_x = ScatterplotFacet.getBinIndex(project, column_x, eval_x, expression_x); index_x = ScatterplotFacet.getBinIndex(project, column_x, eval_x, o.expression_x);
min_x = index_x.getMin(); min_x = index_x.getMin();
max_x = index_x.getMax(); max_x = index_x.getMax();
} }
String col_y_name = o.getString(ScatterplotFacet.Y_COLUMN_NAME); Column column_y = project.columnModel.getColumnByName(o.columnName_y);
Column column_y = project.columnModel.getColumnByName(col_y_name);
if (column_y != null) { if (column_y != null) {
columnIndex_y = column_y.getCellIndex(); columnIndex_y = column_y.getCellIndex();
index_y = ScatterplotFacet.getBinIndex(project, column_y, eval_y, expression_y); index_y = ScatterplotFacet.getBinIndex(project, column_y, eval_y, o.expression_y);
min_y = index_y.getMin(); min_y = index_y.getMin();
max_y = index_y.getMax(); max_y = index_y.getMax();
} }
@ -183,7 +190,7 @@ public class GetScatterplotCommand extends Command {
if (index_x != null && index_y != null && index_x.isNumeric() && index_y.isNumeric()) { if (index_x != null && index_y != null && index_x.isNumeric() && index_y.isNumeric()) {
ScatterplotDrawingRowVisitor drawer = new ScatterplotDrawingRowVisitor( ScatterplotDrawingRowVisitor drawer = new ScatterplotDrawingRowVisitor(
columnIndex_x, columnIndex_y, min_x, max_x, min_y, max_y, columnIndex_x, columnIndex_y, min_x, max_x, min_y, max_y,
size, dim_x, dim_y, rotation, dot, color o.size, o.dim_x, o.dim_y, o.rotation, o.dot, color
); );
if (base_color != null) { if (base_color != null) {

View File

@ -35,14 +35,14 @@ package com.google.refine.commands.cell;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.util.Properties;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONWriter; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.commands.Command; import com.google.refine.commands.Command;
import com.google.refine.history.Change; import com.google.refine.history.Change;
import com.google.refine.history.HistoryEntry; import com.google.refine.history.HistoryEntry;
@ -55,6 +55,32 @@ import com.google.refine.util.ParsingUtilities;
import com.google.refine.util.Pool; import com.google.refine.util.Pool;
public class EditOneCellCommand extends Command { public class EditOneCellCommand extends Command {
protected static class EditResult {
@JsonProperty("code")
protected String code;
@JsonProperty("historyEntry")
@JsonInclude(Include.NON_NULL)
protected HistoryEntry historyEntry;
@JsonProperty("cell")
@JsonInclude(Include.NON_NULL)
protected Cell cell;
@JsonProperty("pool")
@JsonInclude(Include.NON_NULL)
protected Pool pool;
protected EditResult(
String code,
HistoryEntry historyEntry,
Cell cell,
Pool pool) {
this.code = code;
this.historyEntry = historyEntry;
this.cell = cell;
this.pool = pool;
}
}
@Override @Override
public void doPost(HttpServletRequest request, HttpServletResponse response) public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { throws ServletException, IOException {
@ -96,18 +122,11 @@ public class EditOneCellCommand extends Command {
* If the operation has been done, return the new cell's data * If the operation has been done, return the new cell's data
* so the client side can update the cell's rendering right away. * so the client side can update the cell's rendering right away.
*/ */
JSONWriter writer = new JSONWriter(response.getWriter());
Pool pool = new Pool(); Pool pool = new Pool();
Properties options = new Properties(); if(process.newCell != null && process.newCell.recon != null) {
options.put("pool", pool); pool.pool(process.newCell.recon);
}
writer.object(); respondJSON(response, new EditResult("ok", historyEntry, process.newCell, pool));
writer.key("code"); writer.value("ok");
writer.key("historyEntry"); historyEntry.write(writer, options);
writer.key("cell"); process.newCell.write(writer, options);
writer.key("pool"); pool.write(writer, options);
writer.endObject();
} else { } else {
respond(response, "{ \"code\" : \"pending\" }"); respond(response, "{ \"code\" : \"pending\" }");
} }

View File

@ -33,13 +33,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.commands.cell; package com.google.refine.commands.cell;
import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.EngineConfig;
import com.google.refine.commands.EngineDependentCommand; import com.google.refine.commands.EngineDependentCommand;
import com.google.refine.model.AbstractOperation; import com.google.refine.model.AbstractOperation;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.operations.cell.MassEditOperation; import com.google.refine.operations.cell.MassEditOperation;
import com.google.refine.operations.cell.MassEditOperation.Edit;
import com.google.refine.util.ParsingUtilities; import com.google.refine.util.ParsingUtilities;
public class MassEditCommand extends EngineDependentCommand { public class MassEditCommand extends EngineDependentCommand {
@ -55,7 +59,7 @@ public class MassEditCommand extends EngineDependentCommand {
engineConfig, engineConfig,
columnName, columnName,
expression, expression,
MassEditOperation.reconstructEdits(ParsingUtilities.evaluateJsonStringToArray(editsString)) ParsingUtilities.mapper.readValue(editsString, new TypeReference<List<Edit>>() {})
); );
} }
} }

View File

@ -40,14 +40,13 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray; import com.fasterxml.jackson.core.type.TypeReference;
import com.google.refine.commands.Command; import com.google.refine.commands.Command;
import com.google.refine.model.AbstractOperation; import com.google.refine.model.AbstractOperation;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.operations.cell.MultiValuedCellSplitOperation; import com.google.refine.operations.cell.MultiValuedCellSplitOperation;
import com.google.refine.util.ParsingUtilities;
import com.google.refine.process.Process; import com.google.refine.process.Process;
import com.google.refine.util.ParsingUtilities;
public class SplitMultiValueCellsCommand extends Command { public class SplitMultiValueCellsCommand extends Command {
@Override @Override
@ -74,12 +73,7 @@ public class SplitMultiValueCellsCommand extends Command {
} else { } else {
String s = request.getParameter("fieldLengths"); String s = request.getParameter("fieldLengths");
JSONArray a = ParsingUtilities.evaluateJsonStringToArray(s); int[] fieldLengths = ParsingUtilities.mapper.readValue(s, new TypeReference<int[]>() {});
int[] fieldLengths = new int[a.length()];
for (int i = 0; i < fieldLengths.length; i++) {
fieldLengths[i] = a.getInt(i);
}
AbstractOperation op = new MultiValuedCellSplitOperation(columnName, AbstractOperation op = new MultiValuedCellSplitOperation(columnName,
keyColumnName, keyColumnName,

View File

@ -33,16 +33,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.commands.column; package com.google.refine.commands.column;
import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.json.JSONArray; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.refine.browsing.EngineConfig; import com.google.refine.browsing.EngineConfig;
import com.google.refine.commands.EngineDependentCommand; import com.google.refine.commands.EngineDependentCommand;
import com.google.refine.model.AbstractOperation; import com.google.refine.model.AbstractOperation;
import com.google.refine.model.Project; import com.google.refine.model.Project;
import com.google.refine.operations.cell.TextTransformOperation; import com.google.refine.operations.cell.TextTransformOperation;
import com.google.refine.operations.column.ColumnAdditionByFetchingURLsOperation; import com.google.refine.operations.column.ColumnAdditionByFetchingURLsOperation;
import com.google.refine.operations.column.ColumnAdditionByFetchingURLsOperation.HttpHeader;
public class AddColumnByFetchingURLsCommand extends EngineDependentCommand { public class AddColumnByFetchingURLsCommand extends EngineDependentCommand {
@Override @Override
@ -56,7 +59,8 @@ public class AddColumnByFetchingURLsCommand extends EngineDependentCommand {
int delay = Integer.parseInt(request.getParameter("delay")); int delay = Integer.parseInt(request.getParameter("delay"));
String onError = request.getParameter("onError"); String onError = request.getParameter("onError");
boolean cacheResponses = Boolean.parseBoolean(request.getParameter("cacheResponses")); boolean cacheResponses = Boolean.parseBoolean(request.getParameter("cacheResponses"));
JSONArray httpHeadersJson = new JSONArray(request.getParameter("httpHeaders")); ObjectMapper mapper = new ObjectMapper();
List<HttpHeader> headers = Arrays.asList(mapper.readValue(request.getParameter("httpHeaders"), HttpHeader[].class));
return new ColumnAdditionByFetchingURLsOperation( return new ColumnAdditionByFetchingURLsOperation(
engineConfig, engineConfig,
@ -67,7 +71,7 @@ public class AddColumnByFetchingURLsCommand extends EngineDependentCommand {
columnInsertIndex, columnInsertIndex,
delay, delay,
cacheResponses, cacheResponses,
httpHeadersJson headers
); );
} }

Some files were not shown because too many files have changed in this diff Show More