diff --git a/main/src/com/google/refine/model/changes/ColumnAdditionChange.java b/main/src/com/google/refine/model/changes/ColumnAdditionChange.java index 2f5f34bc2..e0db19c67 100644 --- a/main/src/com/google/refine/model/changes/ColumnAdditionChange.java +++ b/main/src/com/google/refine/model/changes/ColumnAdditionChange.java @@ -37,11 +37,13 @@ import java.io.IOException; import java.io.LineNumberReader; import java.io.Writer; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.Properties; import com.google.refine.history.Change; import com.google.refine.model.Column; +import com.google.refine.model.ColumnGroup; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.util.Pool; @@ -51,6 +53,7 @@ public class ColumnAdditionChange extends ColumnChange { final protected int _columnIndex; final protected CellAtRow[] _newCells; protected int _newCellIndex = -1; + protected List _oldColumnGroups; public ColumnAdditionChange(String columnName, int columnIndex, List newCells) { _columnName = columnName; @@ -64,9 +67,36 @@ public class ColumnAdditionChange extends ColumnChange { if (_newCellIndex < 0) { _newCellIndex = project.columnModel.allocateNewCellIndex(); } + + int columnGroupCount = project.columnModel.columnGroups.size(); + _oldColumnGroups = new ArrayList(columnGroupCount); + for (int i = columnGroupCount - 1; i >= 0; i--) { + ColumnGroup columnGroup = project.columnModel.columnGroups.get(i); + + _oldColumnGroups.add(columnGroup); + + if (columnGroup.startColumnIndex <= _columnIndex) { + if (columnGroup.startColumnIndex + columnGroup.columnSpan > _columnIndex) { + // the new column is inserted right in the middle of the group + project.columnModel.columnGroups.set(i, new ColumnGroup( + columnGroup.startColumnIndex, + columnGroup.columnSpan + 1, + columnGroup.keyColumnIndex < _columnIndex ? + columnGroup.keyColumnIndex : + (columnGroup.keyColumnIndex + 1) + )); + } + } else { + // the new column precedes this whole group + project.columnModel.columnGroups.set(i, new ColumnGroup( + columnGroup.startColumnIndex + 1, + columnGroup.columnSpan, + columnGroup.keyColumnIndex + 1 + )); + } + } Column column = new Column(_newCellIndex, _columnName); - project.columnModel.columns.add(_columnIndex, column); try { for (CellAtRow cell : _newCells) { @@ -75,6 +105,7 @@ public class ColumnAdditionChange extends ColumnChange { } catch (Exception e) { e.printStackTrace(); } + project.update(); } } @@ -88,6 +119,9 @@ public class ColumnAdditionChange extends ColumnChange { project.columnModel.columns.remove(_columnIndex); + project.columnModel.columnGroups.clear(); + project.columnModel.columnGroups.addAll(_oldColumnGroups); + project.update(); } } @@ -101,6 +135,7 @@ public class ColumnAdditionChange extends ColumnChange { c.save(writer, options); writer.write('\n'); } + writeOldColumnGroups(writer, options, _oldColumnGroups); writer.write("/ec/\n"); // end of change marker } @@ -109,6 +144,7 @@ public class ColumnAdditionChange extends ColumnChange { int columnIndex = -1; int newCellIndex = -1; List newCells = null; + List oldColumnGroups = null; String line; while ((line = reader.readLine()) != null && !"/ec/".equals(line)) { @@ -131,12 +167,18 @@ public class ColumnAdditionChange extends ColumnChange { newCells.add(CellAtRow.load(line, pool)); } } + } else if ("oldColumnGroupCount".equals(field)) { + int oldColumnGroupCount = Integer.parseInt(line.substring(equal + 1)); + + oldColumnGroups = readOldColumnGroups(reader, oldColumnGroupCount); } } ColumnAdditionChange change = new ColumnAdditionChange(columnName, columnIndex, newCells); change._newCellIndex = newCellIndex; - + change._oldColumnGroups = oldColumnGroups != null ? + oldColumnGroups : new LinkedList(); + return change; } } diff --git a/main/src/com/google/refine/model/changes/ColumnChange.java b/main/src/com/google/refine/model/changes/ColumnChange.java index 09f064591..df2956865 100644 --- a/main/src/com/google/refine/model/changes/ColumnChange.java +++ b/main/src/com/google/refine/model/changes/ColumnChange.java @@ -33,7 +33,45 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model.changes; +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONWriter; + import com.google.refine.history.Change; +import com.google.refine.model.ColumnGroup; abstract public class ColumnChange implements Change { + + static public void writeOldColumnGroups(Writer writer, Properties options, + List oldColumnGroups) throws IOException { + writer.write("oldColumnGroupCount="); + writer.write(Integer.toString(oldColumnGroups.size())); writer.write('\n'); + for (ColumnGroup cg : oldColumnGroups) { + JSONWriter jsonWriter = new JSONWriter(writer); + try { + cg.write(jsonWriter, options); + } catch (JSONException e) { + throw new IOException(e); + } + writer.write('\n'); + } + } + + static public List readOldColumnGroups( + LineNumberReader reader, int oldColumnGroupCount) throws Exception { + List oldColumnGroups = new ArrayList(oldColumnGroupCount); + for (int i = 0; i < oldColumnGroupCount; i++) { + String line = reader.readLine(); + if (line != null) { + oldColumnGroups.add(ColumnGroup.load(line)); + } + } + return oldColumnGroups; + } } diff --git a/main/src/com/google/refine/model/changes/ColumnMoveChange.java b/main/src/com/google/refine/model/changes/ColumnMoveChange.java index 8088de2eb..e5f1055e4 100644 --- a/main/src/com/google/refine/model/changes/ColumnMoveChange.java +++ b/main/src/com/google/refine/model/changes/ColumnMoveChange.java @@ -36,10 +36,14 @@ package com.google.refine.model.changes; import java.io.IOException; import java.io.LineNumberReader; import java.io.Writer; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; import java.util.Properties; import com.google.refine.history.Change; import com.google.refine.model.Column; +import com.google.refine.model.ColumnGroup; import com.google.refine.model.Project; import com.google.refine.util.Pool; @@ -47,6 +51,7 @@ public class ColumnMoveChange extends ColumnChange { final protected String _columnName; final protected int _newColumnIndex; protected int _oldColumnIndex; + protected List _oldColumnGroups; public ColumnMoveChange(String columnName, int index) { _columnName = columnName; @@ -57,8 +62,13 @@ public class ColumnMoveChange extends ColumnChange { synchronized (project) { _oldColumnIndex = project.columnModel.getColumnIndexByName(_columnName); + if (_oldColumnGroups == null) { + _oldColumnGroups = new ArrayList(project.columnModel.columnGroups); + } + Column column = project.columnModel.columns.remove(_oldColumnIndex); project.columnModel.columns.add(_newColumnIndex, column); + project.columnModel.columnGroups.clear(); project.update(); } @@ -69,6 +79,9 @@ public class ColumnMoveChange extends ColumnChange { Column column = project.columnModel.columns.remove(_newColumnIndex); project.columnModel.columns.add(_oldColumnIndex, column); + project.columnModel.columnGroups.clear(); + project.columnModel.columnGroups.addAll(_oldColumnGroups); + project.update(); } } @@ -77,6 +90,7 @@ public class ColumnMoveChange extends ColumnChange { writer.write("columnName="); writer.write(_columnName); writer.write('\n'); writer.write("oldColumnIndex="); writer.write(Integer.toString(_oldColumnIndex)); writer.write('\n'); writer.write("newColumnIndex="); writer.write(Integer.toString(_newColumnIndex)); writer.write('\n'); + writeOldColumnGroups(writer, options, _oldColumnGroups); writer.write("/ec/\n"); // end of change marker } @@ -84,7 +98,8 @@ public class ColumnMoveChange extends ColumnChange { String columnName = null; int oldColumnIndex = -1; int newColumnIndex = -1; - + List oldColumnGroups = null; + String line; while ((line = reader.readLine()) != null && !"/ec/".equals(line)) { int equal = line.indexOf('='); @@ -97,11 +112,17 @@ public class ColumnMoveChange extends ColumnChange { newColumnIndex = Integer.parseInt(value); } else if ("columnName".equals(field)) { columnName = value; + } else if ("oldColumnGroupCount".equals(field)) { + int oldColumnGroupCount = Integer.parseInt(line.substring(equal + 1)); + + oldColumnGroups = readOldColumnGroups(reader, oldColumnGroupCount); } } ColumnMoveChange change = new ColumnMoveChange(columnName, newColumnIndex); change._oldColumnIndex = oldColumnIndex; + change._oldColumnGroups = oldColumnGroups != null ? + oldColumnGroups : new LinkedList(); return change; } diff --git a/main/src/com/google/refine/model/changes/ColumnRemovalChange.java b/main/src/com/google/refine/model/changes/ColumnRemovalChange.java index 03737404d..e7c57ee1c 100644 --- a/main/src/com/google/refine/model/changes/ColumnRemovalChange.java +++ b/main/src/com/google/refine/model/changes/ColumnRemovalChange.java @@ -36,19 +36,24 @@ package com.google.refine.model.changes; import java.io.IOException; import java.io.LineNumberReader; import java.io.Writer; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; import java.util.Properties; import com.google.refine.history.Change; import com.google.refine.model.Cell; import com.google.refine.model.Column; +import com.google.refine.model.ColumnGroup; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.util.Pool; public class ColumnRemovalChange extends ColumnChange { - final protected int _oldColumnIndex; - protected Column _oldColumn; - protected CellAtRow[] _oldCells; + final protected int _oldColumnIndex; + protected Column _oldColumn; + protected CellAtRow[] _oldCells; + protected List _oldColumnGroups; public ColumnRemovalChange(int index) { _oldColumnIndex = index; @@ -56,9 +61,44 @@ public class ColumnRemovalChange extends ColumnChange { public void apply(Project project) { synchronized (project) { + int columnGroupCount = project.columnModel.columnGroups.size(); + _oldColumnGroups = new ArrayList(columnGroupCount); + for (int i = columnGroupCount - 1; i >= 0; i--) { + ColumnGroup columnGroup = project.columnModel.columnGroups.get(i); + + _oldColumnGroups.add(columnGroup); + + if (columnGroup.startColumnIndex <= _oldColumnIndex) { + if (columnGroup.startColumnIndex + columnGroup.columnSpan > _oldColumnIndex) { + // the group starts before or at _oldColumnIndex + // but spans to include _oldColumnIndex + + if (columnGroup.keyColumnIndex == _oldColumnIndex) { + // the key column is removed, so we remove the whole group + project.columnModel.columnGroups.remove(i); + } else { + // otherwise, the group's span has been reduced by 1 + project.columnModel.columnGroups.set(i, new ColumnGroup( + columnGroup.startColumnIndex, + columnGroup.columnSpan - 1, + columnGroup.keyColumnIndex < _oldColumnIndex ? + columnGroup.keyColumnIndex : + (columnGroup.keyColumnIndex - 1) + )); + } + } + } else { + // the column removed precedes this whole group + project.columnModel.columnGroups.set(i, new ColumnGroup( + columnGroup.startColumnIndex - 1, + columnGroup.columnSpan, + columnGroup.keyColumnIndex - 1 + )); + } + } + _oldColumn = project.columnModel.columns.remove(_oldColumnIndex); _oldCells = new CellAtRow[project.rows.size()]; - int cellIndex = _oldColumn.getCellIndex(); for (int i = 0; i < _oldCells.length; i++) { Row row = project.rows.get(i); @@ -85,6 +125,9 @@ public class ColumnRemovalChange extends ColumnChange { project.rows.get(cell.row).cells.set(cellIndex, cell.cell); } + project.columnModel.columnGroups.clear(); + project.columnModel.columnGroups.addAll(_oldColumnGroups); + project.update(); } } @@ -97,6 +140,8 @@ public class ColumnRemovalChange extends ColumnChange { c.save(writer, options); writer.write('\n'); } + writeOldColumnGroups(writer, options, _oldColumnGroups); + writer.write("/ec/\n"); // end of change marker } @@ -104,6 +149,7 @@ public class ColumnRemovalChange extends ColumnChange { int oldColumnIndex = -1; Column oldColumn = null; CellAtRow[] oldCells = null; + List oldColumnGroups = null; String line; while ((line = reader.readLine()) != null && !"/ec/".equals(line)) { @@ -124,12 +170,18 @@ public class ColumnRemovalChange extends ColumnChange { oldCells[i] = CellAtRow.load(line, pool); } } + } else if ("oldColumnGroupCount".equals(field)) { + int oldColumnGroupCount = Integer.parseInt(line.substring(equal + 1)); + + oldColumnGroups = readOldColumnGroups(reader, oldColumnGroupCount); } } ColumnRemovalChange change = new ColumnRemovalChange(oldColumnIndex); change._oldColumn = oldColumn; change._oldCells = oldCells; + change._oldColumnGroups = oldColumnGroups != null ? + oldColumnGroups : new LinkedList(); return change; } diff --git a/main/src/com/google/refine/model/changes/ColumnReorderChange.java b/main/src/com/google/refine/model/changes/ColumnReorderChange.java index b64f34afa..9c9fe21bf 100644 --- a/main/src/com/google/refine/model/changes/ColumnReorderChange.java +++ b/main/src/com/google/refine/model/changes/ColumnReorderChange.java @@ -37,11 +37,13 @@ import java.io.IOException; import java.io.LineNumberReader; import java.io.Writer; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.Properties; import com.google.refine.history.Change; import com.google.refine.model.Column; +import com.google.refine.model.ColumnGroup; import com.google.refine.model.Project; import com.google.refine.util.Pool; @@ -49,6 +51,7 @@ public class ColumnReorderChange extends ColumnChange { final protected List _columnNames; protected List _oldColumns; protected List _newColumns; + protected List _oldColumnGroups; public ColumnReorderChange(List columnNames) { _columnNames = columnNames; @@ -66,10 +69,14 @@ public class ColumnReorderChange extends ColumnChange { _newColumns.add(column); } } + + _oldColumnGroups = new ArrayList(project.columnModel.columnGroups); } project.columnModel.columns.clear(); project.columnModel.columns.addAll(_newColumns); + project.columnModel.columnGroups.clear(); + project.update(); } } @@ -78,6 +85,10 @@ public class ColumnReorderChange extends ColumnChange { synchronized (project) { project.columnModel.columns.clear(); project.columnModel.columns.addAll(_oldColumns); + + project.columnModel.columnGroups.clear(); + project.columnModel.columnGroups.addAll(_oldColumnGroups); + project.update(); } } @@ -98,6 +109,7 @@ public class ColumnReorderChange extends ColumnChange { c.save(writer); writer.write('\n'); } + writeOldColumnGroups(writer, options, _oldColumnGroups); writer.write("/ec/\n"); // end of change marker } @@ -105,6 +117,7 @@ public class ColumnReorderChange extends ColumnChange { List columnNames = new ArrayList(); List oldColumns = new ArrayList(); List newColumns = new ArrayList(); + List oldColumnGroups = null; String line; while ((line = reader.readLine()) != null && !"/ec/".equals(line)) { @@ -135,12 +148,18 @@ public class ColumnReorderChange extends ColumnChange { newColumns.add(Column.load(line)); } } + } else if ("oldColumnGroupCount".equals(field)) { + int oldColumnGroupCount = Integer.parseInt(line.substring(equal + 1)); + + oldColumnGroups = readOldColumnGroups(reader, oldColumnGroupCount); } } ColumnReorderChange change = new ColumnReorderChange(columnNames); change._oldColumns = oldColumns; change._newColumns = newColumns; + change._oldColumnGroups = oldColumnGroups != null ? + oldColumnGroups : new LinkedList(); return change; } diff --git a/main/src/com/google/refine/model/changes/ColumnSplitChange.java b/main/src/com/google/refine/model/changes/ColumnSplitChange.java index d51f8dd50..b8af956c8 100644 --- a/main/src/com/google/refine/model/changes/ColumnSplitChange.java +++ b/main/src/com/google/refine/model/changes/ColumnSplitChange.java @@ -38,6 +38,7 @@ import java.io.LineNumberReader; import java.io.Serializable; import java.io.Writer; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.Properties; @@ -47,6 +48,7 @@ import org.json.JSONTokener; import com.google.refine.history.Change; import com.google.refine.model.Cell; import com.google.refine.model.Column; +import com.google.refine.model.ColumnGroup; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.util.Pool; @@ -67,6 +69,8 @@ public class ColumnSplitChange implements Change { protected List _oldRows; protected List _newRows; + protected List _oldColumnGroups; + public ColumnSplitChange( String columnName, List columnNames, @@ -152,6 +156,49 @@ public class ColumnSplitChange implements Change { } } + int columnGroupCount = project.columnModel.columnGroups.size(); + int columnCountChange = _columnNames.size() - (_removeOriginalColumn ? 1 : 0); + _oldColumnGroups = new ArrayList(columnGroupCount); + for (int i = columnGroupCount - 1; i >= 0; i--) { + ColumnGroup columnGroup = project.columnModel.columnGroups.get(i); + + _oldColumnGroups.add(columnGroup); + + if (columnGroup.startColumnIndex <= _columnIndex) { + if (columnGroup.startColumnIndex + columnGroup.columnSpan > _columnIndex) { + // the column being split is in the middle of the group + + if (columnGroup.keyColumnIndex == _columnIndex) { + if (_removeOriginalColumn) { + // the key column is being split and removed + project.columnModel.columnGroups.remove(i); + } else { + project.columnModel.columnGroups.set(i, new ColumnGroup( + columnGroup.startColumnIndex, + columnGroup.columnSpan + columnCountChange, + columnGroup.keyColumnIndex + )); + } + } else { + project.columnModel.columnGroups.set(i, new ColumnGroup( + columnGroup.startColumnIndex, + columnGroup.columnSpan + columnCountChange, + columnGroup.keyColumnIndex < _columnIndex ? + columnGroup.keyColumnIndex : + (columnGroup.keyColumnIndex + columnCountChange) + )); + } + } + } else { + // the new column precedes this whole group + project.columnModel.columnGroups.set(i, new ColumnGroup( + columnGroup.startColumnIndex + columnCountChange, + columnGroup.columnSpan, + columnGroup.keyColumnIndex + columnCountChange + )); + } + } + for (int i = 0; i < _rowIndices.size(); i++) { int r = _rowIndices.get(i); Row newRow = _newRows.get(i); @@ -193,6 +240,9 @@ public class ColumnSplitChange implements Change { project.columnModel.columns.remove(_columnIndex + 1); } + project.columnModel.columnGroups.clear(); + project.columnModel.columnGroups.addAll(_oldColumnGroups); + project.update(); } } @@ -240,6 +290,7 @@ public class ColumnSplitChange implements Change { row.save(writer, options); writer.write('\n'); } + ColumnChange.writeOldColumnGroups(writer, options, _oldColumnGroups); writer.write("/ec/\n"); // end of change marker } @@ -257,6 +308,8 @@ public class ColumnSplitChange implements Change { List oldRows = null; List newRows = null; + List oldColumnGroups = null; + String line; while ((line = reader.readLine()) != null && !"/ec/".equals(line)) { int equal = line.indexOf('='); @@ -337,8 +390,11 @@ public class ColumnSplitChange implements Change { newRows.add(Row.load(line, pool)); } } + } else if ("oldColumnGroupCount".equals(field)) { + int oldColumnGroupCount = Integer.parseInt(line.substring(equal + 1)); + + oldColumnGroups = ColumnChange.readOldColumnGroups(reader, oldColumnGroupCount); } - } ColumnSplitChange change = new ColumnSplitChange( @@ -355,7 +411,8 @@ public class ColumnSplitChange implements Change { oldRows, newRows ); - + change._oldColumnGroups = oldColumnGroups != null ? + oldColumnGroups : new LinkedList(); return change; } diff --git a/main/src/com/google/refine/model/changes/MassRowColumnChange.java b/main/src/com/google/refine/model/changes/MassRowColumnChange.java index dd4cbc968..498df6fc2 100644 --- a/main/src/com/google/refine/model/changes/MassRowColumnChange.java +++ b/main/src/com/google/refine/model/changes/MassRowColumnChange.java @@ -37,11 +37,13 @@ import java.io.IOException; import java.io.LineNumberReader; import java.io.Writer; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.Properties; import com.google.refine.history.Change; import com.google.refine.model.Column; +import com.google.refine.model.ColumnGroup; import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.util.Pool; @@ -51,6 +53,7 @@ public class MassRowColumnChange implements Change { final protected List _newRows; protected List _oldColumns; protected List _oldRows; + protected List _oldColumnGroups; public MassRowColumnChange(List newColumns, List newRows) { _newColumns = newColumns; @@ -59,11 +62,19 @@ public class MassRowColumnChange implements Change { public void apply(Project project) { synchronized (project) { - _oldColumns = new ArrayList(project.columnModel.columns); - _oldRows = new ArrayList(project.rows); + if (_oldColumnGroups == null) { + _oldColumnGroups = new ArrayList(project.columnModel.columnGroups); + } + if (_oldColumns == null) { + _oldColumns = new ArrayList(project.columnModel.columns); + } + if (_oldRows == null) { + _oldRows = new ArrayList(project.rows); + } project.columnModel.columns.clear(); project.columnModel.columns.addAll(_newColumns); + project.columnModel.columnGroups.clear(); project.rows.clear(); project.rows.addAll(_newRows); @@ -77,6 +88,9 @@ public class MassRowColumnChange implements Change { project.columnModel.columns.clear(); project.columnModel.columns.addAll(_oldColumns); + project.columnModel.columnGroups.clear(); + project.columnModel.columnGroups.addAll(_oldColumnGroups); + project.rows.clear(); project.rows.addAll(_oldRows); @@ -105,13 +119,15 @@ public class MassRowColumnChange implements Change { row.save(writer, options); writer.write('\n'); } + ColumnChange.writeOldColumnGroups(writer, options, _oldColumnGroups); writer.write("/ec/\n"); // end of change marker } static public Change load(LineNumberReader reader, Pool pool) throws Exception { List oldColumns = null; List newColumns = null; - + List oldColumnGroups = null; + List oldRows = null; List newRows = null; @@ -160,12 +176,18 @@ public class MassRowColumnChange implements Change { newColumns.add(Column.load(line)); } } + } else if ("oldColumnGroupCount".equals(field)) { + int oldColumnGroupCount = Integer.parseInt(line.substring(equal + 1)); + + oldColumnGroups = ColumnChange.readOldColumnGroups(reader, oldColumnGroupCount); } } MassRowColumnChange change = new MassRowColumnChange(newColumns, newRows); change._oldColumns = oldColumns; change._oldRows = oldRows; + change._oldColumnGroups = oldColumnGroups != null ? + oldColumnGroups : new LinkedList(); return change; }