Internal refactor for IO - HistoryEntry is now a concrete class, so can be instantiated (reverting Operations classes back to r972 which were changed as a result of HistoryEntry being abstract).

HistoryEntry now deals with backend (filesystem etc.) through classes which implement HistoryEntryManager.  This HistoryEntryManager is held by ProjectManager, which allows for FileProjectManager to create FileHistoryEntryManager as appropriate.

git-svn-id: http://google-refine.googlecode.com/svn/trunk@982 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
Iain Sproat 2010-06-16 12:35:37 +00:00
parent 280daad2f6
commit f92fc2d056
23 changed files with 447 additions and 466 deletions

View File

@ -2,7 +2,6 @@ package com.metaweb.gridworks;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -11,9 +10,7 @@ import org.apache.tools.tar.TarOutputStream;
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.history.HistoryEntryManager;
import com.metaweb.gridworks.model.Project;
@ -44,6 +41,8 @@ public abstract class ProjectManager {
*/
transient protected Map<Long, Project> _projects;
protected HistoryEntryManager _historyEntryManager;
static public ProjectManager singleton;
public InterProjectModel getInterProjectModel() {
@ -126,6 +125,9 @@ 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);
//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);
public HistoryEntryManager getHistoryEntryManager(){
return this._historyEntryManager;
}
}

View File

@ -10,7 +10,6 @@ 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;
@ -122,7 +121,7 @@ public class EditOneCellCommand extends Command {
Change change = new CellChange(rowIndex, cellIndex, cell, newCell);
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID, _project, description, null, change);
}
}

View File

@ -9,7 +9,6 @@ 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;
@ -199,7 +198,7 @@ public class ReconJudgeOneCellCommand extends Command {
stats
);
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID, _project, description, null, change);
}
}

View File

