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;