First pass implementation of new Fusion Tables API - fixes #539
This commit is contained in:
parent
2464421014
commit
7fb95ebbad
@ -29,20 +29,18 @@
|
|||||||
package com.google.refine.extension.gdata;
|
package com.google.refine.extension.gdata;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Scanner;
|
|
||||||
import java.util.regex.MatchResult;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import com.google.gdata.client.GoogleService;
|
import com.google.api.client.auth.oauth2.Credential;
|
||||||
import com.google.gdata.client.Service.GDataRequest;
|
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||||
import com.google.gdata.client.Service.GDataRequest.RequestType;
|
import com.google.api.client.http.AbstractInputStreamContent;
|
||||||
import com.google.gdata.util.ContentType;
|
import com.google.api.services.fusiontables.Fusiontables;
|
||||||
import com.google.gdata.util.ServiceException;
|
import com.google.api.services.fusiontables.Fusiontables.Query.Sql;
|
||||||
|
import com.google.api.services.fusiontables.Fusiontables.Query.SqlGet;
|
||||||
|
import com.google.api.services.fusiontables.Fusiontables.Table.ImportRows;
|
||||||
|
import com.google.api.services.fusiontables.model.FusiontablesImport;
|
||||||
|
import com.google.api.services.fusiontables.model.Sqlresponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tom Morris <tfmorris@gmail.com>
|
* @author Tom Morris <tfmorris@gmail.com>
|
||||||
@ -51,54 +49,83 @@ import com.google.gdata.util.ServiceException;
|
|||||||
|
|
||||||
public class FusionTableHandler {
|
public class FusionTableHandler {
|
||||||
|
|
||||||
final static private String FUSION_TABLES_SERVICE_URL =
|
static private Sqlresponse executeQuery (Fusiontables service, String query)
|
||||||
"https://www.google.com/fusiontables/api/query";
|
throws IOException {
|
||||||
// "https://www.googleapis.com/fusiontables/v1/query";
|
Sql sql = service.query().sql(query);
|
||||||
|
Sqlresponse response = sql.execute();
|
||||||
final static private Pattern CSV_VALUE_PATTERN =
|
return response;
|
||||||
Pattern.compile("([^,\\r\\n\"]*|\"(([^\"]*\"\")*[^\"]*)\")(,|\\r?\\n)");
|
}
|
||||||
|
|
||||||
static public GDataRequest createFusionTablesPostRequest(
|
static String createTable(Fusiontables service, String name, List<String> columnNames) throws IOException {
|
||||||
GoogleService service, RequestType requestType, String query)
|
StringBuffer sb = new StringBuffer();
|
||||||
throws IOException, ServiceException {
|
sb.append("CREATE TABLE '");
|
||||||
|
sb.append(name);
|
||||||
URL url = new URL(FUSION_TABLES_SERVICE_URL);
|
sb.append("' (");
|
||||||
GDataRequest request = service.getRequestFactory().getRequest(
|
boolean first = true;
|
||||||
requestType, url, new ContentType("application/x-www-form-urlencoded"));
|
for (String columnName : columnNames) {
|
||||||
|
if (first) {
|
||||||
OutputStreamWriter writer =
|
first = false;
|
||||||
new OutputStreamWriter(request.getRequestStream());
|
} else {
|
||||||
writer.append("sql=" + URLEncoder.encode(query, "UTF-8") + "&alt=csv");
|
sb.append(',');
|
||||||
writer.flush();
|
}
|
||||||
writer.close();
|
sb.append("'");
|
||||||
|
sb.append(columnName);
|
||||||
return request;
|
sb.append("': STRING");
|
||||||
|
}
|
||||||
|
sb.append(")");
|
||||||
|
|
||||||
|
String createQuery = sb.toString();
|
||||||
|
|
||||||
|
Sqlresponse response = executeQuery(service, createQuery);
|
||||||
|
// response.getTableId(); // FIXME: Oh wait, there's no such F*ing method!!!
|
||||||
|
return getTableId(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public GDataRequest createFusionTablesRequest(
|
private static String getTableId(Sqlresponse response) {
|
||||||
GoogleService service, RequestType requestType, String query)
|
List<Object> row = response.getRows().get(0);
|
||||||
throws IOException, ServiceException {
|
int i = 0;
|
||||||
URL url = new URL(FUSION_TABLES_SERVICE_URL + "?sql=" +
|
for (String colname : response.getColumns()) {
|
||||||
URLEncoder.encode(query, "UTF-8")+"&alt=csv");
|
if ("tableid".equals(colname)) {
|
||||||
return service.getRequestFactory().getRequest(
|
return (String) row.get(i);
|
||||||
requestType, url, ContentType.TEXT_PLAIN);
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a set of rows and optionally return the IDs of the new rows.
|
||||||
|
*
|
||||||
|
* @param service a Fusiontables object
|
||||||
|
* @param sql SQL statement to do the inserts
|
||||||
|
* @param returnIds true to return the IDs of the newly inserted rows
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
static Long insertRows(Fusiontables service, String tableId, AbstractInputStreamContent mediaContent) throws IOException {
|
||||||
|
ImportRows importRows = service.table().importRows(tableId, mediaContent);
|
||||||
|
importRows.setIsStrict(false);
|
||||||
|
FusiontablesImport response = importRows.execute();
|
||||||
|
return response.getNumRowsReceived();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static String getFusionTableKey(URL url) {
|
static String getFusionTableKey(URL url) {
|
||||||
String tableId = getParamValue(url,"dsrcid");
|
String tableId = getParamValue(url,"dsrcid"); // old style phased out
|
||||||
// TODO: Any special id format considerations to worry about?
|
if (tableId == null || tableId.isEmpty()) {
|
||||||
// if (tableId.startsWith("p") || !tableId.contains(".")) {
|
tableId = getParamValue(url,"docid");
|
||||||
// return tableId;
|
}
|
||||||
// }
|
|
||||||
return tableId;
|
return tableId;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public GoogleService getFusionTablesGoogleService(String token) {
|
static public Fusiontables getFusionTablesService(String token) {
|
||||||
GoogleService service = new GoogleService("fusiontables", GDataExtension.SERVICE_APP_NAME);
|
Credential credential = new GoogleCredential().setAccessToken(token);
|
||||||
if (token != null) {
|
Fusiontables fusiontables = new Fusiontables.Builder(
|
||||||
service.setAuthSubToken(token);
|
GDataExtension.HTTP_TRANSPORT, GDataExtension.JSON_FACTORY, credential)
|
||||||
}
|
.setApplicationName(GDataExtension.SERVICE_APP_NAME)
|
||||||
return service;
|
.build();;
|
||||||
|
|
||||||
|
return fusiontables;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isFusionTableURL(URL url) {
|
static boolean isFusionTableURL(URL url) {
|
||||||
@ -109,60 +136,17 @@ public class FusionTableHandler {
|
|||||||
}
|
}
|
||||||
return url.getHost().endsWith(".google.com")
|
return url.getHost().endsWith(".google.com")
|
||||||
&& url.getPath().startsWith("/fusiontables/DataSource")
|
&& url.getPath().startsWith("/fusiontables/DataSource")
|
||||||
&& query.contains("dsrcid=");
|
&& (query.contains("dsrcid=")||query.contains("docid="));
|
||||||
}
|
}
|
||||||
|
|
||||||
static public List<List<String>> parseFusionTablesResults(GDataRequest request) throws IOException {
|
static Sqlresponse runFusionTablesSelect(Fusiontables service, String selectQuery)
|
||||||
List<List<String>> rows = new ArrayList<List<String>>();
|
throws IOException {
|
||||||
List<String> row = null;
|
|
||||||
|
|
||||||
Scanner scanner = new Scanner(request.getResponseStream(), "UTF-8");
|
// FIXME: alt=csv doesn't actually work! It will attempt to parse response as JSON and die
|
||||||
while (scanner.hasNextLine()) {
|
// perhaps use .executeUnparsed() would work?
|
||||||
scanner.findWithinHorizon(CSV_VALUE_PATTERN, 0);
|
SqlGet query = service.query().sqlGet(selectQuery);//.setAlt("csv");
|
||||||
MatchResult match = scanner.match();
|
Sqlresponse response = query.execute();
|
||||||
String quotedString = match.group(2);
|
return response;
|
||||||
String decoded = quotedString == null ? match.group(1) : quotedString.replaceAll("\"\"", "\"");
|
|
||||||
|
|
||||||
if (row == null) {
|
|
||||||
row = new ArrayList<String>();
|
|
||||||
}
|
|
||||||
row.add(decoded);
|
|
||||||
|
|
||||||
if (!match.group(4).equals(",")) {
|
|
||||||
if (row != null) {
|
|
||||||
rows.add(row);
|
|
||||||
row = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scanner.close();
|
|
||||||
if (row != null) {
|
|
||||||
rows.add(row);
|
|
||||||
}
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
static public List<List<String>> listTables(GoogleService service) throws IOException, ServiceException {
|
|
||||||
List<List<String>> rows = runFusionTablesSelect(service, "SHOW TABLES");
|
|
||||||
// Format is id, name to which we append a link URL based on ID
|
|
||||||
if (rows.size() > 1) { // excluding headers
|
|
||||||
for (int i = 1; i < rows.size(); i++) {
|
|
||||||
List<String> row = rows.get(i);
|
|
||||||
if (row.size() >= 2) {
|
|
||||||
String id = row.get(0);
|
|
||||||
row.add("https://www.google.com/fusiontables/DataSource?docid=" + id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
static public List<List<String>> runFusionTablesSelect(GoogleService service, String selectQuery)
|
|
||||||
throws IOException, ServiceException {
|
|
||||||
|
|
||||||
GDataRequest request = createFusionTablesRequest(service, RequestType.QUERY, selectQuery);
|
|
||||||
request.execute();
|
|
||||||
return parseFusionTablesResults(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static private String getParamValue(URL url, String key) {
|
static private String getParamValue(URL url, String key) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2010, Thomas F. Morris
|
* Copyright (c) 2010,2013 Thomas F. Morris and other contributors
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -34,8 +34,10 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import com.google.gdata.client.GoogleService;
|
import com.google.api.services.fusiontables.Fusiontables;
|
||||||
import com.google.gdata.util.ServiceException;
|
import com.google.api.services.fusiontables.model.Column;
|
||||||
|
import com.google.api.services.fusiontables.model.Sqlresponse;
|
||||||
|
import com.google.api.services.fusiontables.model.Table;
|
||||||
|
|
||||||
import com.google.refine.ProjectMetadata;
|
import com.google.refine.ProjectMetadata;
|
||||||
import com.google.refine.importers.TabularImportingParserBase;
|
import com.google.refine.importers.TabularImportingParserBase;
|
||||||
@ -61,7 +63,7 @@ public class FusionTableImporter {
|
|||||||
JSONObject options,
|
JSONObject options,
|
||||||
List<Exception> exceptions) {
|
List<Exception> exceptions) {
|
||||||
|
|
||||||
GoogleService service = FusionTableHandler.getFusionTablesGoogleService(token);
|
Fusiontables service = FusionTableHandler.getFusionTablesService(token);
|
||||||
parse(
|
parse(
|
||||||
service,
|
service,
|
||||||
project,
|
project,
|
||||||
@ -89,7 +91,7 @@ public class FusionTableImporter {
|
|||||||
final ImportingJob job;
|
final ImportingJob job;
|
||||||
final String fileSource;
|
final String fileSource;
|
||||||
|
|
||||||
final GoogleService service;
|
final Fusiontables service;
|
||||||
final List<FTColumnData> columns;
|
final List<FTColumnData> columns;
|
||||||
final int batchSize;
|
final int batchSize;
|
||||||
|
|
||||||
@ -102,7 +104,7 @@ public class FusionTableImporter {
|
|||||||
boolean usedHeaders = false;
|
boolean usedHeaders = false;
|
||||||
|
|
||||||
public FusionTableBatchRowReader(ImportingJob job, String fileSource,
|
public FusionTableBatchRowReader(ImportingJob job, String fileSource,
|
||||||
GoogleService service, String tableId, List<FTColumnData> columns,
|
Fusiontables service, String tableId, List<FTColumnData> columns,
|
||||||
int batchSize) {
|
int batchSize) {
|
||||||
this.job = job;
|
this.job = job;
|
||||||
this.fileSource = fileSource;
|
this.fileSource = fileSource;
|
||||||
@ -143,14 +145,10 @@ public class FusionTableImporter {
|
|||||||
|
|
||||||
if (rowsOfCells == null || (nextRow >= batchRowStart + rowsOfCells.size() && !end)) {
|
if (rowsOfCells == null || (nextRow >= batchRowStart + rowsOfCells.size() && !end)) {
|
||||||
int newBatchRowStart = batchRowStart + (rowsOfCells == null ? 0 : rowsOfCells.size());
|
int newBatchRowStart = batchRowStart + (rowsOfCells == null ? 0 : rowsOfCells.size());
|
||||||
try {
|
rowsOfCells = getRowsOfCells(newBatchRowStart);
|
||||||
rowsOfCells = getRowsOfCells(newBatchRowStart);
|
batchRowStart = newBatchRowStart;
|
||||||
batchRowStart = newBatchRowStart;
|
|
||||||
|
GDataImporter.setProgress(job, fileSource, -1 /* batchRowStart * 100 / totalRows */);
|
||||||
GDataImporter.setProgress(job, fileSource, -1 /* batchRowStart * 100 / totalRows */);
|
|
||||||
} catch (ServiceException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rowsOfCells != null && nextRow - batchRowStart < rowsOfCells.size()) {
|
if (rowsOfCells != null && nextRow - batchRowStart < rowsOfCells.size()) {
|
||||||
@ -161,18 +159,19 @@ public class FusionTableImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<List<Object>> getRowsOfCells(int startRow) throws IOException, ServiceException {
|
private List<List<Object>> getRowsOfCells(int startRow) throws IOException {
|
||||||
List<List<Object>> rowsOfCells = new ArrayList<List<Object>>(batchSize);
|
List<List<Object>> rowsOfCells = new ArrayList<List<Object>>(batchSize);
|
||||||
|
|
||||||
String query = baseQuery + " OFFSET " + startRow + " LIMIT " + batchSize;
|
String query = baseQuery + " OFFSET " + startRow + " LIMIT " + batchSize;
|
||||||
|
|
||||||
List<List<String>> rows = FusionTableHandler.runFusionTablesSelect(service, query);
|
Sqlresponse sqlresponse = FusionTableHandler.runFusionTablesSelect(service, query);
|
||||||
|
List<List<Object>> rows = sqlresponse.getRows();
|
||||||
if (rows.size() > 1) {
|
if (rows.size() > 1) {
|
||||||
for (int i = 1; i < rows.size(); i++) {
|
for (int i = 1; i < rows.size(); i++) {
|
||||||
List<String> row = rows.get(i);
|
List<Object> row = rows.get(i);
|
||||||
List<Object> rowOfCells = new ArrayList<Object>(row.size());
|
List<Object> rowOfCells = new ArrayList<Object>(row.size());
|
||||||
for (int j = 0; j < row.size() && j < columns.size(); j++) {
|
for (int j = 0; j < row.size() && j < columns.size(); j++) {
|
||||||
String text = row.get(j);
|
String text = (String)row.get(j);
|
||||||
if (text.isEmpty()) {
|
if (text.isEmpty()) {
|
||||||
rowOfCells.add(null);
|
rowOfCells.add(null);
|
||||||
} else {
|
} else {
|
||||||
@ -208,7 +207,7 @@ public class FusionTableImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static public void parse(
|
static public void parse(
|
||||||
GoogleService service,
|
Fusiontables service,
|
||||||
Project project,
|
Project project,
|
||||||
ProjectMetadata metadata,
|
ProjectMetadata metadata,
|
||||||
final ImportingJob job,
|
final ImportingJob job,
|
||||||
@ -222,37 +221,34 @@ public class FusionTableImporter {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
List<FTColumnData> columns = new ArrayList<FusionTableImporter.FTColumnData>();
|
List<FTColumnData> columns = new ArrayList<FusionTableImporter.FTColumnData>();
|
||||||
List<List<String>> rows = FusionTableHandler.runFusionTablesSelect(service, "DESCRIBE " + id);
|
Table table = service.table().get(id).execute();
|
||||||
if (rows.size() > 1) {
|
for (Column col : table.getColumns()) {
|
||||||
for (int i = 1; i < rows.size(); i++) {
|
FTColumnData cd = new FTColumnData();
|
||||||
List<String> row = rows.get(i);
|
cd.name = col.getName();
|
||||||
if (row.size() >= 2) {
|
String type = col.getType();
|
||||||
FTColumnData cd = new FTColumnData();
|
if (type.equals("STRING")) {
|
||||||
cd.name = row.get(1);
|
cd.type = FTColumnType.STRING;
|
||||||
cd.type = FTColumnType.STRING;
|
} else if (type.equals("NUMBER")) {
|
||||||
|
cd.type = FTColumnType.NUMBER;
|
||||||
if (row.size() > 2) {
|
} else if (type.equals("DATETIME")) {
|
||||||
String type = row.get(2).toLowerCase();
|
cd.type = FTColumnType.DATETIME;
|
||||||
if (type.equals("number")) {
|
} else if (type.equals("LOCATION")) {
|
||||||
cd.type = FTColumnType.NUMBER;
|
cd.type = FTColumnType.LOCATION;
|
||||||
} else if (type.equals("datetime")) {
|
} else {
|
||||||
cd.type = FTColumnType.DATETIME;
|
// TODO: unknown type
|
||||||
} else if (type.equals("location")) {
|
cd.type = FTColumnType.STRING;
|
||||||
cd.type = FTColumnType.LOCATION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
columns.add(cd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
columns.add(cd);
|
||||||
setProgress(job, docUrlString, -1);
|
}
|
||||||
|
|
||||||
// Force these options for the next call because each fusion table
|
setProgress(job, docUrlString, -1);
|
||||||
// is strictly structured with a single line of headers.
|
|
||||||
JSONUtilities.safePut(options, "ignoreLines", 0); // number of blank lines at the beginning to ignore
|
// Force these options for the next call because each fusion table
|
||||||
JSONUtilities.safePut(options, "headerLines", 1); // number of header lines
|
// is strictly structured with a single line of headers.
|
||||||
|
JSONUtilities.safePut(options, "ignoreLines", 0); // number of blank lines at the beginning to ignore
|
||||||
TabularImportingParserBase.readTable(
|
JSONUtilities.safePut(options, "headerLines", 1); // number of header lines
|
||||||
|
|
||||||
|
TabularImportingParserBase.readTable(
|
||||||
project,
|
project,
|
||||||
metadata,
|
metadata,
|
||||||
job,
|
job,
|
||||||
@ -262,14 +258,10 @@ public class FusionTableImporter {
|
|||||||
options,
|
options,
|
||||||
exceptions
|
exceptions
|
||||||
);
|
);
|
||||||
setProgress(job, docUrlString, 100);
|
setProgress(job, docUrlString, 100);
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
exceptions.add(e);
|
exceptions.add(e);
|
||||||
} catch (ServiceException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
exceptions.add(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,15 +6,16 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import com.google.gdata.client.GoogleService;
|
import com.google.api.client.http.AbstractInputStreamContent;
|
||||||
import com.google.gdata.client.Service.GDataRequest;
|
import com.google.api.client.http.ByteArrayContent;
|
||||||
import com.google.gdata.client.Service.GDataRequest.RequestType;
|
import com.google.api.client.http.HttpResponseException;
|
||||||
import com.google.gdata.util.ServiceException;
|
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 {
|
||||||
GoogleService service;
|
private static final int BATCH_SIZE = 20;
|
||||||
|
Fusiontables service;
|
||||||
String tableName;
|
String tableName;
|
||||||
List<Exception> exceptions;
|
List<Exception> exceptions;
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ final class FusionTableSerializer implements TabularSerializer {
|
|||||||
StringBuffer sbBatch;
|
StringBuffer sbBatch;
|
||||||
int rows;
|
int rows;
|
||||||
|
|
||||||
FusionTableSerializer(GoogleService service, String tableName, List<Exception> exceptions) {
|
FusionTableSerializer(Fusiontables service, String tableName, List<Exception> exceptions) {
|
||||||
this.service = service;
|
this.service = service;
|
||||||
this.tableName = tableName;
|
this.tableName = tableName;
|
||||||
this.exceptions = exceptions;
|
this.exceptions = exceptions;
|
||||||
@ -44,68 +45,75 @@ final class FusionTableSerializer implements TabularSerializer {
|
|||||||
public void addRow(List<CellData> cells, boolean isHeader) {
|
public void addRow(List<CellData> cells, boolean isHeader) {
|
||||||
if (isHeader) {
|
if (isHeader) {
|
||||||
columnNames = new ArrayList<String>(cells.size());
|
columnNames = new ArrayList<String>(cells.size());
|
||||||
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
sb.append("CREATE TABLE '");
|
|
||||||
sb.append(tableName);
|
|
||||||
sb.append("' (");
|
|
||||||
boolean first = true;
|
|
||||||
for (CellData cellData : cells) {
|
for (CellData cellData : cells) {
|
||||||
columnNames.add(cellData.text);
|
columnNames.add(cellData.text);
|
||||||
|
}
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
sb.append(',');
|
|
||||||
}
|
|
||||||
sb.append("'");
|
|
||||||
sb.append(cellData.text);
|
|
||||||
sb.append("': STRING");
|
|
||||||
}
|
|
||||||
sb.append(")");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String createQuery = sb.toString();
|
tableId = FusionTableHandler.createTable(service, tableName, columnNames);
|
||||||
|
|
||||||
GDataRequest createTableRequest = FusionTableHandler.createFusionTablesPostRequest(
|
|
||||||
service, RequestType.INSERT, createQuery);
|
|
||||||
createTableRequest.execute();
|
|
||||||
|
|
||||||
List<List<String>> createTableResults =
|
|
||||||
FusionTableHandler.parseFusionTablesResults(createTableRequest);
|
|
||||||
if (createTableResults != null && createTableResults.size() == 2) {
|
|
||||||
tableId = createTableResults.get(1).get(0);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
tableId = null;
|
||||||
exceptions.add(e);
|
exceptions.add(e);
|
||||||
}
|
}
|
||||||
} else if (tableId != null) {
|
} else if (tableId != null) {
|
||||||
if (sbBatch == null) {
|
if (sbBatch == null) {
|
||||||
sbBatch = new StringBuffer();
|
sbBatch = new StringBuffer();
|
||||||
}
|
}
|
||||||
formulateInsert(cells, sbBatch);
|
formatCsv(cells, sbBatch);
|
||||||
|
|
||||||
rows++;
|
rows++;
|
||||||
if (rows % 20 == 0) {
|
if (rows % BATCH_SIZE == 0) {
|
||||||
sendBatch();
|
if (!sendBatch()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendBatch() {
|
private boolean sendBatch() {
|
||||||
try {
|
try {
|
||||||
GDataRequest createTableRequest = FusionTableHandler.createFusionTablesPostRequest(
|
// FIXME: text/csv doesn't work even though that's what the content is
|
||||||
service, RequestType.INSERT, sbBatch.toString());
|
AbstractInputStreamContent content = ByteArrayContent.fromString("application/octet-stream", sbBatch.toString());
|
||||||
createTableRequest.execute();
|
|
||||||
|
// AbstractInputStreamContent content = new InputStreamContent("application/octet-stream",
|
||||||
|
// // TODO: we really want to do GZIP compression here
|
||||||
|
// new ByteArrayInputStream(sbBatch.toString().getBytes("UTF-8")));
|
||||||
|
Long count = FusionTableHandler.insertRows(service, tableId, content);
|
||||||
|
if (count != BATCH_SIZE) {
|
||||||
|
exceptions.add(new IOException("only imported %d of %d rows"));
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
exceptions.add(e);
|
exceptions.add(e);
|
||||||
} catch (ServiceException e) {
|
if (e instanceof HttpResponseException) {
|
||||||
exceptions.add(e);
|
int code = ((HttpResponseException)e).getStatusCode();
|
||||||
|
if (code >= 400 && code < 500) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 500s appear to be retried automatically by li
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
sbBatch = null;
|
sbBatch = null;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void formatCsv(List<CellData> cells, StringBuffer sb) {
|
||||||
|
boolean first = true;
|
||||||
|
for (int i = 0; i < cells.size() && i < columnNames.size(); i++) {
|
||||||
|
CellData cellData = cells.get(i);
|
||||||
|
if (!first) {
|
||||||
|
sb.append(',');
|
||||||
|
} else {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
sb.append("\"");
|
||||||
|
if (cellData != null && cellData.text != null) {
|
||||||
|
sb.append(cellData.text.replaceAll("\"", "\\\\\""));
|
||||||
|
}
|
||||||
|
sb.append("\"");
|
||||||
|
}
|
||||||
|
sb.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Old-style SQL INSERT can be removed once we're sure importRows will work
|
||||||
private void formulateInsert(List<CellData> cells, StringBuffer sb) {
|
private void formulateInsert(List<CellData> cells, StringBuffer sb) {
|
||||||
StringBuffer sbColumnNames = new StringBuffer();
|
StringBuffer sbColumnNames = new StringBuffer();
|
||||||
StringBuffer sbValues = new StringBuffer();
|
StringBuffer sbValues = new StringBuffer();
|
||||||
|
@ -49,7 +49,9 @@ import org.json.JSONException;
|
|||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.json.JSONWriter;
|
import org.json.JSONWriter;
|
||||||
|
|
||||||
import com.google.gdata.client.GoogleService;
|
import com.google.api.services.fusiontables.Fusiontables;
|
||||||
|
import com.google.api.services.fusiontables.model.Table;
|
||||||
|
import com.google.api.services.fusiontables.model.TableList;
|
||||||
import com.google.gdata.client.docs.DocsService;
|
import com.google.gdata.client.docs.DocsService;
|
||||||
import com.google.gdata.client.spreadsheet.FeedURLFactory;
|
import com.google.gdata.client.spreadsheet.FeedURLFactory;
|
||||||
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
||||||
@ -59,6 +61,7 @@ import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
|
|||||||
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
|
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
|
||||||
import com.google.gdata.data.spreadsheet.WorksheetEntry;
|
import com.google.gdata.data.spreadsheet.WorksheetEntry;
|
||||||
import com.google.gdata.data.spreadsheet.WorksheetFeed;
|
import com.google.gdata.data.spreadsheet.WorksheetFeed;
|
||||||
|
import com.google.gdata.util.AuthenticationException;
|
||||||
import com.google.gdata.util.ServiceException;
|
import com.google.gdata.util.ServiceException;
|
||||||
|
|
||||||
import com.google.refine.ProjectManager;
|
import com.google.refine.ProjectManager;
|
||||||
@ -125,13 +128,15 @@ public class GDataImportingController implements ImportingController {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
listSpreadsheets(GDataExtension.getDocsService(token), writer);
|
listSpreadsheets(GDataExtension.getDocsService(token), writer);
|
||||||
listFusionTables(FusionTableHandler.getFusionTablesGoogleService(token), writer);
|
listFusionTables(FusionTableHandler.getFusionTablesService(token), writer);
|
||||||
|
} catch (AuthenticationException e) {
|
||||||
|
TokenCookie.deleteToken(request, response);
|
||||||
} catch (ServiceException e) {
|
} catch (ServiceException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
writer.endArray();
|
||||||
|
writer.endObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.endArray();
|
|
||||||
writer.endObject();
|
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
throw new ServletException(e);
|
throw new ServletException(e);
|
||||||
} finally {
|
} finally {
|
||||||
@ -167,27 +172,24 @@ public class GDataImportingController implements ImportingController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void listFusionTables(GoogleService service, JSONWriter writer)
|
private void listFusionTables(Fusiontables service, JSONWriter writer)
|
||||||
throws IOException, ServiceException, JSONException {
|
throws IOException, ServiceException, JSONException {
|
||||||
|
|
||||||
List<List<String>> rows = FusionTableHandler.listTables(service);
|
Fusiontables.Table.List listTables = service.table().list();
|
||||||
if (rows.size() > 1) { // excluding headers
|
TableList tablelist = listTables.execute();
|
||||||
for (int i = 1; i < rows.size(); i++) {
|
for (Table table : tablelist.getItems()) {
|
||||||
List<String> row = rows.get(i);
|
String id = table.getTableId();
|
||||||
if (row.size() >= 2) {
|
String name = table.getName();
|
||||||
String id = row.get(0);
|
String link = "https://www.google.com/fusiontables/DataSource?docid=" + id;
|
||||||
String name = row.get(1);
|
|
||||||
String link = row.get(2);
|
// Add JSON object to our stream
|
||||||
|
writer.object();
|
||||||
writer.object();
|
writer.key("docId"); writer.value(id);
|
||||||
writer.key("docId"); writer.value(id);
|
writer.key("docLink"); writer.value(link);
|
||||||
writer.key("docLink"); writer.value(link);
|
writer.key("docSelfLink"); writer.value(link);
|
||||||
writer.key("docSelfLink"); writer.value(link);
|
writer.key("title"); writer.value(name);
|
||||||
writer.key("title"); writer.value(name);
|
writer.key("type"); writer.value("table");
|
||||||
writer.key("type"); writer.value("table");
|
writer.endObject();
|
||||||
writer.endObject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,6 @@ import org.json.JSONWriter;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.gdata.client.GoogleService;
|
|
||||||
import com.google.gdata.client.docs.DocsService;
|
import com.google.gdata.client.docs.DocsService;
|
||||||
import com.google.gdata.client.spreadsheet.CellQuery;
|
import com.google.gdata.client.spreadsheet.CellQuery;
|
||||||
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
||||||
@ -292,8 +291,9 @@ public class UploadCommand extends Command {
|
|||||||
static private String uploadFusionTable(
|
static private String uploadFusionTable(
|
||||||
Project project, final Engine engine, final Properties params,
|
Project project, final Engine engine, final Properties params,
|
||||||
String token, String name, List<Exception> exceptions) {
|
String token, String name, List<Exception> exceptions) {
|
||||||
GoogleService service = FusionTableHandler.getFusionTablesGoogleService(token);
|
|
||||||
FusionTableSerializer serializer = new FusionTableSerializer(service, name, exceptions);
|
FusionTableSerializer serializer = new FusionTableSerializer(
|
||||||
|
FusionTableHandler.getFusionTablesService(token), name, exceptions);
|
||||||
|
|
||||||
CustomizableTabularExporterUtilities.exportRows(
|
CustomizableTabularExporterUtilities.exportRows(
|
||||||
project, engine, params, serializer);
|
project, engine, params, serializer);
|
||||||
|
Loading…
Reference in New Issue
Block a user