@ -6,7 +6,6 @@ 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;
@ -83,7 +82,7 @@ public class AnnotateOneRowCommand extends Command {
}
protected HistoryEntry createHistoryEntry(long historyEntryID) throws Exception {
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID,
_project,
(starred ? "Star row " : "Unstar row ") + (rowIndex + 1),
@ -109,7 +108,7 @@ public class AnnotateOneRowCommand extends Command {
}
protected HistoryEntry createHistoryEntry(long historyEntryID) throws Exception {
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID,
_project,
(flagged ? "Flag row " : "Unflag row ") + (rowIndex + 1),

View File

@ -19,20 +19,31 @@ import com.metaweb.gridworks.util.ParsingUtilities;
* 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 abstract class HistoryEntry implements Jsonizable {
public class HistoryEntry implements Jsonizable {
final public long id;
final public long projectID;
final public String description;
final public Date time;
// the manager (deals with IO systems or databases etc.)
final public HistoryEntryManager _manager;
// the abstract operation, if any, that results in the change
final public AbstractOperation operation;
// the actual change, loaded on demand
transient protected Change _change;
private transient Change _change;
private final static String OPERATION = "operation";
public void setChange(Change _change) {
this._change = _change;
}
public Change getChange() {
return _change;
}
static public long allocateID() {
return Math.round(Math.random() * 1000000) + System.currentTimeMillis();
}
@ -44,7 +55,8 @@ public abstract class HistoryEntry implements Jsonizable {
this.operation = operation;
this.time = new Date();
_change = change;
this._manager = ProjectManager.singleton.getHistoryEntryManager();
setChange(change);
}
protected HistoryEntry(long id, long projectID, String description, AbstractOperation operation, Date time) {
@ -53,6 +65,7 @@ public abstract class HistoryEntry implements Jsonizable {
this.description = description;
this.operation = operation;
this.time = time;
this._manager = ProjectManager.singleton.getHistoryEntryManager();
}
public void write(JSONWriter writer, Properties options)
@ -68,23 +81,27 @@ public abstract class HistoryEntry implements Jsonizable {
writer.endObject();
}
public void save(Writer writer, Properties options){
_manager.save(this, writer, options);
}
public void apply(Project project) {
if (_change == null) {
loadChange();
if (getChange() == null) {
ProjectManager.singleton.getHistoryEntryManager().loadChange(this);
}
synchronized (project) {
_change.apply(project);
getChange().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();
_manager.saveChange(this);
} catch (Exception e) {
e.printStackTrace();
_change.revert(project);
getChange().revert(project);
throw new RuntimeException("Failed to apply change", e);
}
@ -92,20 +109,12 @@ public abstract class HistoryEntry implements Jsonizable {
}
public void revert(Project project) {
if (_change == null) {
loadChange();
if (getChange() == null) {
_manager.loadChange(this);
}
_change.revert(project);
getChange().revert(project);
}
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);
@ -114,7 +123,7 @@ public abstract class HistoryEntry implements Jsonizable {
operation = OperationRegistry.reconstruct(project, obj.getJSONObject(OPERATION));
}
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
obj.getLong("id"),
project.id,
obj.getString("description"),
@ -123,6 +132,8 @@ public abstract class HistoryEntry implements Jsonizable {
);
}
public void delete(){
_manager.delete(this);
}
}

View File

@ -8,55 +8,46 @@ 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.history.HistoryEntryManager;
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);
}
public class FileHistoryEntry implements HistoryEntryManager{
protected void delete() {
File file = getChangeFile();
public void delete(HistoryEntry historyEntry) {
File file = getChangeFile(historyEntry);
if (file.exists()) {
file.delete();
}
}
public void save(Writer writer, Properties options) {
public void save(HistoryEntry historyEntry, Writer writer, Properties options) {
JSONWriter jsonWriter = new JSONWriter(writer);
try {
write(jsonWriter, options);
historyEntry.write(jsonWriter, options);
} catch (JSONException e) {
e.printStackTrace();
}
}
public void loadChange() {
File changeFile = getChangeFile();
public void loadChange(HistoryEntry historyEntry) {
File changeFile = getChangeFile(historyEntry);
try {
loadChange(changeFile);
loadChange(historyEntry, changeFile);
} catch (Exception e) {
throw new RuntimeException("Failed to load change file " + changeFile.getAbsolutePath(), e);
}
}
protected void loadChange(File file) throws Exception {
protected void loadChange(HistoryEntry historyEntry, File file) throws Exception {
ZipFile zipFile = new ZipFile(file);
try {
Pool pool = new Pool();
@ -66,28 +57,28 @@ public class FileHistoryEntry extends HistoryEntry{
zipFile.getInputStream(poolEntry)));
} // else, it's a legacy project file
_change = History.readOneChange(
zipFile.getInputStream(zipFile.getEntry("change.txt")), pool);
historyEntry.setChange(History.readOneChange(
zipFile.getInputStream(zipFile.getEntry("change.txt")), pool));
} finally {
zipFile.close();
}
}
protected void saveChange() throws Exception {
File changeFile = getChangeFile();
public void saveChange(HistoryEntry historyEntry) throws Exception {
File changeFile = getChangeFile(historyEntry);
if (!(changeFile.exists())) {
saveChange(changeFile);
saveChange(historyEntry, changeFile);
}
}
protected void saveChange(File file) throws Exception {
protected void saveChange(HistoryEntry historyEntry, 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);
History.writeOneChange(out, historyEntry.getChange(), pool);
} finally {
out.closeEntry();
}
@ -103,12 +94,14 @@ public class FileHistoryEntry extends HistoryEntry{
}
}
protected File getChangeFile() {
return new File(getHistoryDir(), id + ".change.zip");
protected File getChangeFile(HistoryEntry historyEntry) {
return new File(getHistoryDir(historyEntry), historyEntry.id + ".change.zip");
}
protected File getHistoryDir() {//FIXME relies on FileProjectManager
File dir = new File(((FileProjectManager)ProjectManager.singleton).getProjectDir(projectID), "history");
protected File getHistoryDir(HistoryEntry historyEntry) {
File dir = new File(((FileProjectManager)ProjectManager.singleton)
.getProjectDir(historyEntry.projectID),
"history");
dir.mkdirs();
return dir;

View File

@ -30,9 +30,6 @@ 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;
@ -47,6 +44,7 @@ public class FileProjectManager extends ProjectManager{
logger.info("Using workspace directory: {}", dir.getAbsolutePath());
singleton = new FileProjectManager(dir);
}
}
private FileProjectManager(File dir) {
@ -57,6 +55,8 @@ public class FileProjectManager extends ProjectManager{
_expressions = new LinkedList<String>();
_projects = new HashMap<Long, Project>();
_historyEntryManager = new FileHistoryEntry();
load();
}
@ -445,11 +445,4 @@ public class FileProjectManager extends ProjectManager{
return found;
}
public HistoryEntry createHistoryEntry(long id, long projectID, String description, AbstractOperation operation, Date time){
return new FileHistoryEntry(id, projectID, description, operation, time);
}
public HistoryEntry createHistoryEntry(long id, Project project, String description, AbstractOperation operation, Change change){
return new FileHistoryEntry(id, project, description, operation, change);
}
}

View File

@ -5,7 +5,6 @@ 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;
@ -46,7 +45,7 @@ abstract public class EngineDependentMassCellOperation extends EngineDependentOp
String description = createDescription(column, cellChanges);
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID, project, description, this, createChange(project, column, cellChanges));
}

View File

@ -9,7 +9,6 @@ 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;
@ -51,7 +50,7 @@ public class SaveProtographOperation extends AbstractOperation {
Change change = new ProtographChange(_protograph);
return ProjectManager.singleton.createHistoryEntry(historyEntryID, project, description, SaveProtographOperation.this, change);
return new HistoryEntry(historyEntryID, project, description, SaveProtographOperation.this, change);
}
static public class ProtographChange implements Change {

View File

@ -8,7 +8,6 @@ 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;
@ -119,7 +118,7 @@ public class MultiValuedCellJoinOperation extends AbstractOperation {
r = r2 - 1; // r will be incremented by the for loop anyway
}
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID,
project,
getBriefDescription(null),

View File

@ -9,7 +9,6 @@ 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;
@ -137,7 +136,7 @@ public class MultiValuedCellSplitOperation extends AbstractOperation {
r = r2 - 1; // r will be incremented by the for loop anyway
}
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID,
project,
getBriefDescription(null),

View File

@ -9,7 +9,6 @@ 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;
@ -116,7 +115,7 @@ public class ColumnAdditionOperation extends EngineDependentOperation {
Change change = new ColumnAdditionChange(_newColumnName, _columnInsertIndex, cellsAtRows);
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID, project, description, this, change);
}

View File

@ -6,7 +6,6 @@ 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;
@ -55,6 +54,6 @@ public class ColumnRemovalOperation extends AbstractOperation {
Change change = new ColumnRemovalChange(project.columnModel.columns.indexOf(column));
return ProjectManager.singleton.createHistoryEntry(historyEntryID, project, description, ColumnRemovalOperation.this, change);
return new HistoryEntry(historyEntryID, project, description, ColumnRemovalOperation.this, change);
}
}

View File

@ -6,7 +6,6 @@ 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;
@ -59,6 +58,6 @@ public class ColumnRenameOperation extends AbstractOperation {
Change change = new ColumnRenameChange(_oldColumnName, _newColumnName);
return ProjectManager.singleton.createHistoryEntry(historyEntryID, project, getBriefDescription(null), ColumnRenameOperation.this, change);
return new HistoryEntry(historyEntryID, project, getBriefDescription(null), ColumnRenameOperation.this, change);
}
}

View File

@ -11,7 +11,6 @@ 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;
@ -212,7 +211,7 @@ public class ColumnSplitOperation extends EngineDependentOperation {
_removeOriginalColumn
);
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID, project, description, this, change);
}

View File

@ -13,7 +13,6 @@ 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;
@ -253,7 +252,7 @@ public class ExtendDataOperation extends EngineDependentOperation {
columnTypes.add(info.expectedType);
}
HistoryEntry historyEntry = ProjectManager.singleton.createHistoryEntry(
HistoryEntry historyEntry = new HistoryEntry(
_historyEntryID,
_project,
_description,

View File

@ -10,7 +10,6 @@ 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;
@ -282,7 +281,7 @@ public class ReconOperation extends EngineDependentOperation {
null
);
HistoryEntry historyEntry = ProjectManager.singleton.createHistoryEntry(
HistoryEntry historyEntry = new HistoryEntry(
_historyEntryID,
_project,
_description,

View File

@ -8,7 +8,6 @@ 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;
@ -72,7 +71,7 @@ public class DenormalizeOperation extends AbstractOperation {
newRows.add(newRow != null ? newRow : oldRow);
}
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID,
project,
getBriefDescription(project),

View File

@ -8,7 +8,6 @@ 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;
@ -63,7 +62,7 @@ public class RowFlagOperation extends EngineDependentOperation {
FilteredRows filteredRows = engine.getAllFilteredRows();
filteredRows.accept(project, createRowVisitor(project, changes));
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID,
project,
(_flagged ? "Flag" : "Unflag") + " " + changes.size() + " rows",

View File

@ -8,7 +8,6 @@ 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;
@ -55,7 +54,7 @@ public class RowRemovalOperation extends EngineDependentOperation {
FilteredRows filteredRows = engine.getAllFilteredRows();
filteredRows.accept(project, createRowVisitor(project, rowIndices));
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID,
project,
"Remove " + rowIndices.size() + " rows",

View File

@ -8,7 +8,6 @@ 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;
@ -86,7 +85,7 @@ public class RowReorderOperation extends AbstractOperation {
engine.getAllRecords().accept(project, visitor);
}
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID,
project,
"Reorder rows",

View File

@ -8,7 +8,6 @@ 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;
@ -63,7 +62,7 @@ public class RowStarOperation extends EngineDependentOperation {
FilteredRows filteredRows = engine.getAllFilteredRows();
filteredRows.accept(project, createRowVisitor(project, changes));
return ProjectManager.singleton.createHistoryEntry(
return new HistoryEntry(
historyEntryID,
project,
(_starred ? "Star" : "Unstar") + " " + changes.size() + " rows",