From 015b5a92ae8001055b164bdade90581df25a1837 Mon Sep 17 00:00:00 2001 From: Iain Sproat Date: Mon, 24 May 2010 12:36:35 +0000 Subject: [PATCH] CsvExporter is linked to the UI, and should fully work. Unit Tests now assert that null cells can be handled by CsvExporter. CHANGES.txt is now updated to reflect Issue 59. git-svn-id: http://google-refine.googlecode.com/svn/trunk@845 7d457c2a-affb-35e4-300a-418c747d4874 --- CHANGES.txt | 3 +- .../commands/project/ExportRowsCommand.java | 16 +++---- .../gridworks/exporters/CsvExporter.java | 6 ++- src/main/webapp/scripts/project/menu-bar.js | 42 ++++++++++--------- .../tests/exporters/CsvExporterTests.java | 18 ++++++++ 5 files changed, 57 insertions(+), 28 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index c206e891d..78bc88287 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -18,6 +18,7 @@ Fixes: Features: - Row/record sorting (Issue 32) +- CSV exporting (Issue 59) Changes: - Moved unit tests from JUnit to TestNG @@ -26,7 +27,7 @@ Changes: Fixes: - Issue 2: "Undo History bug" - bulk row starring and flagging operations could not be undone. -- Issue 5: "Localized Windows cause save problems for Gridworks" - +- Issue 5: "Localized Windows cause save problems for Gridworks" - Windows user IDs that contain unicode characters were not retrieved correctly. - Issue 10: "OAuth fails on sign in" - due to clock offset. - Issue 11: "missing "lang" attribute in MQL generated in schema alignment" diff --git a/src/main/java/com/metaweb/gridworks/commands/project/ExportRowsCommand.java b/src/main/java/com/metaweb/gridworks/commands/project/ExportRowsCommand.java index a215856f8..48260f483 100644 --- a/src/main/java/com/metaweb/gridworks/commands/project/ExportRowsCommand.java +++ b/src/main/java/com/metaweb/gridworks/commands/project/ExportRowsCommand.java @@ -13,6 +13,7 @@ import javax.servlet.http.HttpServletResponse; import com.metaweb.gridworks.ProjectManager; import com.metaweb.gridworks.browsing.Engine; import com.metaweb.gridworks.commands.Command; +import com.metaweb.gridworks.exporters.CsvExporter; import com.metaweb.gridworks.exporters.Exporter; import com.metaweb.gridworks.exporters.HtmlTableExporter; import com.metaweb.gridworks.exporters.TripleloaderExporter; @@ -21,32 +22,33 @@ import com.metaweb.gridworks.exporters.XlsExporter; import com.metaweb.gridworks.model.Project; public class ExportRowsCommand extends Command { - + static final protected Map s_formatToExporter = new HashMap(); - + static { s_formatToExporter.put("tripleloader", new TripleloaderExporter()); s_formatToExporter.put("html", new HtmlTableExporter()); s_formatToExporter.put("xls", new XlsExporter()); + s_formatToExporter.put("csv", new CsvExporter()); } - + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - + ProjectManager.singleton.setBusy(true); try { Project project = getProject(request); Engine engine = getEngine(request, project); String format = request.getParameter("format"); - + Exporter exporter = s_formatToExporter.get(format.toLowerCase()); if (exporter == null){ exporter = new TsvExporter(); } - + response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", exporter.getContentType()); - + if (exporter.takeWriter()) { PrintWriter writer = response.getWriter(); exporter.export(project, new Properties(), engine, writer); diff --git a/src/main/java/com/metaweb/gridworks/exporters/CsvExporter.java b/src/main/java/com/metaweb/gridworks/exporters/CsvExporter.java index d47cf713b..7212c2886 100644 --- a/src/main/java/com/metaweb/gridworks/exporters/CsvExporter.java +++ b/src/main/java/com/metaweb/gridworks/exporters/CsvExporter.java @@ -8,6 +8,7 @@ import java.util.Properties; import com.metaweb.gridworks.browsing.Engine; import com.metaweb.gridworks.browsing.FilteredRows; import com.metaweb.gridworks.browsing.RowVisitor; +import com.metaweb.gridworks.model.Cell; import com.metaweb.gridworks.model.Project; import com.metaweb.gridworks.model.Row; @@ -48,7 +49,10 @@ public class CsvExporter implements Exporter{ vals = new String[row.cells.size()]; for(int i = 0; i < vals.length; i++){ - vals[i] = row.cells.get(i).value.toString(); + Cell cell = row.cells.get(i); + if(cell != null){ + vals[i] = row.cells.get(i).value.toString(); + } } csvWriter.writeNext(vals); diff --git a/src/main/webapp/scripts/project/menu-bar.js b/src/main/webapp/scripts/project/menu-bar.js index 7b1f48200..7a6716a15 100644 --- a/src/main/webapp/scripts/project/menu-bar.js +++ b/src/main/webapp/scripts/project/menu-bar.js @@ -9,12 +9,12 @@ MenuBar.prototype.resize = function() { MenuBar.prototype._initializeUI = function() { this._mode = "inactive"; this._menuItemRecords = []; - + this._div.addClass("menu-bar").html(" "); this._innerDiv = $('
').addClass("menu-bar-inner").appendTo(this._div); var self = this; - + this._createTopLevelMenuItem("Project", [ /* { @@ -40,6 +40,10 @@ MenuBar.prototype._initializeUI = function() { "label": "Tab-Separated Value", "click": function() { self._doExportRows("tsv", "tsv"); } }, + { + "label": "Comma-Separated Value", + "click": function() { self._doExportRows("csv", "csv"); } + }, { "label": "HTML Table", "click": function() { self._doExportRows("html", "html"); } @@ -79,22 +83,22 @@ MenuBar.prototype._initializeUI = function() { click: function() { self._doLoadIntoFreebase(); } } ]); - + this._wireAllMenuItemsInactive(); }; MenuBar.prototype._createTopLevelMenuItem = function(label, submenu) { var self = this; - + var menuItem = MenuSystem.createMenuItem().text(label).appendTo(this._innerDiv); - + this._menuItemRecords.push({ menuItem: menuItem, show: function() { MenuSystem.dismissUntil(self._level); - + menuItem.addClass("menu-expanded"); - + MenuSystem.createAndShowStandardMenu( submenu, this, @@ -115,7 +119,7 @@ MenuBar.prototype._wireMenuItemInactive = function(record) { self._activateMenu(); record.show.apply(record.menuItem[0]); }; - + record.menuItem.click(function() { // because we're going to rewire the menu bar, we have to // make this asynchronous, or jquery event binding won't work. @@ -143,13 +147,13 @@ MenuBar.prototype._wireAllMenuItemsActive = function() { MenuBar.prototype._activateMenu = function() { var self = this; - + var top = this._innerDiv.offset().top; - + this._innerDiv.remove().css("top", top + "px"); this._wireAllMenuItemsActive(); this._mode = "active"; - + this._level = MenuSystem.showMenu(this._innerDiv, function() { self._deactivateMenu(); }); @@ -160,14 +164,14 @@ MenuBar.prototype._deactivateMenu = function() { .css("z-index", "auto") .css("top", "0px") .appendTo(this._div); - + this._wireAllMenuItemsInactive(); this._mode = "inactive"; }; MenuBar.prototype._doDenormalizeRecords = function() { Gridworks.postProcess( - "denormalize", + "denormalize", {}, null, { modelsChanged: true } @@ -206,12 +210,12 @@ MenuBar.prototype._doExportRows = function(format, ext) { .attr("name", "format") .attr("value", format) .appendTo(form); - + document.body.appendChild(form); window.open("about:blank", "gridworks-export"); form.submit(); - + document.body.removeChild(form); }; @@ -222,12 +226,12 @@ MenuBar.prototype._exportProject = function() { .css("display", "none") .attr("method", "post") .attr("action", "/command/export-project/" + name + ".gridworks.tar.gz") - .attr("target", "gridworks-export"); + .attr("target", "gridworks-export"); $('') .attr("name", "project") .attr("value", theProject.id) .appendTo(form); - + document.body.appendChild(form); window.open("about:blank", "gridworks-export"); @@ -241,12 +245,12 @@ MenuBar.prototype._renameProject = function() { if (name == null) { return; } - + name = $.trim(name); if (theProject.metadata.name == name || name.length == 0) { return; } - + $.ajax({ type: "POST", url: "/command/rename-project", diff --git a/tests/java/src/com/metaweb/gridworks/tests/exporters/CsvExporterTests.java b/tests/java/src/com/metaweb/gridworks/tests/exporters/CsvExporterTests.java index 808a1affd..ac43a4b39 100644 --- a/tests/java/src/com/metaweb/gridworks/tests/exporters/CsvExporterTests.java +++ b/tests/java/src/com/metaweb/gridworks/tests/exporters/CsvExporterTests.java @@ -97,6 +97,24 @@ public class CsvExporterTests { "\"row2cell0\",\"row2cell1\",\"row2cell2\"\n"); } + @Test + public void exportCsvWithEmptyCells(){ + CreateGrid(3,3); + + project.rows.get(1).cells.set(1, null); + project.rows.get(2).cells.set(0, null); + try { + SUT.export(project, options, engine, writer); + } catch (IOException e) { + Assert.fail(); + } + + Assert.assertEquals(writer.toString(), "\"column0\",\"column1\",\"column2\"\n" + + "\"row0cell0\",\"row0cell1\",\"row0cell2\"\n" + + "\"row1cell0\",,\"row1cell2\"\n" + + ",\"row2cell1\",\"row2cell2\"\n"); + } + //helper methods protected void CreateColumns(int noOfColumns){