From 8f071ede312053ccc791261a40e85eab6962668b Mon Sep 17 00:00:00 2001 From: David Huynh Date: Sun, 8 Aug 2010 06:30:30 +0000 Subject: [PATCH] Added command Transpose Cells in Rows into Columns (Issue 82). git-svn-id: http://google-refine.googlecode.com/svn/trunk@1147 7d457c2a-affb-35e4-300a-418c747d4874 --- .../google/gridworks/GridworksServlet.java | 1 + .../cell/TransposeRowsIntoColumnsCommand.java | 37 ++++++ .../operations/OperationRegistry.java | 2 + .../TransposeRowsIntoColumnsOperation.java | 125 ++++++++++++++++++ .../data-table/data-table-column-header-ui.js | 31 +++++ 5 files changed, 196 insertions(+) create mode 100644 main/src/com/google/gridworks/commands/cell/TransposeRowsIntoColumnsCommand.java create mode 100644 main/src/com/google/gridworks/operations/cell/TransposeRowsIntoColumnsOperation.java diff --git a/main/src/com/google/gridworks/GridworksServlet.java b/main/src/com/google/gridworks/GridworksServlet.java index 8c21259aa..442ec6c79 100644 --- a/main/src/com/google/gridworks/GridworksServlet.java +++ b/main/src/com/google/gridworks/GridworksServlet.java @@ -74,6 +74,7 @@ public class GridworksServlet extends Butterfly { {"fill-down", "com.google.gridworks.commands.cell.FillDownCommand"}, {"blank-down", "com.google.gridworks.commands.cell.BlankDownCommand"}, {"transpose-columns-into-rows", "com.google.gridworks.commands.cell.TransposeColumnsIntoRowsCommand"}, + {"transpose-rows-into-columns", "com.google.gridworks.commands.cell.TransposeRowsIntoColumnsCommand"}, {"add-column", "com.google.gridworks.commands.column.AddColumnCommand"}, {"remove-column", "com.google.gridworks.commands.column.RemoveColumnCommand"}, diff --git a/main/src/com/google/gridworks/commands/cell/TransposeRowsIntoColumnsCommand.java b/main/src/com/google/gridworks/commands/cell/TransposeRowsIntoColumnsCommand.java new file mode 100644 index 000000000..6e3916786 --- /dev/null +++ b/main/src/com/google/gridworks/commands/cell/TransposeRowsIntoColumnsCommand.java @@ -0,0 +1,37 @@ +package com.google.gridworks.commands.cell; + +import java.io.IOException; +import java.util.Properties; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.google.gridworks.commands.Command; +import com.google.gridworks.model.AbstractOperation; +import com.google.gridworks.model.Project; +import com.google.gridworks.operations.cell.TransposeRowsIntoColumnsOperation; +import com.google.gridworks.process.Process; + +public class TransposeRowsIntoColumnsCommand extends Command { + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + try { + Project project = getProject(request); + + String columnName = request.getParameter("columnName"); + int rowCount = Integer.parseInt(request.getParameter("rowCount")); + + AbstractOperation op = new TransposeRowsIntoColumnsOperation( + columnName, rowCount); + + Process process = op.createProcess(project, new Properties()); + + performProcessAndRespond(request, response, project, process); + } catch (Exception e) { + respondException(response, e); + } + } +} diff --git a/main/src/com/google/gridworks/operations/OperationRegistry.java b/main/src/com/google/gridworks/operations/OperationRegistry.java index 141762262..844ed46af 100644 --- a/main/src/com/google/gridworks/operations/OperationRegistry.java +++ b/main/src/com/google/gridworks/operations/OperationRegistry.java @@ -14,6 +14,7 @@ import com.google.gridworks.operations.cell.MultiValuedCellJoinOperation; import com.google.gridworks.operations.cell.MultiValuedCellSplitOperation; import com.google.gridworks.operations.cell.TextTransformOperation; import com.google.gridworks.operations.cell.TransposeColumnsIntoRowsOperation; +import com.google.gridworks.operations.cell.TransposeRowsIntoColumnsOperation; import com.google.gridworks.operations.column.ColumnAdditionOperation; import com.google.gridworks.operations.column.ColumnMoveOperation; import com.google.gridworks.operations.column.ColumnRemovalOperation; @@ -54,6 +55,7 @@ public abstract class OperationRegistry { register("multivalued-cell-split", MultiValuedCellSplitOperation.class); register("fill-down", FillDownOperation.class); register("transpose-columns-into-rows", TransposeColumnsIntoRowsOperation.class); + register("transpose-rows-into-columns", TransposeRowsIntoColumnsOperation.class); register("column-addition", ColumnAdditionOperation.class); register("column-removal", ColumnRemovalOperation.class); diff --git a/main/src/com/google/gridworks/operations/cell/TransposeRowsIntoColumnsOperation.java b/main/src/com/google/gridworks/operations/cell/TransposeRowsIntoColumnsOperation.java new file mode 100644 index 000000000..1a3a4f4c1 --- /dev/null +++ b/main/src/com/google/gridworks/operations/cell/TransposeRowsIntoColumnsOperation.java @@ -0,0 +1,125 @@ +package com.google.gridworks.operations.cell; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONWriter; + +import com.google.gridworks.history.HistoryEntry; +import com.google.gridworks.model.AbstractOperation; +import com.google.gridworks.model.Cell; +import com.google.gridworks.model.Column; +import com.google.gridworks.model.Project; +import com.google.gridworks.model.Row; +import com.google.gridworks.model.changes.MassRowColumnChange; +import com.google.gridworks.operations.OperationRegistry; + +public class TransposeRowsIntoColumnsOperation extends AbstractOperation { + final protected String _columnName; + final protected int _rowCount; + + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { + return new TransposeRowsIntoColumnsOperation( + obj.getString("columnName"), + obj.getInt("rowCount") + ); + } + + public TransposeRowsIntoColumnsOperation( + String columnName, + int rowCount + ) { + _columnName = columnName; + _rowCount = rowCount; + } + + 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("Transpose every " + _rowCount + " cells in column " + _columnName + " into separate columns"); + writer.key("columnName"); writer.value(_columnName); + writer.key("rowCount"); writer.value(_rowCount); + writer.endObject(); + } + + protected String getBriefDescription(Project project) { + return "Transpose every " + _rowCount + " cells in column " + _columnName + " into separate columns"; + } + + @Override + protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception { + List newColumns = new ArrayList(); + List oldColumns = project.columnModel.columns; + + int columnIndex = project.columnModel.getColumnIndexByName(_columnName); + int columnCount = oldColumns.size(); + + newColumns.addAll(oldColumns.subList(0, columnIndex)); + + for (int i = 0; i < columnCount; i++) { + Column column = oldColumns.get(i); + + if (i == columnIndex) { + int newIndex = 1; + for (int n = 0; n < _rowCount; n++) { + String columnName = _columnName + " " + newIndex++; + while (project.columnModel.getColumnByName(columnName) != null) { + columnName = _columnName + " " + newIndex++; + } + + newColumns.add(new Column(i + n, columnName)); + } + } else if (i < columnIndex) { + newColumns.add(new Column(i, column.getName())); + } else { + newColumns.add(new Column(i + _rowCount - 1, column.getName())); + } + } + + List oldRows = project.rows; + List newRows = new ArrayList(oldRows.size() / _rowCount); + for (int r = 0; r < oldRows.size(); r += _rowCount) { + Row firstNewRow = new Row(newColumns.size()); + + for (int r2 = 0; r2 < _rowCount && r + r2 < oldRows.size(); r2++) { + Row oldRow = oldRows.get(r + r2); + Row newRow = r2 == 0 ? firstNewRow : new Row(newColumns.size()); + boolean hasData = r2 == 0; + + for (int c = 0; c < oldColumns.size(); c++) { + Column column = oldColumns.get(c); + Cell cell = oldRow.getCell(column.getCellIndex()); + + if (cell != null && cell.value != null) { + if (c == columnIndex) { + firstNewRow.setCell(columnIndex + r2, cell); + } else if (c < columnIndex) { + newRow.setCell(c, cell); + hasData = true; + } else { + newRow.setCell(c + _rowCount - 1, cell); + hasData = true; + } + } + } + + if (hasData) { + newRows.add(newRow); + } + } + } + + return new HistoryEntry( + historyEntryID, + project, + getBriefDescription(null), + this, + new MassRowColumnChange(newColumns, newRows) + ); + } +} diff --git a/main/webapp/modules/core/scripts/views/data-table/data-table-column-header-ui.js b/main/webapp/modules/core/scripts/views/data-table/data-table-column-header-ui.js index c1ec9b87b..c62f6526f 100644 --- a/main/webapp/modules/core/scripts/views/data-table/data-table-column-header-ui.js +++ b/main/webapp/modules/core/scripts/views/data-table/data-table-column-header-ui.js @@ -352,6 +352,10 @@ DataTableColumnHeaderUI.prototype._createMenuForColumnHeader = function(elmt) { { label: "Cells Across Columns into Rows", click: function() { self._doTransposeColumnsIntoRows(); } + }, + { + label: "Cells in Rows into Columns", + click: function() { self._doTransposeRowsIntoColumns(); } } ] }, @@ -1232,6 +1236,33 @@ DataTableColumnHeaderUI.prototype._doTransposeColumnsIntoRows = function() { elmts.fromColumnSelect.bind("change", populateToColumn); }; +DataTableColumnHeaderUI.prototype._doTransposeRowsIntoColumns = function() { + var rowCount = window.prompt("How many rows to transpose?", "2"); + if (rowCount != null) { + try { + rowCount = parseInt(rowCount); + } catch (e) { + // ignore + } + + if (isNaN(rowCount) || rowCount < 2) { + alert("Expected an integer at least 2."); + } else { + var config = { + columnName: this._column.name, + rowCount: rowCount + }; + + Gridworks.postProcess( + "transpose-rows-into-columns", + config, + null, + { modelsChanged: true } + ); + } + } +}; + DataTableColumnHeaderUI.prototype._showSortingCriterion = function(criterion, hasOtherCriteria) { var self = this;