From a35b9f53f73225551ce616aaff5aaeefee7d1a6f Mon Sep 17 00:00:00 2001 From: David Huynh Date: Sun, 6 Nov 2011 02:50:33 +0000 Subject: [PATCH] Made operation "Transpose columns into rows" support the option of transposing into 2 new columns rather than just one. git-svn-id: http://google-refine.googlecode.com/svn/trunk@2362 7d457c2a-affb-35e4-300a-418c747d4874 --- .../cell/TransposeColumnsIntoRowsCommand.java | 24 +- .../TransposeColumnsIntoRowsOperation.java | 205 +++++++++++++----- .../views/data-table/menu-edit-cells.js | 39 +++- .../transpose-columns-into-rows.html | 50 +++-- 4 files changed, 234 insertions(+), 84 deletions(-) diff --git a/main/src/com/google/refine/commands/cell/TransposeColumnsIntoRowsCommand.java b/main/src/com/google/refine/commands/cell/TransposeColumnsIntoRowsCommand.java index 35846e1a3..8f84b4478 100644 --- a/main/src/com/google/refine/commands/cell/TransposeColumnsIntoRowsCommand.java +++ b/main/src/com/google/refine/commands/cell/TransposeColumnsIntoRowsCommand.java @@ -53,17 +53,29 @@ public class TransposeColumnsIntoRowsCommand extends Command { try { Project project = getProject(request); + AbstractOperation op; String startColumnName = request.getParameter("startColumnName"); int columnCount = Integer.parseInt(request.getParameter("columnCount")); - String combinedColumnName = request.getParameter("combinedColumnName"); - - boolean prependColumnName = Boolean.parseBoolean(request.getParameter("prependColumnName")); - String separator = request.getParameter("separator"); boolean ignoreBlankCells = Boolean.parseBoolean(request.getParameter("ignoreBlankCells")); - AbstractOperation op = new TransposeColumnsIntoRowsOperation( - startColumnName, columnCount, combinedColumnName, prependColumnName, separator, ignoreBlankCells); + String combinedColumnName = request.getParameter("combinedColumnName"); + if (combinedColumnName != null) { + boolean prependColumnName = Boolean.parseBoolean(request.getParameter("prependColumnName")); + String separator = request.getParameter("separator"); + op = new TransposeColumnsIntoRowsOperation( + startColumnName, columnCount, + combinedColumnName, prependColumnName, separator, + ignoreBlankCells); + } else { + String keyColumnName = request.getParameter("keyColumnName"); + String valueColumnName = request.getParameter("valueColumnName"); + + op = new TransposeColumnsIntoRowsOperation( + startColumnName, columnCount, + keyColumnName, valueColumnName, + ignoreBlankCells); + } Process process = op.createProcess(project, new Properties()); diff --git a/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java b/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java index 2f7854938..3a8b0f0a9 100644 --- a/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java +++ b/main/src/com/google/refine/operations/cell/TransposeColumnsIntoRowsOperation.java @@ -49,24 +49,40 @@ import com.google.refine.model.Project; import com.google.refine.model.Row; import com.google.refine.model.changes.MassRowColumnChange; import com.google.refine.operations.OperationRegistry; +import com.google.refine.util.JSONUtilities; public class TransposeColumnsIntoRowsOperation extends AbstractOperation { final protected String _startColumnName; final protected int _columnCount; + final protected boolean _ignoreBlankCells; + final protected String _combinedColumnName; final protected boolean _prependColumnName; final protected String _separator; - final protected boolean _ignoreBlankCells; + + final protected String _keyColumnName; + final protected String _valueColumnName; static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { - return new TransposeColumnsIntoRowsOperation( - obj.getString("startColumnName"), - obj.getInt("columnCount"), - obj.getString("combinedColumnName"), - obj.getBoolean("prependColumnName"), - obj.getString("separator"), - obj.getBoolean("ignoreBlankCells") - ); + String combinedColumnName = JSONUtilities.getString(obj, "combinedColumnName", null); + if (combinedColumnName != null) { + return new TransposeColumnsIntoRowsOperation( + obj.getString("startColumnName"), + obj.getInt("columnCount"), + combinedColumnName, + obj.getBoolean("prependColumnName"), + obj.getString("separator"), + obj.getBoolean("ignoreBlankCells") + ); + } else { + return new TransposeColumnsIntoRowsOperation( + obj.getString("startColumnName"), + obj.getInt("columnCount"), + obj.getString("keyColumnName"), + obj.getString("valueColumnName"), + obj.getBoolean("ignoreBlankCells") + ); + } } public TransposeColumnsIntoRowsOperation( @@ -79,10 +95,33 @@ public class TransposeColumnsIntoRowsOperation extends AbstractOperation { ) { _startColumnName = startColumnName; _columnCount = columnCount; + _ignoreBlankCells = ignoreBlankCells; + _combinedColumnName = combinedColumnName; _prependColumnName = prependColumnName; _separator = separator; + + _keyColumnName = null; + _valueColumnName = null; + } + + public TransposeColumnsIntoRowsOperation( + String startColumnName, + int columnCount, + String keyColumnName, + String valueColumnName, + boolean ignoreBlankCells + ) { + _startColumnName = startColumnName; + _columnCount = columnCount; _ignoreBlankCells = ignoreBlankCells; + + _combinedColumnName = null; + _prependColumnName = false; + _separator = null; + + _keyColumnName = keyColumnName; + _valueColumnName = valueColumnName; } @Override @@ -91,38 +130,67 @@ public class TransposeColumnsIntoRowsOperation extends AbstractOperation { writer.object(); writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); - writer.key("description"); writer.value( - _columnCount > 0 ? - ("Transpose cells in " + _columnCount + - " column(s) starting with " + _startColumnName + " into rows") : - ("Transpose cells in columns starting with " + - _startColumnName + " into rows")); + writer.key("description"); writer.value(getBriefDescription()); writer.key("startColumnName"); writer.value(_startColumnName); writer.key("columnCount"); writer.value(_columnCount); - writer.key("combinedColumnName"); writer.value(_combinedColumnName); - writer.key("prependColumnName"); writer.value(_prependColumnName); - writer.key("separator"); writer.value(_separator); writer.key("ignoreBlankCells"); writer.value(_ignoreBlankCells); + if (_combinedColumnName != null) { + writer.key("combinedColumnName"); writer.value(_combinedColumnName); + writer.key("prependColumnName"); writer.value(_prependColumnName); + writer.key("separator"); writer.value(_separator); + } else { + writer.key("keyColumnName"); writer.value(_keyColumnName); + writer.key("valueColumnName"); writer.value(_valueColumnName); + } writer.endObject(); } @Override protected String getBriefDescription(Project project) { - return _columnCount > 0 ? - ("Transpose cells in " + _columnCount + - " column(s) starting with " + _startColumnName + " into rows") : - ("Transpose cells in columns starting with " + - _startColumnName + " into rows"); + return getBriefDescription(); + } + + protected String getBriefDescription() { + if (_combinedColumnName != null) { + if (_columnCount > 0) { + return "Transpose cells in " + _columnCount + + " column(s) starting with " + _startColumnName + + " into rows in one new column named " + _combinedColumnName; + } else { + return "Transpose cells in columns starting with " + + _startColumnName + + " into rows in one new column named " + _combinedColumnName; + } + } else { + if (_columnCount > 0) { + return "Transpose cells in " + _columnCount + + " column(s) starting with " + _startColumnName + + " into rows in two new columns named " + + _keyColumnName + " and " + _valueColumnName; + } else { + return "Transpose cells in columns starting with " + + _startColumnName + + " into rows in two new columns named " + + _keyColumnName + " and " + _valueColumnName; + } + } } @Override protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception { - if (_combinedColumnName != null && - !_combinedColumnName.isEmpty() && - project.columnModel.getColumnByName(_combinedColumnName) != null) { - throw new Exception("Another column already named " + _combinedColumnName); + if (_combinedColumnName != null) { + if (project.columnModel.getColumnByName(_combinedColumnName) != null) { + throw new Exception("Another column already named " + _combinedColumnName); + } + } else { + if (project.columnModel.getColumnByName(_keyColumnName) != null) { + throw new Exception("Another column already named " + _keyColumnName); + } + if (project.columnModel.getColumnByName(_valueColumnName) != null) { + throw new Exception("Another column already named " + _valueColumnName); + } } - + List newColumns = new ArrayList(); List oldColumns = project.columnModel.columns; @@ -149,10 +217,12 @@ public class TransposeColumnsIntoRowsOperation extends AbstractOperation { startColumnIndex = c; - String columnName = _combinedColumnName != null && _combinedColumnName.length() > 0 ? _combinedColumnName : column.getName(); - Column newColumn = new Column(newColumns.size(), columnName); - - newColumns.add(newColumn); + if (_combinedColumnName != null) { + newColumns.add(new Column(newColumns.size(), _combinedColumnName)); + } else { + newColumns.add(new Column(newColumns.size(), _keyColumnName)); + newColumns.add(new Column(newColumns.size(), _valueColumnName)); + } columnsLeftToTranspose--; } else { @@ -172,11 +242,12 @@ public class TransposeColumnsIntoRowsOperation extends AbstractOperation { startColumnIndex = c; - String columnName = _combinedColumnName != null && _combinedColumnName.length() > 0 ? - _combinedColumnName : column.getName(); - Column newColumn = new Column(newColumns.size(), columnName); - - newColumns.add(newColumn); + if (_combinedColumnName != null) { + newColumns.add(new Column(newColumns.size(), _combinedColumnName)); + } else { + newColumns.add(new Column(newColumns.size(), _keyColumnName)); + newColumns.add(new Column(newColumns.size(), _valueColumnName)); + } break; } else { // This column is before all columns to transpose @@ -206,32 +277,52 @@ public class TransposeColumnsIntoRowsOperation extends AbstractOperation { if (c < startColumnIndex) { firstNewRow.setCell(c, cell); } else if (c == startColumnIndex || c < startColumnIndex + columnCount) { - Cell newCell; - - if (cell == null || cell.value == null) { - if (_prependColumnName && !_ignoreBlankCells) { - newCell = new Cell(column.getName() + _separator, null); + if (_combinedColumnName != null) { + Cell newCell; + if (cell == null || cell.value == null) { + if (_prependColumnName && !_ignoreBlankCells) { + newCell = new Cell(column.getName() + _separator, null); + } else { + continue; + } + } else if (_prependColumnName) { + newCell = new Cell(column.getName() + _separator + cell.value, null); } else { + newCell = cell; + } + + Row rowToModify; + if (transposedCells == 0) { + rowToModify = firstNewRow; + } else { + rowToModify = new Row(newColumns.size()); + newRows.add(rowToModify); + } + rowToModify.setCell(startColumnIndex, newCell); + + transposedCells++; + } else { + if (_ignoreBlankCells && (cell == null || cell.value == null)) { continue; } - } else if (_prependColumnName) { - newCell = new Cell(column.getName() + _separator + cell.value, null); - } else { - newCell = cell; - } - - if (transposedCells == 0) { - firstNewRow.setCell(startColumnIndex, newCell); - } else { - Row newRow = new Row(newColumns.size()); - newRow.setCell(startColumnIndex, newCell); - newRows.add(newRow); + Row rowToModify; + if (transposedCells == 0) { + rowToModify = firstNewRow; + } else { + rowToModify = new Row(newColumns.size()); + newRows.add(rowToModify); + } + rowToModify.setCell(startColumnIndex, new Cell(column.getName(), null)); + rowToModify.setCell(startColumnIndex + 1, cell); + + transposedCells++; } - transposedCells++; } else { - firstNewRow.setCell(c - columnCount + 1, cell); + firstNewRow.setCell( + c - columnCount + (_combinedColumnName != null ? 1 : 2), + cell); } } } @@ -239,7 +330,7 @@ public class TransposeColumnsIntoRowsOperation extends AbstractOperation { return new HistoryEntry( historyEntryID, project, - getBriefDescription(null), + getBriefDescription(), this, new MassRowColumnChange(newColumns, newRows) ); diff --git a/main/webapp/modules/core/scripts/views/data-table/menu-edit-cells.js b/main/webapp/modules/core/scripts/views/data-table/menu-edit-cells.js index 8c8348ddf..dbcaf7184 100644 --- a/main/webapp/modules/core/scripts/views/data-table/menu-edit-cells.js +++ b/main/webapp/modules/core/scripts/views/data-table/menu-edit-cells.js @@ -251,21 +251,44 @@ DataTableColumnHeaderUI.extendMenu(function(column, columnHeaderUI, menu) { elmts.cancelButton.click(function() { dismiss(); }); elmts.okButton.click(function() { var config = { - startColumnName: elmts.fromColumnSelect[0].value, - columnCount: elmts.toColumnSelect[0].value, - combinedColumnName: $.trim(elmts.combinedColumnNameInput[0].value), - prependColumnName: elmts.prependColumnNameCheckbox[0].checked, - separator: elmts.separatorInput[0].value, - ignoreBlankCells: elmts.ignoreBlankCellsCheckbox[0].checked + startColumnName: elmts.fromColumnSelect[0].value, + columnCount: elmts.toColumnSelect[0].value, + ignoreBlankCells: elmts.ignoreBlankCellsCheckbox[0].checked }; + + var mode = dialog.find('input[name="transpose-dialog-column-choices"]:checked')[0].value; + if (mode == "2") { + config.keyColumnName = $.trim(elmts.keyColumnNameInput[0].value); + config.valueColumnName = $.trim(elmts.valueColumnNameInput[0].value); + if (config.keyColumnName == "") { + alert("Please specify the new key column's name."); + return; + } else if (config.valueColumnName == "") { + alert("Please specify the new value column's name."); + return; + } + } else { + config.combinedColumnName = $.trim(elmts.combinedColumnNameInput[0].value); + config.prependColumnName = elmts.prependColumnNameCheckbox[0].checked; + config.separator = elmts.separatorInput[0].value; + if (config.combinedColumnName == "") { + alert("Please specify the new column's name."); + return; + } else if (config.prependColumnName && config.separator == "") { + alert("Please specify the separator between original column names and cell values."); + return; + } + } Refine.postCoreProcess( "transpose-columns-into-rows", config, null, - { modelsChanged: true } + { modelsChanged: true }, + { + onDone: dismiss + } ); - dismiss(); }); for (var i = 0; i < columns.length; i++) { diff --git a/main/webapp/modules/core/scripts/views/data-table/transpose-columns-into-rows.html b/main/webapp/modules/core/scripts/views/data-table/transpose-columns-into-rows.html index 26557acb3..9a06b90b4 100644 --- a/main/webapp/modules/core/scripts/views/data-table/transpose-columns-into-rows.html +++ b/main/webapp/modules/core/scripts/views/data-table/transpose-columns-into-rows.html @@ -1,4 +1,4 @@ -
+
Transpose Cells Across Columns into Rows
@@ -6,29 +6,53 @@ From Column To Column - Formatting Options + Transpose into -
+
- - - - + + - + + + + + - + + + + +
Combined column name
-
 Separate column name and cell value with - -
+ + + + + + + + +
Key column (containing original columns' names)
Value column (containing original cells' values)
  -
+ + + + + + + + + +
 followed by + + before the cell's value +