From 17f1dc2e6f7313311ca5ad56fabdfd38d21b8823 Mon Sep 17 00:00:00 2001 From: Iain Sproat Date: Tue, 15 Jun 2010 22:11:35 +0000 Subject: [PATCH] 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 --- .../com/metaweb/gridworks/ProjectManager.java | 10 +- .../commands/cell/EditOneCellCommand.java | 51 +++--- .../project/ExportProjectCommand.java | 37 ++--- .../project/ImportProjectCommand.java | 45 +++--- .../recon/ReconJudgeOneCellCommand.java | 91 +++++------ .../commands/row/AnnotateOneRowCommand.java | 65 ++++---- .../gridworks/history/HistoryEntry.java | 145 ++++-------------- .../gridworks/io/FileHistoryEntry.java | 116 ++++++++++++++ .../gridworks/io/FileProjectManager.java | 10 ++ .../gridworks/io/ProjectUtilities.java | 2 +- .../EngineDependentMassCellOperation.java | 19 +-- .../operations/SaveProtographOperation.java | 33 ++-- .../cell/MultiValuedCellJoinOperation.java | 37 ++--- .../cell/MultiValuedCellSplitOperation.java | 47 +++--- .../column/ColumnAdditionOperation.java | 63 ++++---- .../column/ColumnRemovalOperation.java | 15 +- .../column/ColumnRenameOperation.java | 13 +- .../column/ColumnSplitOperation.java | 87 +++++------ .../column/ExtendDataOperation.java | 101 ++++++------ .../operations/recon/ReconOperation.java | 105 ++++++------- .../operations/row/DenormalizeOperation.java | 25 +-- .../operations/row/RowFlagOperation.java | 33 ++-- .../operations/row/RowRemovalOperation.java | 31 ++-- .../operations/row/RowReorderOperation.java | 35 +++-- .../operations/row/RowStarOperation.java | 33 ++-- 25 files changed, 658 insertions(+), 591 deletions(-) create mode 100644 main/src/com/metaweb/gridworks/io/FileHistoryEntry.java diff --git a/main/src/com/metaweb/gridworks/ProjectManager.java b/main/src/com/metaweb/gridworks/ProjectManager.java index f5eb2e04c..524b2fa7d 100644 --- a/main/src/com/metaweb/gridworks/ProjectManager.java +++ b/main/src/com/metaweb/gridworks/ProjectManager.java @@ -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); } diff --git a/main/src/com/metaweb/gridworks/commands/cell/EditOneCellCommand.java b/main/src/com/metaweb/gridworks/commands/cell/EditOneCellCommand.java index 275a0a262..bb4099ec6 100644 --- a/main/src/com/metaweb/gridworks/commands/cell/EditOneCellCommand.java +++ b/main/src/com/metaweb/gridworks/commands/cell/EditOneCellCommand.java @@ -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); } } diff --git a/main/src/com/metaweb/gridworks/commands/project/ExportProjectCommand.java b/main/src/com/metaweb/gridworks/commands/project/ExportProjectCommand.java index 31ef2e25c..01bae2ed7 100644 --- a/main/src/com/metaweb/gridworks/commands/project/ExportProjectCommand.java +++ b/main/src/com/metaweb/gridworks/commands/project/ExportProjectCommand.java @@ -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(); } diff --git a/main/src/com/metaweb/gridworks/commands/project/ImportProjectCommand.java b/main/src/com/metaweb/gridworks/commands/project/ImportProjectCommand.java index 96ee6aae4..bfcdc0bcb 100644 --- a/main/src/com/metaweb/gridworks/commands/project/ImportProjectCommand.java +++ b/main/src/com/metaweb/gridworks/commands/project/ImportProjectCommand.java @@ -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 { diff --git a/main/src/com/metaweb/gridworks/commands/recon/ReconJudgeOneCellCommand.java b/main/src/com/metaweb/gridworks/commands/recon/ReconJudgeOneCellCommand.java index f128903c3..8255370fb 100644 --- a/main/src/com/metaweb/gridworks/commands/recon/ReconJudgeOneCellCommand.java +++ b/main/src/com/metaweb/gridworks/commands/recon/ReconJudgeOneCellCommand.java @@ -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); } } diff --git a/main/src/com/metaweb/gridworks/commands/row/AnnotateOneRowCommand.java b/main/src/com/metaweb/gridworks/commands/row/AnnotateOneRowCommand.java index a7a9d8d80..cc7f451c0 100644 --- a/main/src/com/metaweb/gridworks/commands/row/AnnotateOneRowCommand.java +++ b/main/src/com/metaweb/gridworks/commands/row/AnnotateOneRowCommand.java @@ -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) ); } diff --git a/main/src/com/metaweb/gridworks/history/HistoryEntry.java b/main/src/com/metaweb/gridworks/history/HistoryEntry.java index 4cffde6bd..46d504a17 100644 --- a/main/src/com/metaweb/gridworks/history/HistoryEntry.java +++ b/main/src/com/metaweb/gridworks/history/HistoryEntry.java @@ -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; - } + + } diff --git a/main/src/com/metaweb/gridworks/io/FileHistoryEntry.java b/main/src/com/metaweb/gridworks/io/FileHistoryEntry.java new file mode 100644 index 000000000..0a71cd308 --- /dev/null +++ b/main/src/com/metaweb/gridworks/io/FileHistoryEntry.java @@ -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; + } +} diff --git a/main/src/com/metaweb/gridworks/io/FileProjectManager.java b/main/src/com/metaweb/gridworks/io/FileProjectManager.java index 6f78dae23..1bda53ae7 100644 --- a/main/src/com/metaweb/gridworks/io/FileProjectManager.java +++ b/main/src/com/metaweb/gridworks/io/FileProjectManager.java @@ -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); + } } diff --git a/main/src/com/metaweb/gridworks/io/ProjectUtilities.java b/main/src/com/metaweb/gridworks/io/ProjectUtilities.java index a048a051b..877672b31 100644 --- a/main/src/com/metaweb/gridworks/io/ProjectUtilities.java +++ b/main/src/com/metaweb/gridworks/io/ProjectUtilities.java @@ -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 { diff --git a/main/src/com/metaweb/gridworks/operations/EngineDependentMassCellOperation.java b/main/src/com/metaweb/gridworks/operations/EngineDependentMassCellOperation.java index 73eafe356..051407979 100644 --- a/main/src/com/metaweb/gridworks/operations/EngineDependentMassCellOperation.java +++ b/main/src/com/metaweb/gridworks/operations/EngineDependentMassCellOperation.java @@ -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 cellChanges = new ArrayList(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 cellChanges) { return new MassCellChange( cellChanges, column.getName(), _updateRowContextDependencies); } - + abstract protected RowVisitor createRowVisitor(Project project, List cellChanges, long historyEntryID) throws Exception; abstract protected String createDescription(Column column, List cellChanges); } diff --git a/main/src/com/metaweb/gridworks/operations/SaveProtographOperation.java b/main/src/com/metaweb/gridworks/operations/SaveProtographOperation.java index 8e50a3c99..ce2dec9ad 100644 --- a/main/src/com/metaweb/gridworks/operations/SaveProtographOperation.java +++ b/main/src/com/metaweb/gridworks/operations/SaveProtographOperation.java @@ -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 { } } } - } + } } diff --git a/main/src/com/metaweb/gridworks/operations/cell/MultiValuedCellJoinOperation.java b/main/src/com/metaweb/gridworks/operations/cell/MultiValuedCellJoinOperation.java index dafba7be2..33cdcda00 100644 --- a/main/src/com/metaweb/gridworks/operations/cell/MultiValuedCellJoinOperation.java +++ b/main/src/com/metaweb/gridworks/operations/cell/MultiValuedCellJoinOperation.java @@ -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 newRows = new ArrayList(); - + 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) ); } diff --git a/main/src/com/metaweb/gridworks/operations/cell/MultiValuedCellSplitOperation.java b/main/src/com/metaweb/gridworks/operations/cell/MultiValuedCellSplitOperation.java index d14e92a85..30694b7df 100644 --- a/main/src/com/metaweb/gridworks/operations/cell/MultiValuedCellSplitOperation.java +++ b/main/src/com/metaweb/gridworks/operations/cell/MultiValuedCellSplitOperation.java @@ -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 newRows = new ArrayList(); - + 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) ); } diff --git a/main/src/com/metaweb/gridworks/operations/column/ColumnAdditionOperation.java b/main/src/com/metaweb/gridworks/operations/column/ColumnAdditionOperation.java index d818ea935..1b75ece4d 100644 --- a/main/src/com/metaweb/gridworks/operations/column/ColumnAdditionOperation.java +++ b/main/src/com/metaweb/gridworks/operations/column/ColumnAdditionOperation.java @@ -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 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 cellsAtRows = new ArrayList(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 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 cellsAtRows; Evaluable eval; - + public RowVisitor init(int cellIndex, Properties bindings, List 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); diff --git a/main/src/com/metaweb/gridworks/operations/column/ColumnRemovalOperation.java b/main/src/com/metaweb/gridworks/operations/column/ColumnRemovalOperation.java index 44846261c..8dff5a9ae 100644 --- a/main/src/com/metaweb/gridworks/operations/column/ColumnRemovalOperation.java +++ b/main/src/com/metaweb/gridworks/operations/column/ColumnRemovalOperation.java @@ -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); } } diff --git a/main/src/com/metaweb/gridworks/operations/column/ColumnRenameOperation.java b/main/src/com/metaweb/gridworks/operations/column/ColumnRenameOperation.java index f79cd5738..e5f9eed81 100644 --- a/main/src/com/metaweb/gridworks/operations/column/ColumnRenameOperation.java +++ b/main/src/com/metaweb/gridworks/operations/column/ColumnRenameOperation.java @@ -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); } } diff --git a/main/src/com/metaweb/gridworks/operations/column/ColumnSplitOperation.java b/main/src/com/metaweb/gridworks/operations/column/ColumnSplitOperation.java index af19ba939..f1299c40e 100644 --- a/main/src/com/metaweb/gridworks/operations/column/ColumnSplitOperation.java +++ b/main/src/com/metaweb/gridworks/operations/column/ColumnSplitOperation.java @@ -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 columnNames = new ArrayList(); List rowIndices = new ArrayList(project.rows.size()); List> tuples = new ArrayList>(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 split(String s) { List results = new ArrayList(_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 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 columnNames; List rowIndices; List> tuples; - + int columnNameIndex = 1; - + ColumnSplitRowVisitor( int cellIndex, List 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 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 split(String s) { throw new UnsupportedOperationException(); } - + protected Serializable stringToValue(String s) { return _guessCellType ? ImporterUtilities.parseCellValue(s) : s; } - + protected List stringArrayToValueList(String[] cells) { List results = new ArrayList(cells.length); for (String cell : cells) { results.add(stringToValue(cell)); } - + return results; } } diff --git a/main/src/com/metaweb/gridworks/operations/column/ExtendDataOperation.java b/main/src/com/metaweb/gridworks/operations/column/ExtendDataOperation.java index 8d553b206..55b3b16bd 100644 --- a/main/src/com/metaweb/gridworks/operations/column/ExtendDataOperation.java +++ b/main/src/com/metaweb/gridworks/operations/column/ExtendDataOperation.java @@ -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 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 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 _rowIndices; - + public RowVisitor init(List 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 rowIndices, - List dataExtensions, - int from, + List rowIndices, + List dataExtensions, + int from, int limit, Map reconCandidateMap ) { Set guids = new HashSet(); - + 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 map = null; try { map = _job.extend(guids, reconCandidateMap); } catch (Exception e) { map = new HashMap(); } - + 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 rowIndices = new ArrayList(); List dataExtensions = new ArrayList(); - + try { populateRowsWithMatches(rowIndices); } catch (Exception e2) { // TODO : Not sure what to do here? e2.printStackTrace(); } - + int start = 0; Map reconCandidateMap = new HashMap(); - + 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 columnNames = new ArrayList(); for (ColumnInfo info : _job.columns) { columnNames.add(StringUtils.join(info.names, " - ")); } - + List columnTypes = new ArrayList(); 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); } diff --git a/main/src/com/metaweb/gridworks/operations/recon/ReconOperation.java b/main/src/com/metaweb/gridworks/operations/recon/ReconOperation.java index 6964150de..c0321b29c 100644 --- a/main/src/com/metaweb/gridworks/operations/recon/ReconOperation.java +++ b/main/src/com/metaweb/gridworks/operations/recon/ReconOperation.java @@ -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 entries = new ArrayList(); - + 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 _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(_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 jobKeyToGroup = new HashMap(); - + 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 cellChanges = new ArrayList(_entries.size()); List groups = new ArrayList(jobKeyToGroup.values()); - + int batchSize = _reconConfig.getBatchSize(); for (int i = 0; i < groups.size(); i += batchSize) { int to = Math.min(i + batchSize, groups.size()); - + List jobs = new ArrayList(to - i); for (int j = i; j < to; j++) { jobs.add(groups.get(j).job); } - + List recons = _reconConfig.batchRecon(jobs, _historyEntryID); for (int j = i; j < to; j++) { Recon recon = recons.get(j - i); List 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); } diff --git a/main/src/com/metaweb/gridworks/operations/row/DenormalizeOperation.java b/main/src/com/metaweb/gridworks/operations/row/DenormalizeOperation.java index ec176c902..235f85978 100644 --- a/main/src/com/metaweb/gridworks/operations/row/DenormalizeOperation.java +++ b/main/src/com/metaweb/gridworks/operations/row/DenormalizeOperation.java @@ -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 newRows = new ArrayList(); - + List 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, diff --git a/main/src/com/metaweb/gridworks/operations/row/RowFlagOperation.java b/main/src/com/metaweb/gridworks/operations/row/RowFlagOperation.java index 53e953202..e9df51c64 100644 --- a/main/src/com/metaweb/gridworks/operations/row/RowFlagOperation.java +++ b/main/src/com/metaweb/gridworks/operations/row/RowFlagOperation.java @@ -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 changes = new ArrayList(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 changes) throws Exception { return new RowVisitor() { List changes; - + public RowVisitor init(List 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; diff --git a/main/src/com/metaweb/gridworks/operations/row/RowRemovalOperation.java b/main/src/com/metaweb/gridworks/operations/row/RowRemovalOperation.java index a08aa9717..53f3e3034 100644 --- a/main/src/com/metaweb/gridworks/operations/row/RowRemovalOperation.java +++ b/main/src/com/metaweb/gridworks/operations/row/RowRemovalOperation.java @@ -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 rowIndices = new ArrayList(); - + 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 rowIndices) throws Exception { return new RowVisitor() { List rowIndices; - + public RowVisitor init(List 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); diff --git a/main/src/com/metaweb/gridworks/operations/row/RowReorderOperation.java b/main/src/com/metaweb/gridworks/operations/row/RowReorderOperation.java index 2244adc1d..99693aa38 100644 --- a/main/src/com/metaweb/gridworks/operations/row/RowReorderOperation.java +++ b/main/src/com/metaweb/gridworks/operations/row/RowReorderOperation.java @@ -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 rowIndices = new ArrayList(); 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 _indices; - + IndexingVisitor(List indices) { _indices = indices; } - + @Override public void start(Project project) { } diff --git a/main/src/com/metaweb/gridworks/operations/row/RowStarOperation.java b/main/src/com/metaweb/gridworks/operations/row/RowStarOperation.java index a37db65c9..b65f5d4e6 100644 --- a/main/src/com/metaweb/gridworks/operations/row/RowStarOperation.java +++ b/main/src/com/metaweb/gridworks/operations/row/RowStarOperation.java @@ -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 changes = new ArrayList(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 changes) throws Exception { return new RowVisitor() { List changes; - + public RowVisitor init(List 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;