The file system coupled method getProjectDirectory is now removed from ProjectManager.

Methods of HistoryEntry which directly work with the File System have been moved to FileHistoryEntry in the io directory, and HistoryEntry made abstract.

As the abstract HistoryEntry cannot be instantiated directly, the ProjectManager is now responsible for creating new HistoryEntry.

git-svn-id: http://google-refine.googlecode.com/svn/trunk@973 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
Iain Sproat 2010-06-15 22:11:35 +00:00
parent b07075bed5
commit 17f1dc2e6f
25 changed files with 658 additions and 591 deletions

View File

@ -1,6 +1,6 @@
package com.metaweb.gridworks;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -8,6 +8,9 @@ import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.metaweb.gridworks.history.Change;
import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.AbstractOperation;
import com.metaweb.gridworks.model.Project;
@ -44,9 +47,6 @@ public abstract class ProjectManager {
return _interProjectModel;
}
//FIXME this is File System specific, need to remove from this abstract class
public abstract File getProjectDir(long id);
public void registerProject(Project project, ProjectMetadata projectMetadata) {
synchronized (this) {
_projects.put(project.id, project);
@ -119,4 +119,6 @@ public abstract class ProjectManager {
public abstract void deleteProject(long projectID) ;
public abstract HistoryEntry createHistoryEntry(long id, long projectID, String description, AbstractOperation operation, Date time);
public abstract HistoryEntry createHistoryEntry(long id, Project project, String description, AbstractOperation operation, Change change);
}

View File

@ -10,6 +10,7 @@ import javax.servlet.http.HttpServletResponse;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.commands.Command;
import com.metaweb.gridworks.history.Change;
import com.metaweb.gridworks.history.HistoryEntry;
@ -25,20 +26,20 @@ public class EditOneCellCommand extends Command {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
Project project = getProject(request);
int rowIndex = Integer.parseInt(request.getParameter("row"));
int cellIndex = Integer.parseInt(request.getParameter("cell"));
String type = request.getParameter("type");
String valueString = request.getParameter("value");
Serializable value = null;
if ("number".equals(type)) {
value = Double.parseDouble(valueString);
} else if ("boolean".equals(type)) {
@ -50,13 +51,13 @@ public class EditOneCellCommand extends Command {
}
EditOneCellProcess process = new EditOneCellProcess(
project,
project,
"Edit single cell",
rowIndex,
cellIndex,
rowIndex,
cellIndex,
value
);
HistoryEntry historyEntry = project.processManager.queueProcess(process);
if (historyEntry != null) {
/*
@ -64,11 +65,11 @@ public class EditOneCellCommand extends Command {
* so the client side can update the cell's rendering right away.
*/
JSONWriter writer = new JSONWriter(response.getWriter());
Pool pool = new Pool();
Properties options = new Properties();
options.put("pool", pool);
writer.object();
writer.key("code"); writer.value("ok");
writer.key("historyEntry"); historyEntry.write(writer, options);
@ -82,22 +83,22 @@ public class EditOneCellCommand extends Command {
respondException(response, e);
}
}
protected static class EditOneCellProcess extends QuickHistoryEntryProcess {
final int rowIndex;
final int cellIndex;
final Serializable value;
Cell newCell;
EditOneCellProcess(
Project project,
String briefDescription,
int rowIndex,
int cellIndex,
Project project,
String briefDescription,
int rowIndex,
int cellIndex,
Serializable value
) {
super(project, briefDescription);
this.rowIndex = rowIndex;
this.cellIndex = cellIndex;
this.value = value;
@ -109,19 +110,19 @@ public class EditOneCellCommand extends Command {
if (column == null) {
throw new Exception("No such column");
}
newCell = new Cell(
value,
value,
cell != null ? cell.recon : null
);
String description =
"Edit single cell on row " + (rowIndex + 1) +
String description =
"Edit single cell on row " + (rowIndex + 1) +
", column " + column.getName();
Change change = new CellChange(rowIndex, cellIndex, cell, newCell);
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID, _project, description, null, change);
}
}

View File

@ -15,6 +15,7 @@ import org.apache.tools.tar.TarOutputStream;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.commands.Command;
import com.metaweb.gridworks.io.FileProjectManager;
import com.metaweb.gridworks.model.Project;
public class ExportProjectCommand extends Command {
@ -22,17 +23,17 @@ public class ExportProjectCommand extends Command {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
Project project = getProject(request);
ProjectManager.singleton.ensureProjectSaved(project.id);
response.setHeader("Content-Type", "application/x-gzip");
OutputStream os = response.getOutputStream();
try {
gzipTarToOutputStream(
ProjectManager.singleton.getProjectDir(project.id),
gzipTarToOutputStream(//FIXME relies on FileProjectManager
((FileProjectManager)ProjectManager.singleton).getProjectDir(project.id),
os
);
} finally {
@ -42,7 +43,7 @@ public class ExportProjectCommand extends Command {
respondException(response, e);
}
}
protected void gzipTarToOutputStream(File dir, OutputStream os) throws IOException {
GZIPOutputStream gos = new GZIPOutputStream(os);
try {
@ -51,7 +52,7 @@ public class ExportProjectCommand extends Command {
gos.close();
}
}
protected void tarToOutputStream(File dir, OutputStream os) throws IOException {
TarOutputStream tos = new TarOutputStream(os);
try {
@ -60,43 +61,43 @@ public class ExportProjectCommand extends Command {
tos.close();
}
}
protected void tarDir(String relative, File dir, TarOutputStream tos) throws IOException {
File[] files = dir.listFiles();
for (File file : files) {
if (!file.isHidden()) {
String path = relative + file.getName();
if (file.isDirectory()) {
tarDir(path + File.separator, file, tos);
} else {
TarEntry entry = new TarEntry(path);
entry.setMode(TarEntry.DEFAULT_FILE_MODE);
entry.setSize(file.length());
entry.setModTime(file.lastModified());
tos.putNextEntry(entry);
copyFile(file, tos);
tos.closeEntry();
}
}
}
}
protected void copyFile(File file, OutputStream os) throws IOException {
final int buffersize = 4096;
FileInputStream fis = new FileInputStream(file);
try {
byte[] buf = new byte[buffersize];
int count;
while((count = fis.read(buf, 0, buffersize)) != -1) {
os.write(buf, 0, count);
}
os.write(buf, 0, count);
}
} finally {
fis.close();
}

View File

@ -25,28 +25,29 @@ import org.slf4j.LoggerFactory;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.ProjectMetadata;
import com.metaweb.gridworks.commands.Command;
import com.metaweb.gridworks.io.FileProjectManager;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.util.ParsingUtilities;
public class ImportProjectCommand extends Command {
final static Logger logger = LoggerFactory.getLogger("import-project_command");
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ProjectManager.singleton.setBusy(true);
try {
Properties options = ParsingUtilities.parseUrlParameters(request);
long projectID = Project.generateID();
logger.info("Importing existing project using new ID {}", projectID);
internalImport(request, options, projectID);
ProjectManager.singleton.importProject(projectID);
ProjectMetadata pm = ProjectManager.singleton.getProjectMetadata(projectID);
if (pm != null) {
if (options.containsKey("project-name")) {
@ -55,7 +56,7 @@ public class ImportProjectCommand extends Command {
pm.setName(projectName);
}
}
redirect(response, "/project.html?project=" + projectID);
} else {
redirect(response, "/error.html?redirect=index.html&msg=" +
@ -68,17 +69,17 @@ public class ImportProjectCommand extends Command {
ProjectManager.singleton.setBusy(false);
}
}
protected void internalImport(
HttpServletRequest request,
Properties options,
long projectID
) throws Exception {
String url = null;
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
@ -98,13 +99,13 @@ public class ImportProjectCommand extends Command {
stream.close();
}
}
}
}
if (url != null && url.length() > 0) {
internalImportURL(request, options, projectID, url);
}
}
protected void internalImportURL(
HttpServletRequest request,
Properties options,
@ -113,7 +114,7 @@ public class ImportProjectCommand extends Command {
) throws Exception {
URL url = new URL(urlString);
URLConnection connection = null;
try {
connection = url.openConnection();
connection.setConnectTimeout(5000);
@ -121,25 +122,25 @@ public class ImportProjectCommand extends Command {
} catch (Exception e) {
throw new Exception("Cannot connect to " + urlString, e);
}
InputStream inputStream = null;
try {
inputStream = connection.getInputStream();
} catch (Exception e) {
throw new Exception("Cannot retrieve content from " + url, e);
}
try {
internalImportInputStream(projectID, inputStream, !urlString.endsWith(".tar"));
} finally {
inputStream.close();
}
}
protected void internalImportInputStream(long projectID, InputStream inputStream, boolean gziped) throws IOException {
File destDir = ProjectManager.singleton.getProjectDir(projectID);
File destDir = ((FileProjectManager)ProjectManager.singleton).getProjectDir(projectID);//FIXME relies on FileProjectManager
destDir.mkdirs();
if (gziped) {
GZIPInputStream gis = new GZIPInputStream(inputStream);
untar(destDir, gis);
@ -147,19 +148,19 @@ public class ImportProjectCommand extends Command {
untar(destDir, inputStream);
}
}
protected void untar(File destDir, InputStream inputStream) throws IOException {
TarInputStream tin = new TarInputStream(inputStream);
TarEntry tarEntry = null;
while ((tarEntry = tin.getNextEntry()) != null) {
File destEntry = new File(destDir, tarEntry.getName());
File parent = destEntry.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
if (tarEntry.isDirectory()) {
destEntry.mkdirs();
} else {

View File

@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletResponse;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.commands.Command;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.history.Change;
@ -29,19 +30,19 @@ public class ReconJudgeOneCellCommand extends Command {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
Project project = getProject(request);
int rowIndex = Integer.parseInt(request.getParameter("row"));
int cellIndex = Integer.parseInt(request.getParameter("cell"));
Judgment judgment = Recon.stringToJudgment(request.getParameter("judgment"));
ReconCandidate match = null;
String topicID = request.getParameter("topicID");
if (topicID != null) {
String scoreString = request.getParameter("score");
match = new ReconCandidate(
topicID,
request.getParameter("topicGUID"),
@ -50,16 +51,16 @@ public class ReconJudgeOneCellCommand extends Command {
scoreString != null ? Double.parseDouble(scoreString) : 100
);
}
JudgeOneCellProcess process = new JudgeOneCellProcess(
project,
project,
"Judge one cell's recon result",
judgment,
rowIndex,
cellIndex,
rowIndex,
cellIndex,
match
);
HistoryEntry historyEntry = project.processManager.queueProcess(process);
if (historyEntry != null) {
/*
@ -67,11 +68,11 @@ public class ReconJudgeOneCellCommand extends Command {
* client side can update its UI right away.
*/
JSONWriter writer = new JSONWriter(response.getWriter());
Pool pool = new Pool();
Properties options = new Properties();
options.put("pool", pool);
writer.object();
writer.key("code"); writer.value("ok");
writer.key("historyEntry"); historyEntry.write(writer, options);
@ -85,7 +86,7 @@ public class ReconJudgeOneCellCommand extends Command {
respondException(response, e);
}
}
protected static class JudgeOneCellProcess extends QuickHistoryEntryProcess {
final int rowIndex;
@ -93,17 +94,17 @@ public class ReconJudgeOneCellCommand extends Command {
final Judgment judgment;
final ReconCandidate match;
Cell newCell;
JudgeOneCellProcess(
Project project,
String briefDescription,
Judgment judgment,
int rowIndex,
int cellIndex,
Project project,
String briefDescription,
Judgment judgment,
int rowIndex,
int cellIndex,
ReconCandidate match
) {
super(project, briefDescription);
this.judgment = judgment;
this.rowIndex = rowIndex;
this.cellIndex = cellIndex;
@ -115,63 +116,63 @@ public class ReconJudgeOneCellCommand extends Command {
if (cell == null || !ExpressionUtils.isNonBlankData(cell.value)) {
throw new Exception("Cell is blank or error");
}
Column column = _project.columnModel.getColumnByCellIndex(cellIndex);
if (column == null) {
throw new Exception("No such column");
}
Judgment oldJudgment = cell.recon == null ? Judgment.None : cell.recon.judgment;
newCell = new Cell(
cell.value,
cell.value,
cell.recon == null ? new Recon(historyEntryID) : cell.recon.dup(historyEntryID)
);
String cellDescription =
"single cell on row " + (rowIndex + 1) +
", column " + column.getName() +
String cellDescription =
"single cell on row " + (rowIndex + 1) +
", column " + column.getName() +
", containing \"" + cell.value + "\"";
String description = null;
newCell.recon.matchRank = -1;
newCell.recon.judgmentAction = "single";
newCell.recon.judgmentBatchSize = 1;
if (judgment == Judgment.None) {
newCell.recon.judgment = Recon.Judgment.None;
newCell.recon.match = null;
description = "Discard recon judgment for " + cellDescription;
} else if (judgment == Judgment.New) {
newCell.recon.judgment = Recon.Judgment.New;
newCell.recon.match = null;
description = "Mark to create new topic for " + cellDescription;
} else {
newCell.recon.judgment = Recon.Judgment.Matched;
newCell.recon.match = this.match;
for (int m = 0; m < newCell.recon.candidates.size(); m++) {
if (newCell.recon.candidates.get(m).topicGUID.equals(this.match.topicGUID)) {
newCell.recon.matchRank = m;
break;
}
}
description = "Match " + this.match.topicName +
" (" + match.topicID + ") to " +
" (" + match.topicID + ") to " +
cellDescription;
}
ReconStats stats = column.getReconStats();
if (stats == null) {
stats = ReconStats.create(_project, cellIndex);
} else {
int newChange = 0;
int matchChange = 0;
if (oldJudgment == Judgment.New) {
newChange--;
}
@ -184,21 +185,21 @@ public class ReconJudgeOneCellCommand extends Command {
if (newCell.recon.judgment == Judgment.Matched) {
matchChange++;
}
stats = new ReconStats(
stats.nonBlanks,
stats.newTopics + newChange,
stats.nonBlanks,
stats.newTopics + newChange,
stats.matchedTopics + matchChange);
}
Change change = new ReconChange(
new CellChange(rowIndex, cellIndex, cell, newCell),
column.getName(),
new CellChange(rowIndex, cellIndex, cell, newCell),
column.getName(),
column.getReconConfig(),
stats
);
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID, _project, description, null, change);
}
}

View File

@ -6,6 +6,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.commands.Command;
import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.Project;
@ -17,27 +18,27 @@ public class AnnotateOneRowCommand extends Command {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json");
try {
Project project = getProject(request);
int rowIndex = Integer.parseInt(request.getParameter("row"));
String starredString = request.getParameter("starred");
if (starredString != null) {
boolean starred = "true".endsWith(starredString);
String description = (starred ? "Star row " : "Unstar row ") + (rowIndex + 1);
String description = (starred ? "Star row " : "Unstar row ") + (rowIndex + 1);
StarOneRowProcess process = new StarOneRowProcess(
project,
project,
description,
rowIndex,
rowIndex,
starred
);
performProcessAndRespond(request, response, project, process);
return;
}
@ -45,48 +46,48 @@ public class AnnotateOneRowCommand extends Command {
String flaggedString = request.getParameter("flagged");
if (flaggedString != null) {
boolean flagged = "true".endsWith(flaggedString);
String description = (flagged ? "Flag row " : "Unflag row ") + (rowIndex + 1);
String description = (flagged ? "Flag row " : "Unflag row ") + (rowIndex + 1);
FlagOneRowProcess process = new FlagOneRowProcess(
project,
project,
description,
rowIndex,
rowIndex,
flagged
);
performProcessAndRespond(request, response, project, process);
return;
}
respond(response, "{ \"code\" : \"error\", \"message\" : \"invalid command parameters\" }");
} catch (Exception e) {
respondException(response, e);
}
}
protected static class StarOneRowProcess extends QuickHistoryEntryProcess {
final int rowIndex;
final boolean starred;
StarOneRowProcess(
Project project,
String briefDescription,
int rowIndex,
Project project,
String briefDescription,
int rowIndex,
boolean starred
) {
super(project, briefDescription);
this.rowIndex = rowIndex;
this.starred = starred;
}
protected HistoryEntry createHistoryEntry(long historyEntryID) throws Exception {
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID,
_project,
(starred ? "Star row " : "Unstar row ") + (rowIndex + 1),
null,
_project,
(starred ? "Star row " : "Unstar row ") + (rowIndex + 1),
null,
new RowStarChange(rowIndex, starred)
);
}
@ -94,25 +95,25 @@ public class AnnotateOneRowCommand extends Command {
protected static class FlagOneRowProcess extends QuickHistoryEntryProcess {
final int rowIndex;
final boolean flagged;
FlagOneRowProcess(
Project project,
String briefDescription,
int rowIndex,
Project project,
String briefDescription,
int rowIndex,
boolean flagged
) {
super(project, briefDescription);
this.rowIndex = rowIndex;
this.flagged = flagged;
}
protected HistoryEntry createHistoryEntry(long historyEntryID) throws Exception {
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID,
_project,
(flagged ? "Flag row " : "Unflag row ") + (rowIndex + 1),
null,
_project,
(flagged ? "Flag row " : "Unflag row ") + (rowIndex + 1),
null,
new RowFlagChange(rowIndex, flagged)
);
}

View File

@ -1,14 +1,8 @@
package com.metaweb.gridworks.history;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.Writer;
import java.util.Date;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import org.json.JSONException;
import org.json.JSONObject;
@ -20,40 +14,39 @@ import com.metaweb.gridworks.model.AbstractOperation;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.operations.OperationRegistry;
import com.metaweb.gridworks.util.ParsingUtilities;
import com.metaweb.gridworks.util.Pool;
/**
* This is the metadata of a Change. It's small, so we can load it in order to
* obtain information about a change without actually loading the change.
*/
public class HistoryEntry implements Jsonizable {
public abstract class HistoryEntry implements Jsonizable {
final public long id;
final public long projectID;
final public String description;
final public Date time;
// the abstract operation, if any, that results in the change
final public AbstractOperation operation;
final public AbstractOperation operation;
// the actual change, loaded on demand
transient protected Change _change;
private final static String OPERATION = "operation";
static public long allocateID() {
return Math.round(Math.random() * 1000000) + System.currentTimeMillis();
}
public HistoryEntry(long id, Project project, String description, AbstractOperation operation, Change change) {
this.id = id;
this.projectID = project.id;
this.description = description;
this.operation = operation;
this.time = new Date();
_change = change;
}
protected HistoryEntry(long id, long projectID, String description, AbstractOperation operation, Date time) {
this.id = id;
this.projectID = projectID;
@ -61,10 +54,10 @@ public class HistoryEntry implements Jsonizable {
this.operation = operation;
this.time = time;
}
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("id"); writer.value(id);
writer.key("description"); writer.value(description);
@ -74,62 +67,54 @@ public class HistoryEntry implements Jsonizable {
}
writer.endObject();
}
public void apply(Project project) {
if (_change == null) {
loadChange();
}
synchronized (project) {
_change.apply(project);
// When a change is applied, it can hang on to old data (in order to be able
// to revert later). Hence, we need to save the change out.
try {
saveChange();
} catch (Exception e) {
e.printStackTrace();
_change.revert(project);
throw new RuntimeException("Failed to apply change", e);
}
}
}
public void revert(Project project) {
if (_change == null) {
loadChange();
}
_change.revert(project);
}
public void delete() {
File file = getChangeFile();
if (file.exists()) {
file.delete();
}
}
public void save(Writer writer, Properties options) {
JSONWriter jsonWriter = new JSONWriter(writer);
try {
write(jsonWriter, options);
} catch (JSONException e) {
e.printStackTrace();
}
}
public abstract void loadChange();
protected abstract void saveChange() throws Exception;
public abstract void save(Writer writer, Properties options);
protected abstract void delete();
static public HistoryEntry load(Project project, String s) throws Exception {
JSONObject obj = ParsingUtilities.evaluateJsonStringToObject(s);
AbstractOperation operation = null;
if (obj.has(OPERATION) && !obj.isNull(OPERATION)) {
operation = OperationRegistry.reconstruct(project, obj.getJSONObject(OPERATION));
}
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
obj.getLong("id"),
project.id,
obj.getString("description"),
@ -138,72 +123,6 @@ public class HistoryEntry implements Jsonizable {
);
}
protected void loadChange() {
File changeFile = getChangeFile();
try {
loadChange(changeFile);
} catch (Exception e) {
throw new RuntimeException("Failed to load change file " + changeFile.getAbsolutePath(), e);
}
}
protected void loadChange(File file) throws Exception {
ZipFile zipFile = new ZipFile(file);
try {
Pool pool = new Pool();
ZipEntry poolEntry = zipFile.getEntry("pool.txt");
if (poolEntry != null) {
pool.load(new InputStreamReader(
zipFile.getInputStream(poolEntry)));
} // else, it's a legacy project file
_change = History.readOneChange(
zipFile.getInputStream(zipFile.getEntry("change.txt")), pool);
} finally {
zipFile.close();
}
}
protected void saveChange() throws Exception {
File changeFile = getChangeFile();
if (!(changeFile.exists())) {
saveChange(changeFile);
}
}
protected void saveChange(File file) throws Exception {
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(file));
try {
Pool pool = new Pool();
out.putNextEntry(new ZipEntry("change.txt"));
try {
History.writeOneChange(out, _change, pool);
} finally {
out.closeEntry();
}
out.putNextEntry(new ZipEntry("pool.txt"));
try {
pool.save(out);
} finally {
out.closeEntry();
}
} finally {
out.close();
}
}
protected File getChangeFile() {
return new File(getHistoryDir(), id + ".change.zip");
}
protected File getHistoryDir() {
File dir = new File(ProjectManager.singleton.getProjectDir(projectID), "history");
dir.mkdirs();
return dir;
}
}

View File

@ -0,0 +1,116 @@
package com.metaweb.gridworks.io;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import java.io.Writer;
import java.util.Date;
import org.json.JSONException;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.history.Change;
import com.metaweb.gridworks.history.History;
import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.AbstractOperation;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.util.Pool;
public class FileHistoryEntry extends HistoryEntry{
protected FileHistoryEntry(long id, long projectID, String description, AbstractOperation operation, Date time) {
super(id, projectID, description, operation, time);
}
protected FileHistoryEntry(long id, Project project, String description, AbstractOperation operation, Change change){
super(id, project, description, operation, change);
}
protected void delete() {
File file = getChangeFile();
if (file.exists()) {
file.delete();
}
}
public void save(Writer writer, Properties options) {
JSONWriter jsonWriter = new JSONWriter(writer);
try {
write(jsonWriter, options);
} catch (JSONException e) {
e.printStackTrace();
}
}
public void loadChange() {
File changeFile = getChangeFile();
try {
loadChange(changeFile);
} catch (Exception e) {
throw new RuntimeException("Failed to load change file " + changeFile.getAbsolutePath(), e);
}
}
protected void loadChange(File file) throws Exception {
ZipFile zipFile = new ZipFile(file);
try {
Pool pool = new Pool();
ZipEntry poolEntry = zipFile.getEntry("pool.txt");
if (poolEntry != null) {
pool.load(new InputStreamReader(
zipFile.getInputStream(poolEntry)));
} // else, it's a legacy project file
_change = History.readOneChange(
zipFile.getInputStream(zipFile.getEntry("change.txt")), pool);
} finally {
zipFile.close();
}
}
protected void saveChange() throws Exception {
File changeFile = getChangeFile();
if (!(changeFile.exists())) {
saveChange(changeFile);
}
}
protected void saveChange(File file) throws Exception {
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(file));
try {
Pool pool = new Pool();
out.putNextEntry(new ZipEntry("change.txt"));
try {
History.writeOneChange(out, _change, pool);
} finally {
out.closeEntry();
}
out.putNextEntry(new ZipEntry("pool.txt"));
try {
pool.save(out);
} finally {
out.closeEntry();
}
} finally {
out.close();
}
}
protected File getChangeFile() {
return new File(getHistoryDir(), id + ".change.zip");
}
protected File getHistoryDir() {//FIXME relies on FileProjectManager
File dir = new File(((FileProjectManager)ProjectManager.singleton).getProjectDir(projectID), "history");
dir.mkdirs();
return dir;
}
}

View File

@ -22,6 +22,9 @@ import org.slf4j.LoggerFactory;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.ProjectMetadata;
import com.metaweb.gridworks.history.Change;
import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.AbstractOperation;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.util.JSONUtilities;
@ -351,4 +354,11 @@ public class FileProjectManager extends ProjectManager{
return found;
}
public HistoryEntry createHistoryEntry(long id, long projectID, String description, AbstractOperation operation, Date time){
return new FileHistoryEntry(id, projectID, description, operation, time);
}
public HistoryEntry createHistoryEntry(long id, Project project, String description, AbstractOperation operation, Change change){
return new FileHistoryEntry(id, project, description, operation, change);
}
}

View File

@ -23,7 +23,7 @@ public class ProjectUtilities {
synchronized public static void save(Project project) {
synchronized (project) {
long id = project.id;
File dir = ProjectManager.singleton.getProjectDir(id);
File dir = ((FileProjectManager)ProjectManager.singleton).getProjectDir(id);
File tempFile = new File(dir, "data.temp.zip");
try {

View File

@ -5,6 +5,7 @@ import java.util.List;
import org.json.JSONObject;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.browsing.Engine;
import com.metaweb.gridworks.browsing.FilteredRows;
import com.metaweb.gridworks.browsing.RowVisitor;
@ -18,7 +19,7 @@ import com.metaweb.gridworks.model.changes.MassCellChange;
abstract public class EngineDependentMassCellOperation extends EngineDependentOperation {
final protected String _columnName;
final protected boolean _updateRowContextDependencies;
protected EngineDependentMassCellOperation(
JSONObject engineConfig, String columnName, boolean updateRowContextDependencies) {
super(engineConfig);
@ -28,32 +29,32 @@ abstract public class EngineDependentMassCellOperation extends EngineDependentOp
protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception {
Engine engine = createEngine(project);
Column column = project.columnModel.getColumnByName(_columnName);
if (column == null) {
throw new Exception("No column named " + _columnName);
}
List<CellChange> cellChanges = new ArrayList<CellChange>(project.rows.size());
FilteredRows filteredRows = engine.getAllFilteredRows();
try {
filteredRows.accept(project, createRowVisitor(project, cellChanges, historyEntryID));
} catch (Exception e) {
e.printStackTrace();
}
String description = createDescription(column, cellChanges);
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID, project, description, this, createChange(project, column, cellChanges));
}
protected Change createChange(Project project, Column column, List<CellChange> cellChanges) {
return new MassCellChange(
cellChanges, column.getName(), _updateRowContextDependencies);
}
abstract protected RowVisitor createRowVisitor(Project project, List<CellChange> cellChanges, long historyEntryID) throws Exception;
abstract protected String createDescription(Column column, List<CellChange> cellChanges);
}

View File

@ -9,6 +9,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.history.Change;
import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.AbstractOperation;
@ -19,20 +20,20 @@ import com.metaweb.gridworks.util.Pool;
public class SaveProtographOperation extends AbstractOperation {
final protected Protograph _protograph;
static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception {
return new SaveProtographOperation(
Protograph.reconstruct(obj.getJSONObject("protograph"))
);
}
public SaveProtographOperation(Protograph protograph) {
_protograph = protograph;
}
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("Save protograph");
@ -47,20 +48,20 @@ public class SaveProtographOperation extends AbstractOperation {
@Override
protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception {
String description = "Save schema-alignment protograph";
Change change = new ProtographChange(_protograph);
return new HistoryEntry(historyEntryID, project, description, SaveProtographOperation.this, change);
return ProjectManager.singleton.createHistoryEntry(historyEntryID, project, description, SaveProtographOperation.this, change);
}
static public class ProtographChange implements Change {
final protected Protograph _newProtograph;
protected Protograph _oldProtograph;
public ProtographChange(Protograph protograph) {
_newProtograph = protograph;
}
public void apply(Project project) {
synchronized (project) {
_oldProtograph = project.protograph;
@ -73,36 +74,36 @@ public class SaveProtographOperation extends AbstractOperation {
project.protograph = _oldProtograph;
}
}
public void save(Writer writer, Properties options) throws IOException {
writer.write("newProtograph="); writeProtograph(_newProtograph, writer); writer.write('\n');
writer.write("oldProtograph="); writeProtograph(_oldProtograph, writer); writer.write('\n');
writer.write("/ec/\n"); // end of change marker
}
static public Change load(LineNumberReader reader, Pool pool) throws Exception {
Protograph oldProtograph = null;
Protograph newProtograph = null;
String line;
while ((line = reader.readLine()) != null && !"/ec/".equals(line)) {
int equal = line.indexOf('=');
CharSequence field = line.subSequence(0, equal);
String value = line.substring(equal + 1);
if ("oldProtograph".equals(field) && value.length() > 0) {
oldProtograph = Protograph.reconstruct(ParsingUtilities.evaluateJsonStringToObject(value));
} else if ("newProtograph".equals(field) && value.length() > 0) {
newProtograph = Protograph.reconstruct(ParsingUtilities.evaluateJsonStringToObject(value));
}
}
ProtographChange change = new ProtographChange(newProtograph);
change._oldProtograph = oldProtograph;
return change;
}
static protected void writeProtograph(Protograph p, Writer writer) throws IOException {
if (p != null) {
JSONWriter jsonWriter = new JSONWriter(writer);
@ -113,5 +114,5 @@ public class SaveProtographOperation extends AbstractOperation {
}
}
}
}
}
}

View File

@ -8,6 +8,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.AbstractOperation;
@ -30,7 +31,7 @@ public class MultiValuedCellJoinOperation extends AbstractOperation {
obj.getString("separator")
);
}
public MultiValuedCellJoinOperation(
String columnName,
String keyColumnName,
@ -43,7 +44,7 @@ public class MultiValuedCellJoinOperation extends AbstractOperation {
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(getBriefDescription(null));
@ -52,7 +53,7 @@ public class MultiValuedCellJoinOperation extends AbstractOperation {
writer.key("separator"); writer.value(_separator);
writer.endObject();
}
protected String getBriefDescription(Project project) {
return "Join multi-valued cells in column " + _columnName;
}
@ -63,34 +64,34 @@ public class MultiValuedCellJoinOperation extends AbstractOperation {
throw new Exception("No column named " + _columnName);
}
int cellIndex = column.getCellIndex();
Column keyColumn = project.columnModel.getColumnByName(_keyColumnName);
if (keyColumn == null) {
throw new Exception("No key column named " + _keyColumnName);
}
int keyCellIndex = keyColumn.getCellIndex();
List<Row> newRows = new ArrayList<Row>();
int oldRowCount = project.rows.size();
for (int r = 0; r < oldRowCount; r++) {
Row oldRow = project.rows.get(r);
if (oldRow.isCellBlank(keyCellIndex)) {
newRows.add(oldRow.dup());
continue;
}
int r2 = r + 1;
while (r2 < oldRowCount && project.rows.get(r2).isCellBlank(keyCellIndex)) {
r2++;
}
if (r2 == r + 1) {
newRows.add(oldRow.dup());
continue;
}
StringBuffer sb = new StringBuffer();
for (int r3 = r; r3 < r2; r3++) {
Object value = project.rows.get(r3).getCellValue(cellIndex);
@ -101,7 +102,7 @@ public class MultiValuedCellJoinOperation extends AbstractOperation {
sb.append(value.toString());
}
}
for (int r3 = r; r3 < r2; r3++) {
Row newRow = project.rows.get(r3).dup();
if (r3 == r) {
@ -109,20 +110,20 @@ public class MultiValuedCellJoinOperation extends AbstractOperation {
} else {
newRow.setCell(cellIndex, null);
}
if (!newRow.isEmpty()) {
newRows.add(newRow);
}
}
r = r2 - 1; // r will be incremented by the for loop anyway
}
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID,
project,
getBriefDescription(null),
this,
project,
getBriefDescription(null),
this,
new MassRowChange(newRows)
);
}

View File

@ -9,6 +9,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.AbstractOperation;
import com.metaweb.gridworks.model.Cell;
@ -32,7 +33,7 @@ public class MultiValuedCellSplitOperation extends AbstractOperation {
obj.getString("mode")
);
}
public MultiValuedCellSplitOperation(
String columnName,
String keyColumnName,
@ -47,7 +48,7 @@ public class MultiValuedCellSplitOperation extends AbstractOperation {
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("Split multi-valued cells in column " + _columnName);
@ -69,15 +70,15 @@ public class MultiValuedCellSplitOperation extends AbstractOperation {
throw new Exception("No column named " + _columnName);
}
int cellIndex = column.getCellIndex();
Column keyColumn = project.columnModel.getColumnByName(_keyColumnName);
if (keyColumn == null) {
throw new Exception("No key column named " + _keyColumnName);
}
int keyCellIndex = keyColumn.getCellIndex();
List<Row> newRows = new ArrayList<Row>();
int oldRowCount = project.rows.size();
for (int r = 0; r < oldRowCount; r++) {
Row oldRow = project.rows.get(r);
@ -85,7 +86,7 @@ public class MultiValuedCellSplitOperation extends AbstractOperation {
newRows.add(oldRow.dup());
continue;
}
Object value = oldRow.getCellValue(cellIndex);
String s = value instanceof String ? ((String) value) : value.toString();
String[] values = null;
@ -94,53 +95,53 @@ public class MultiValuedCellSplitOperation extends AbstractOperation {
} else {
values = StringUtils.splitByWholeSeparator(s, _separator);
}
if (values.length < 2) {
newRows.add(oldRow.dup());
continue;
}
// First value goes into the same row
{
Row firstNewRow = oldRow.dup();
firstNewRow.setCell(cellIndex, new Cell(values[0].trim(), null));
newRows.add(firstNewRow);
}
int r2 = r + 1;
for (int v = 1; v < values.length; v++) {
Cell newCell = new Cell(values[v].trim(), null);
if (r2 < project.rows.size()) {
Row oldRow2 = project.rows.get(r2);
if (oldRow2.isCellBlank(cellIndex) &&
if (oldRow2.isCellBlank(cellIndex) &&
oldRow2.isCellBlank(keyCellIndex)) {
Row newRow = oldRow2.dup();
newRow.setCell(cellIndex, newCell);
newRows.add(newRow);
r2++;
continue;
}
}
Row newRow = new Row(cellIndex + 1);
newRow.setCell(cellIndex, newCell);
newRows.add(newRow);
}
r = r2 - 1; // r will be incremented by the for loop anyway
}
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID,
project,
getBriefDescription(null),
this,
project,
getBriefDescription(null),
this,
new MassRowChange(newRows)
);
}

View File

@ -9,6 +9,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.browsing.Engine;
import com.metaweb.gridworks.browsing.FilteredRows;
import com.metaweb.gridworks.browsing.RowVisitor;
@ -34,13 +35,13 @@ public class ColumnAdditionOperation extends EngineDependentOperation {
final protected String _baseColumnName;
final protected String _expression;
final protected OnError _onError;
final protected String _newColumnName;
final protected int _columnInsertIndex;
static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception {
JSONObject engineConfig = obj.getJSONObject("engineConfig");
return new ColumnAdditionOperation(
engineConfig,
obj.getString("baseColumnName"),
@ -50,28 +51,28 @@ public class ColumnAdditionOperation extends EngineDependentOperation {
obj.getInt("columnInsertIndex")
);
}
public ColumnAdditionOperation(
JSONObject engineConfig,
String baseColumnName,
String expression,
OnError onError,
String newColumnName,
int columnInsertIndex
String newColumnName,
int columnInsertIndex
) {
super(engineConfig);
_baseColumnName = baseColumnName;
_expression = expression;
_onError = onError;
_newColumnName = newColumnName;
_columnInsertIndex = columnInsertIndex;
}
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(getBriefDescription(null));
@ -85,52 +86,52 @@ public class ColumnAdditionOperation extends EngineDependentOperation {
}
protected String getBriefDescription(Project project) {
return "Create column " + _newColumnName +
" at index " + _columnInsertIndex +
" based on column " + _baseColumnName +
return "Create column " + _newColumnName +
" at index " + _columnInsertIndex +
" based on column " + _baseColumnName +
" using expression " + _expression;
}
protected String createDescription(Column column, List<CellAtRow> cellsAtRows) {
return "Create new column " + _newColumnName +
" based on column " + column.getName() +
return "Create new column " + _newColumnName +
" based on column " + column.getName() +
" by filling " + cellsAtRows.size() +
" rows with " + _expression;
}
protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception {
Engine engine = createEngine(project);
Column column = project.columnModel.getColumnByName(_baseColumnName);
if (column == null) {
throw new Exception("No column named " + _baseColumnName);
}
List<CellAtRow> cellsAtRows = new ArrayList<CellAtRow>(project.rows.size());
FilteredRows filteredRows = engine.getAllFilteredRows();
filteredRows.accept(project, createRowVisitor(project, cellsAtRows));
String description = createDescription(column, cellsAtRows);
Change change = new ColumnAdditionChange(_newColumnName, _columnInsertIndex, cellsAtRows);
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID, project, description, this, change);
}
protected RowVisitor createRowVisitor(Project project, List<CellAtRow> cellsAtRows) throws Exception {
Column column = project.columnModel.getColumnByName(_baseColumnName);
Evaluable eval = MetaParser.parse(_expression);
Properties bindings = ExpressionUtils.createBindings(project);
return new RowVisitor() {
int cellIndex;
Properties bindings;
List<CellAtRow> cellsAtRows;
Evaluable eval;
public RowVisitor init(int cellIndex, Properties bindings, List<CellAtRow> cellsAtRows, Evaluable eval) {
this.cellIndex = cellIndex;
this.bindings = bindings;
@ -138,23 +139,23 @@ public class ColumnAdditionOperation extends EngineDependentOperation {
this.eval = eval;
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(cellIndex);
Cell newCell = null;
ExpressionUtils.bind(bindings, row, rowIndex, _baseColumnName, cell);
Object o = eval.evaluate(bindings);
if (o != null) {
if (o instanceof Cell) {
@ -170,17 +171,17 @@ public class ColumnAdditionOperation extends EngineDependentOperation {
v = cell != null ? cell.value : null;
}
}
if (v != null) {
newCell = new Cell(v, null);
}
}
}
if (newCell != null) {
cellsAtRows.add(new CellAtRow(rowIndex, newCell));
}
return false;
}
}.init(column.getCellIndex(), bindings, cellsAtRows, eval);

View File

@ -6,6 +6,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.history.Change;
import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.AbstractOperation;
@ -22,16 +23,16 @@ public class ColumnRemovalOperation extends AbstractOperation {
obj.getString("columnName")
);
}
public ColumnRemovalOperation(
String columnName
) {
_columnName = columnName;
}
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("Remove column " + _columnName);
@ -49,11 +50,11 @@ public class ColumnRemovalOperation extends AbstractOperation {
if (column == null) {
throw new Exception("No column named " + _columnName);
}
String description = "Remove column " + column.getName();
Change change = new ColumnRemovalChange(project.columnModel.columns.indexOf(column));
return new HistoryEntry(historyEntryID, project, description, ColumnRemovalOperation.this, change);
return ProjectManager.singleton.createHistoryEntry(historyEntryID, project, description, ColumnRemovalOperation.this, change);
}
}

View File

@ -6,6 +6,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.history.Change;
import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.AbstractOperation;
@ -23,7 +24,7 @@ public class ColumnRenameOperation extends AbstractOperation {
obj.getString("newColumnName")
);
}
public ColumnRenameOperation(
String oldColumnName,
String newColumnName
@ -31,10 +32,10 @@ public class ColumnRenameOperation extends AbstractOperation {
_oldColumnName = oldColumnName;
_newColumnName = newColumnName;
}
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("Rename column " + _oldColumnName + " to " + _newColumnName);
@ -55,9 +56,9 @@ public class ColumnRenameOperation extends AbstractOperation {
if (project.columnModel.getColumnByName(_newColumnName) != null) {
throw new Exception("Another column already named " + _newColumnName);
}
Change change = new ColumnRenameChange(_oldColumnName, _newColumnName);
return new HistoryEntry(historyEntryID, project, getBriefDescription(null), ColumnRenameOperation.this, change);
return ProjectManager.singleton.createHistoryEntry(historyEntryID, project, getBriefDescription(null), ColumnRenameOperation.this, change);
}
}

View File

@ -11,6 +11,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.browsing.Engine;
import com.metaweb.gridworks.browsing.FilteredRows;
import com.metaweb.gridworks.browsing.RowVisitor;
@ -32,17 +33,17 @@ public class ColumnSplitOperation extends EngineDependentOperation {
final protected boolean _guessCellType;
final protected boolean _removeOriginalColumn;
final protected String _mode;
final protected String _separator;
final protected boolean _regex;
final protected int _maxColumns;
final protected int[] _fieldLengths;
static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception {
JSONObject engineConfig = obj.getJSONObject("engineConfig");
String mode = obj.getString("mode");
if ("separator".equals(mode)) {
return new ColumnSplitOperation(
engineConfig,
@ -63,7 +64,7 @@ public class ColumnSplitOperation extends EngineDependentOperation {
);
}
}
public ColumnSplitOperation(
JSONObject engineConfig,
String columnName,
@ -74,19 +75,19 @@ public class ColumnSplitOperation extends EngineDependentOperation {
int maxColumns
) {
super(engineConfig);
_columnName = columnName;
_guessCellType = guessCellType;
_removeOriginalColumn = removeOriginalColumn;
_mode = "separator";
_separator = separator;
_regex = regex;
_maxColumns = maxColumns;
_fieldLengths = null;
}
public ColumnSplitOperation(
JSONObject engineConfig,
String columnName,
@ -95,22 +96,22 @@ public class ColumnSplitOperation extends EngineDependentOperation {
int[] fieldLengths
) {
super(engineConfig);
_columnName = columnName;
_guessCellType = guessCellType;
_removeOriginalColumn = removeOriginalColumn;
_mode = "lengths";
_separator = null;
_regex = false;
_maxColumns = -1;
_fieldLengths = fieldLengths;
}
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(getBriefDescription(null));
@ -134,53 +135,53 @@ public class ColumnSplitOperation extends EngineDependentOperation {
}
protected String getBriefDescription(Project project) {
return "Split column " + _columnName +
return "Split column " + _columnName +
("separator".equals(_mode) ? " by separator" : " by field lengths");
}
protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception {
Engine engine = createEngine(project);
Column column = project.columnModel.getColumnByName(_columnName);
if (column == null) {
throw new Exception("No column named " + _columnName);
}
List<String> columnNames = new ArrayList<String>();
List<Integer> rowIndices = new ArrayList<Integer>(project.rows.size());
List<List<Serializable>> tuples = new ArrayList<List<Serializable>>(project.rows.size());
FilteredRows filteredRows = engine.getAllFilteredRows();
RowVisitor rowVisitor;
if ("lengths".equals(_mode)) {
rowVisitor = new ColumnSplitRowVisitor(column.getCellIndex(), columnNames, rowIndices, tuples) {
protected java.util.List<Serializable> split(String s) {
List<Serializable> results = new ArrayList<Serializable>(_fieldLengths.length + 1);
int lastIndex = 0;
for (int i = 0; i < _fieldLengths.length; i++) {
int from = lastIndex;
int length = _fieldLengths[i];
int to = Math.min(from + length, s.length());
results.add(stringToValue(s.substring(from, to)));
lastIndex = to;
}
return results;
};
};
} else if (_regex) {
Pattern pattern = Pattern.compile(_separator);
rowVisitor = new ColumnSplitRowVisitor(column.getCellIndex(), columnNames, rowIndices, tuples) {
Pattern _pattern;
protected java.util.List<Serializable> split(String s) {
return stringArrayToValueList(_pattern.split(s, _maxColumns));
};
public RowVisitor init(Pattern pattern) {
_pattern = pattern;
return this;
@ -194,13 +195,13 @@ public class ColumnSplitOperation extends EngineDependentOperation {
};
};
}
filteredRows.accept(project, rowVisitor);
String description =
"Split " + rowIndices.size() +
" cell(s) in column " + _columnName +
" into several columns" +
String description =
"Split " + rowIndices.size() +
" cell(s) in column " + _columnName +
" into several columns" +
("separator".equals(_mode) ? " by separator" : " by field lengths");
Change change = new ColumnSplitChange(
@ -210,8 +211,8 @@ public class ColumnSplitOperation extends EngineDependentOperation {
tuples,
_removeOriginalColumn
);
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID, project, description, this, change);
}
@ -221,9 +222,9 @@ public class ColumnSplitOperation extends EngineDependentOperation {
List<String> columnNames;
List<Integer> rowIndices;
List<List<Serializable>> tuples;
int columnNameIndex = 1;
ColumnSplitRowVisitor(
int cellIndex,
List<String> columnNames,
@ -235,27 +236,27 @@ public class ColumnSplitOperation extends EngineDependentOperation {
this.rowIndices = rowIndices;
this.tuples = tuples;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Object value = row.getCellValue(cellIndex);
if (ExpressionUtils.isNonBlankData(value)) {
String s = value instanceof String ? ((String) value) : value.toString();
List<Serializable> tuple = split(s);
rowIndices.add(rowIndex);
tuples.add(tuple);
for (int i = columnNames.size(); i < tuple.size(); i++) {
while (true) {
String newColumnName = _columnName + " " + columnNameIndex++;
@ -268,21 +269,21 @@ public class ColumnSplitOperation extends EngineDependentOperation {
}
return false;
}
protected List<Serializable> split(String s) {
throw new UnsupportedOperationException();
}
protected Serializable stringToValue(String s) {
return _guessCellType ? ImporterUtilities.parseCellValue(s) : s;
}
protected List<Serializable> stringArrayToValueList(String[] cells) {
List<Serializable> results = new ArrayList<Serializable>(cells.length);
for (String cell : cells) {
results.add(stringToValue(cell));
}
return results;
}
}

View File

@ -13,6 +13,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.browsing.Engine;
import com.metaweb.gridworks.browsing.FilteredRows;
import com.metaweb.gridworks.browsing.RowVisitor;
@ -38,10 +39,10 @@ public class ExtendDataOperation extends EngineDependentOperation {
final protected String _baseColumnName;
final protected JSONObject _extension;
final protected int _columnInsertIndex;
static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception {
JSONObject engineConfig = obj.getJSONObject("engineConfig");
return new ExtendDataOperation(
engineConfig,
obj.getString("baseColumnName"),
@ -49,15 +50,15 @@ public class ExtendDataOperation extends EngineDependentOperation {
obj.getInt("columnInsertIndex")
);
}
public ExtendDataOperation(
JSONObject engineConfig,
String baseColumnName,
JSONObject extension,
int columnInsertIndex
int columnInsertIndex
) {
super(engineConfig);
_baseColumnName = baseColumnName;
_extension = extension;
_columnInsertIndex = columnInsertIndex;
@ -65,7 +66,7 @@ public class ExtendDataOperation extends EngineDependentOperation {
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(getBriefDescription(null));
@ -77,24 +78,24 @@ public class ExtendDataOperation extends EngineDependentOperation {
}
protected String getBriefDescription(Project project) {
return "Extend data at index " + _columnInsertIndex +
return "Extend data at index " + _columnInsertIndex +
" based on column " + _baseColumnName;
}
protected String createDescription(Column column, List<CellAtRow> cellsAtRows) {
return "Extend data at index " + _columnInsertIndex +
" based on column " + column.getName() +
return "Extend data at index " + _columnInsertIndex +
" based on column " + column.getName() +
" by filling " + cellsAtRows.size();
}
public Process createProcess(Project project, Properties options) throws Exception {
return new ExtendDataProcess(
project,
project,
getEngineConfig(),
getBriefDescription(null)
);
}
public class ExtendDataProcess extends LongRunningProcess implements Runnable {
final protected Project _project;
final protected JSONObject _engineConfig;
@ -103,21 +104,21 @@ public class ExtendDataOperation extends EngineDependentOperation {
protected FreebaseDataExtensionJob _job;
public ExtendDataProcess(
Project project,
JSONObject engineConfig,
Project project,
JSONObject engineConfig,
String description
) throws JSONException {
super(description);
_project = project;
_engineConfig = engineConfig;
_historyEntryID = HistoryEntry.allocateID();
_job = new FreebaseDataExtensionJob(_extension);
}
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("id"); writer.value(hashCode());
writer.key("description"); writer.value(_description);
@ -126,111 +127,111 @@ public class ExtendDataOperation extends EngineDependentOperation {
writer.key("progress"); writer.value(_progress);
writer.endObject();
}
protected Runnable getRunnable() {
return this;
}
protected void populateRowsWithMatches(List<Integer> rowIndices) throws Exception {
Engine engine = new Engine(_project);
engine.initializeFromJSON(_engineConfig);
Column column = _project.columnModel.getColumnByName(_baseColumnName);
if (column == null) {
throw new Exception("No column named " + _baseColumnName);
}
_cellIndex = column.getCellIndex();
FilteredRows filteredRows = engine.getAllFilteredRows();
filteredRows.accept(_project, new RowVisitor() {
List<Integer> _rowIndices;
public RowVisitor init(List<Integer> rowIndices) {
_rowIndices = rowIndices;
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(_cellIndex);
if (cell != null && cell.recon != null && cell.recon.match != null) {
_rowIndices.add(rowIndex);
}
return false;
}
}.init(rowIndices));
}
protected int extendRows(
List<Integer> rowIndices,
List<DataExtension> dataExtensions,
int from,
List<Integer> rowIndices,
List<DataExtension> dataExtensions,
int from,
int limit,
Map<String, ReconCandidate> reconCandidateMap
) {
Set<String> guids = new HashSet<String>();
int end;
for (end = from; end < limit && guids.size() < 10; end++) {
int index = rowIndices.get(end);
Row row = _project.rows.get(index);
Cell cell = row.getCell(_cellIndex);
guids.add(cell.recon.match.topicGUID);
}
Map<String, DataExtension> map = null;
try {
map = _job.extend(guids, reconCandidateMap);
} catch (Exception e) {
map = new HashMap<String, DataExtension>();
}
for (int i = from; i < end; i++) {
int index = rowIndices.get(i);
Row row = _project.rows.get(index);
Cell cell = row.getCell(_cellIndex);
String guid = cell.recon.match.topicGUID;
if (map.containsKey(guid)) {
dataExtensions.add(map.get(guid));
} else {
dataExtensions.add(null);
}
}
return end;
}
public void run() {
List<Integer> rowIndices = new ArrayList<Integer>();
List<DataExtension> dataExtensions = new ArrayList<DataExtension>();
try {
populateRowsWithMatches(rowIndices);
} catch (Exception e2) {
// TODO : Not sure what to do here?
e2.printStackTrace();
}
int start = 0;
Map<String, ReconCandidate> reconCandidateMap = new HashMap<String, ReconCandidate>();
while (start < rowIndices.size()) {
int end = extendRows(rowIndices, dataExtensions, start, rowIndices.size(), reconCandidateMap);
start = end;
_progress = end * 100 / rowIndices.size();
try {
Thread.sleep(200);
@ -240,23 +241,23 @@ public class ExtendDataOperation extends EngineDependentOperation {
}
}
}
if (!_canceled) {
List<String> columnNames = new ArrayList<String>();
for (ColumnInfo info : _job.columns) {
columnNames.add(StringUtils.join(info.names, " - "));
}
List<FreebaseType> columnTypes = new ArrayList<FreebaseType>();
for (ColumnInfo info : _job.columns) {
columnTypes.add(info.expectedType);
}
HistoryEntry historyEntry = new HistoryEntry(
HistoryEntry historyEntry = ProjectManager.singleton.createHistoryEntry(
_historyEntryID,
_project,
_description,
ExtendDataOperation.this,
_project,
_description,
ExtendDataOperation.this,
new DataExtensionChange(
_baseColumnName,
_columnInsertIndex,
@ -266,7 +267,7 @@ public class ExtendDataOperation extends EngineDependentOperation {
dataExtensions,
_historyEntryID)
);
_project.history.addEntry(historyEntry);
_project.processManager.onDoneProcess(this);
}

View File

@ -10,6 +10,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.browsing.Engine;
import com.metaweb.gridworks.browsing.FilteredRows;
import com.metaweb.gridworks.browsing.RowVisitor;
@ -35,20 +36,20 @@ import com.metaweb.gridworks.process.Process;
public class ReconOperation extends EngineDependentOperation {
final protected String _columnName;
final protected ReconConfig _reconConfig;
static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception {
JSONObject engineConfig = obj.getJSONObject("engineConfig");
return new ReconOperation(
engineConfig,
engineConfig,
obj.getString("columnName"),
ReconConfig.reconstruct(obj.getJSONObject("config"))
);
}
public ReconOperation(
JSONObject engineConfig,
String columnName,
JSONObject engineConfig,
String columnName,
ReconConfig reconConfig
) {
super(engineConfig);
@ -58,19 +59,19 @@ public class ReconOperation extends EngineDependentOperation {
public Process createProcess(Project project, Properties options) throws Exception {
return new ReconProcess(
project,
project,
getEngineConfig(),
getBriefDescription(null)
);
}
protected String getBriefDescription(Project project) {
return _reconConfig.getBriefDescription(project, _columnName);
}
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(getBriefDescription(null));
@ -83,7 +84,7 @@ public class ReconOperation extends EngineDependentOperation {
static protected class ReconEntry {
final public int rowIndex;
final public Cell cell;
public ReconEntry(int rowIndex, Cell cell) {
this.rowIndex = rowIndex;
this.cell = cell;
@ -92,22 +93,22 @@ public class ReconOperation extends EngineDependentOperation {
static protected class JobGroup {
final public ReconJob job;
final public List<ReconEntry> entries = new ArrayList<ReconEntry>();
public JobGroup(ReconJob job) {
this.job = job;
}
}
public class ReconProcess extends LongRunningProcess implements Runnable {
final protected Project _project;
final protected JSONObject _engineConfig;
final protected long _historyEntryID;
protected List<ReconEntry> _entries;
protected int _cellIndex;
public ReconProcess(
Project project,
JSONObject engineConfig,
Project project,
JSONObject engineConfig,
String description
) {
super(description);
@ -115,10 +116,10 @@ public class ReconOperation extends EngineDependentOperation {
_engineConfig = engineConfig;
_historyEntryID = HistoryEntry.allocateID();
}
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("id"); writer.value(hashCode());
writer.key("description"); writer.value(_description);
@ -159,35 +160,35 @@ public class ReconOperation extends EngineDependentOperation {
writer.endArray();
writer.endObject();
}
protected Runnable getRunnable() {
return this;
}
protected void populateEntries() throws Exception {
Engine engine = new Engine(_project);
engine.initializeFromJSON(_engineConfig);
Column column = _project.columnModel.getColumnByName(_columnName);
if (column == null) {
throw new Exception("No column named " + _columnName);
}
_entries = new ArrayList<ReconEntry>(_project.rows.size());
_cellIndex = column.getCellIndex();
FilteredRows filteredRows = engine.getAllFilteredRows();
filteredRows.accept(_project, new RowVisitor() {
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
if (_cellIndex < row.cells.size()) {
Cell cell = row.cells.get(_cellIndex);
@ -199,7 +200,7 @@ public class ReconOperation extends EngineDependentOperation {
}
});
}
public void run() {
try {
populateEntries();
@ -207,18 +208,18 @@ public class ReconOperation extends EngineDependentOperation {
// TODO : Not sure what to do here?
e2.printStackTrace();
}
Map<Integer, JobGroup> jobKeyToGroup = new HashMap<Integer, JobGroup>();
for (ReconEntry entry : _entries) {
ReconJob job = _reconConfig.createJob(
_project,
entry.rowIndex,
_project.rows.get(entry.rowIndex),
_columnName,
_project,
entry.rowIndex,
_project.rows.get(entry.rowIndex),
_columnName,
entry.cell
);
int key = job.getKey();
JobGroup group = jobKeyToGroup.get(key);
if (group == null) {
@ -227,42 +228,42 @@ public class ReconOperation extends EngineDependentOperation {
}
group.entries.add(entry);
}
List<CellChange> cellChanges = new ArrayList<CellChange>(_entries.size());
List<JobGroup> groups = new ArrayList<JobGroup>(jobKeyToGroup.values());
int batchSize = _reconConfig.getBatchSize();
for (int i = 0; i < groups.size(); i += batchSize) {
int to = Math.min(i + batchSize, groups.size());
List<ReconJob> jobs = new ArrayList<ReconJob>(to - i);
for (int j = i; j < to; j++) {
jobs.add(groups.get(j).job);
}
List<Recon> recons = _reconConfig.batchRecon(jobs, _historyEntryID);
for (int j = i; j < to; j++) {
Recon recon = recons.get(j - i);
List<ReconEntry> entries = groups.get(j).entries;
if (recon != null) {
recon.judgmentBatchSize = entries.size();
}
for (ReconEntry entry : entries) {
Cell oldCell = entry.cell;
Cell newCell = new Cell(oldCell.value, recon);
CellChange cellChange = new CellChange(
entry.rowIndex,
_cellIndex,
oldCell,
entry.rowIndex,
_cellIndex,
oldCell,
newCell
);
cellChanges.add(cellChange);
}
}
_progress = i * 100 / groups.size();
try {
Thread.sleep(50);
@ -272,23 +273,23 @@ public class ReconOperation extends EngineDependentOperation {
}
}
}
if (!_canceled) {
Change reconChange = new ReconChange(
cellChanges,
_columnName,
cellChanges,
_columnName,
_reconConfig,
null
);
HistoryEntry historyEntry = new HistoryEntry(
HistoryEntry historyEntry = ProjectManager.singleton.createHistoryEntry(
_historyEntryID,
_project,
_description,
ReconOperation.this,
_project,
_description,
ReconOperation.this,
reconChange
);
_project.history.addEntry(historyEntry);
_project.processManager.onDoneProcess(this);
}

View File

@ -8,6 +8,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.history.HistoryEntry;
import com.metaweb.gridworks.model.AbstractOperation;
import com.metaweb.gridworks.model.Cell;
@ -22,13 +23,13 @@ public class DenormalizeOperation extends AbstractOperation {
static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception {
return new DenormalizeOperation();
}
public DenormalizeOperation() {
}
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("Denormalize");
@ -42,37 +43,37 @@ public class DenormalizeOperation extends AbstractOperation {
protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception {
List<Row> newRows = new ArrayList<Row>();
List<Row> oldRows = project.rows;
for (int r = 0; r < oldRows.size(); r++) {
Row oldRow = oldRows.get(r);
Row newRow = null;
RowDependency rd = project.recordModel.getRowDependency(r);
if (rd.cellDependencies != null) {
newRow = oldRow.dup();
for (int c = 0; c < rd.cellDependencies.length; c++) {
CellDependency cd = rd.cellDependencies[c];
if (cd != null) {
int contextRowIndex = cd.rowIndex;
int contextCellIndex = cd.cellIndex;
if (contextRowIndex >= 0 && contextRowIndex < oldRows.size()) {
Row contextRow = oldRows.get(contextRowIndex);
Cell contextCell = contextRow.getCell(contextCellIndex);
newRow.setCell(contextCellIndex, contextCell);
}
}
}
}
newRows.add(newRow != null ? newRow : oldRow);
}
return new HistoryEntry(
historyEntryID,
return ProjectManager.singleton.createHistoryEntry(
historyEntryID,
project,
getBriefDescription(project),
DenormalizeOperation.this,

View File

@ -8,6 +8,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.browsing.Engine;
import com.metaweb.gridworks.browsing.FilteredRows;
import com.metaweb.gridworks.browsing.RowVisitor;
@ -27,13 +28,13 @@ public class RowFlagOperation extends EngineDependentOperation {
static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception {
JSONObject engineConfig = obj.getJSONObject("engineConfig");
boolean flagged = obj.getBoolean("flagged");
return new RowFlagOperation(
engineConfig,
engineConfig,
flagged
);
}
public RowFlagOperation(JSONObject engineConfig, boolean flagged) {
super(engineConfig);
_flagged = flagged;
@ -41,7 +42,7 @@ public class RowFlagOperation extends EngineDependentOperation {
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(getBriefDescription(null));
@ -56,17 +57,17 @@ public class RowFlagOperation extends EngineDependentOperation {
protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception {
Engine engine = createEngine(project);
List<Change> changes = new ArrayList<Change>(project.rows.size());
FilteredRows filteredRows = engine.getAllFilteredRows();
filteredRows.accept(project, createRowVisitor(project, changes));
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID,
project,
(_flagged ? "Flag" : "Unflag") + " " + changes.size() + " rows",
this,
project,
(_flagged ? "Flag" : "Unflag") + " " + changes.size() + " rows",
this,
new MassChange(changes, false)
);
}
@ -74,26 +75,26 @@ public class RowFlagOperation extends EngineDependentOperation {
protected RowVisitor createRowVisitor(Project project, List<Change> changes) throws Exception {
return new RowVisitor() {
List<Change> changes;
public RowVisitor init(List<Change> changes) {
this.changes = changes;
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
if (row.flagged != _flagged) {
RowFlagChange change = new RowFlagChange(rowIndex, _flagged);
changes.add(change);
}
return false;

View File

@ -8,6 +8,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.browsing.Engine;
import com.metaweb.gridworks.browsing.FilteredRows;
import com.metaweb.gridworks.browsing.RowVisitor;
@ -22,19 +23,19 @@ import com.metaweb.gridworks.operations.OperationRegistry;
public class RowRemovalOperation extends EngineDependentOperation {
static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception {
JSONObject engineConfig = obj.getJSONObject("engineConfig");
return new RowRemovalOperation(
engineConfig
);
}
public RowRemovalOperation(JSONObject engineConfig) {
super(engineConfig);
}
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(getBriefDescription(null));
@ -48,17 +49,17 @@ public class RowRemovalOperation extends EngineDependentOperation {
protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception {
Engine engine = createEngine(project);
List<Integer> rowIndices = new ArrayList<Integer>();
FilteredRows filteredRows = engine.getAllFilteredRows();
filteredRows.accept(project, createRowVisitor(project, rowIndices));
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID,
project,
"Remove " + rowIndices.size() + " rows",
this,
project,
"Remove " + rowIndices.size() + " rows",
this,
new RowRemovalChange(rowIndices)
);
}
@ -66,25 +67,25 @@ public class RowRemovalOperation extends EngineDependentOperation {
protected RowVisitor createRowVisitor(Project project, List<Integer> rowIndices) throws Exception {
return new RowVisitor() {
List<Integer> rowIndices;
public RowVisitor init(List<Integer> rowIndices) {
this.rowIndices = rowIndices;
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
rowIndices.add(rowIndex);
return false;
}
}.init(rowIndices);

View File

@ -8,6 +8,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.browsing.Engine;
import com.metaweb.gridworks.browsing.RecordVisitor;
import com.metaweb.gridworks.browsing.RowVisitor;
@ -27,13 +28,13 @@ public class RowReorderOperation extends AbstractOperation {
String mode = obj.getString("mode");
JSONObject sorting = obj.has("sorting") && !obj.isNull("sorting") ?
obj.getJSONObject("sorting") : null;
return new RowReorderOperation(Engine.stringToMode(mode), sorting);
}
final protected Mode _mode;
final protected JSONObject _sorting;
public RowReorderOperation(Mode mode, JSONObject sorting) {
_mode = mode;
_sorting = sorting;
@ -41,7 +42,7 @@ public class RowReorderOperation extends AbstractOperation {
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(getBriefDescription(null));
@ -57,50 +58,50 @@ public class RowReorderOperation extends AbstractOperation {
protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception {
Engine engine = new Engine(project);
engine.setMode(_mode);
List<Integer> rowIndices = new ArrayList<Integer>();
if (_mode == Mode.RowBased) {
RowVisitor visitor = new IndexingVisitor(rowIndices);
if (_sorting != null) {
SortingRowVisitor srv = new SortingRowVisitor(visitor);
srv.initializeFromJSON(project, _sorting);
if (srv.hasCriteria()) {
visitor = srv;
}
}
engine.getAllRows().accept(project, visitor);
} else {
RecordVisitor visitor = new IndexingVisitor(rowIndices);
if (_sorting != null) {
SortingRecordVisitor srv = new SortingRecordVisitor(visitor);
srv.initializeFromJSON(project, _sorting);
if (srv.hasCriteria()) {
visitor = srv;
}
}
engine.getAllRecords().accept(project, visitor);
}
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID,
project,
"Reorder rows",
this,
project,
"Reorder rows",
this,
new RowReorderChange(rowIndices)
);
}
static protected class IndexingVisitor implements RowVisitor, RecordVisitor {
List<Integer> _indices;
IndexingVisitor(List<Integer> indices) {
_indices = indices;
}
@Override
public void start(Project project) {
}

View File

@ -8,6 +8,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import com.metaweb.gridworks.ProjectManager;
import com.metaweb.gridworks.browsing.Engine;
import com.metaweb.gridworks.browsing.FilteredRows;
import com.metaweb.gridworks.browsing.RowVisitor;
@ -27,13 +28,13 @@ public class RowStarOperation extends EngineDependentOperation {
static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception {
JSONObject engineConfig = obj.getJSONObject("engineConfig");
boolean starred = obj.getBoolean("starred");
return new RowStarOperation(
engineConfig,
engineConfig,
starred
);
}
public RowStarOperation(JSONObject engineConfig, boolean starred) {
super(engineConfig);
_starred = starred;
@ -41,7 +42,7 @@ public class RowStarOperation extends EngineDependentOperation {
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(getBriefDescription(null));
@ -56,17 +57,17 @@ public class RowStarOperation extends EngineDependentOperation {
protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception {
Engine engine = createEngine(project);
List<Change> changes = new ArrayList<Change>(project.rows.size());
FilteredRows filteredRows = engine.getAllFilteredRows();
filteredRows.accept(project, createRowVisitor(project, changes));
return new HistoryEntry(
return ProjectManager.singleton.createHistoryEntry(
historyEntryID,
project,
(_starred ? "Star" : "Unstar") + " " + changes.size() + " rows",
this,
project,
(_starred ? "Star" : "Unstar") + " " + changes.size() + " rows",
this,
new MassChange(changes, false)
);
}
@ -74,26 +75,26 @@ public class RowStarOperation extends EngineDependentOperation {
protected RowVisitor createRowVisitor(Project project, List<Change> changes) throws Exception {
return new RowVisitor() {
List<Change> changes;
public RowVisitor init(List<Change> changes) {
this.changes = changes;
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
if (row.starred != _starred) {
RowStarChange change = new RowStarChange(rowIndex, _starred);
changes.add(change);
}
return false;