You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/02/23 11:17:00 UTC

[19/28] incubator-taverna-common-activities git commit: Revert "temporarily empty repository"

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportConfiguration.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportConfiguration.java b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportConfiguration.java
new file mode 100644
index 0000000..1cf37ae
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportConfiguration.java
@@ -0,0 +1,416 @@
+/*******************************************************************************
+ * Copyright (C) 2009 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.spreadsheet;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationBean;
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationProperty;
+
+/**
+ * Configuration for the SpreadsheetImport activity.
+ *
+ * @author David Withers
+ */
+@ConfigurationBean(uri = SpreadsheetImportActivity.URI + "#Config")
+public class SpreadsheetImportConfiguration {
+
+	private Range columnRange;
+	private Range rowRange;
+	private String emptyCellValue;
+	private Map<String, String> columnNames;
+	private boolean allRows;
+	private boolean excludeFirstRow;
+	private boolean ignoreBlankRows;
+	private SpreadsheetEmptyCellPolicy emptyCellPolicy;
+	private SpreadsheetOutputFormat outputFormat;
+	private String csvDelimiter;
+
+	/**
+	 * Constructs a new SpreadsheetImportConfiguration.
+	 */
+	public SpreadsheetImportConfiguration() {
+		columnRange = new Range(0, 1);
+		rowRange = new Range(0, -1);
+		emptyCellValue = "";
+		columnNames = new HashMap<String, String>();
+		allRows = true;
+		excludeFirstRow = false;
+		ignoreBlankRows = false;
+		emptyCellPolicy = SpreadsheetEmptyCellPolicy.EMPTY_STRING;
+		outputFormat = SpreadsheetOutputFormat.PORT_PER_COLUMN;
+		csvDelimiter = ",";
+	}
+
+	/**
+	 * Constructs a new SpreadsheetImportConfiguration that copies the values from the given
+	 * configuration.
+	 *
+	 * @param configuration
+	 */
+	public SpreadsheetImportConfiguration(SpreadsheetImportConfiguration configuration) {
+		columnRange = new Range(configuration.columnRange);
+		rowRange = new Range(configuration.rowRange);
+		emptyCellValue = configuration.emptyCellValue;
+		columnNames = new HashMap<String, String>(configuration.columnNames);
+		allRows = configuration.allRows;
+		excludeFirstRow = configuration.excludeFirstRow;
+		emptyCellPolicy = configuration.emptyCellPolicy;
+		ignoreBlankRows = configuration.ignoreBlankRows;
+		outputFormat = configuration.outputFormat;
+		csvDelimiter = configuration.csvDelimiter;
+	}
+
+	/**
+	 * Returns the columnRange.
+	 *
+	 * @return the value of columnRange
+	 */
+	public Range getColumnRange() {
+		return columnRange;
+	}
+
+	/**
+	 * Sets the columnRange.
+	 *
+	 * @param columnRange
+	 *            the new value for columnRange
+	 */
+	@ConfigurationProperty(name = "columnRange", label = "Column Range", description = "The range of columns to be imported (e.g. columns 2 to 7")
+	public void setColumnRange(Range columnRange) {
+		this.columnRange = columnRange;
+	}
+
+	/**
+	 * Returns the rowRange.
+	 *
+	 * @return the value of rowRange
+	 */
+	public Range getRowRange() {
+		return rowRange;
+	}
+
+	/**
+	 * Sets the rowRange.
+	 *
+	 * @param rowRange
+	 *            the new value for rowRange
+	 */
+	@ConfigurationProperty(name = "rowRange", label = "Row Range", description = "The range of rows to be imported (e.g. rows 1 to 15", required = false)
+	public void setRowRange(Range rowRange) {
+		this.rowRange = rowRange;
+	}
+
+	/**
+	 * Returns the emptyCellValue. The default value is "".
+	 *
+	 * @return the value of emptyCellValue
+	 */
+	public String getEmptyCellValue() {
+		return emptyCellValue;
+	}
+
+	/**
+	 * Sets the emptyCellValue.
+	 *
+	 * @param emptyCellValue
+	 *            the new value for emptyCellValue
+	 */
+	@ConfigurationProperty(name = "emptyCellValue", label = "Empty Cell Value", description = "The value to use for empty cells. The default is \"\"", required = false)
+	public void setEmptyCellValue(String emptyCellValue) {
+		this.emptyCellValue = emptyCellValue;
+	}
+
+	/**
+	 * Returns the columnNames. The default value is an empty map.
+	 *
+	 * @return the value of columnNames
+	 */
+	public Map<String, String> getColumnNames() {
+		return columnNames;
+	}
+
+	/**
+	 * Sets the columnNames.
+	 *
+	 * @param columnNames
+	 *            the new value for columnNames
+	 */
+	public void setColumnNames(Map<String, String> columnNames) {
+		this.columnNames = columnNames;
+	}
+
+	/**
+	 * Sets the columnNames.
+	 *
+	 * @param columnNames
+	 *            the new value for columnNames
+	 */
+	@ConfigurationProperty(name = "columnNames", label = "Column Name Mapping", description = "Mapping from column to port names", required = false)
+	public void setColumnNames(Set<Mapping> columnNames) {
+		Map<String, String> columnNamesMap = new HashMap<String, String>();
+		for (Mapping mapping : columnNames) {
+			columnNamesMap.put(mapping.column, mapping.port);
+		}
+		this.columnNames = columnNamesMap;
+	}
+
+	/**
+	 * Returns the allRows property. The default value is <code>true</code>.
+	 *
+	 * @return the value of allRows
+	 */
+	public boolean isAllRows() {
+		return allRows;
+	}
+
+	/**
+	 * Sets the allRows property.
+	 *
+	 * @param allRows
+	 *            the new value for allRows
+	 */
+	@ConfigurationProperty(name = "allRows", label = "Import All Rows", description = "Imports all the rows containing data", required = false)
+	public void setAllRows(boolean allRows) {
+		this.allRows = allRows;
+	}
+
+	/**
+	 * Returns the excludeFirstRow property. The default value is <code>false</code>.
+	 *
+	 * @return the value of excludeFirstRow
+	 */
+	public boolean isExcludeFirstRow() {
+		return excludeFirstRow;
+	}
+
+	/**
+	 * Sets the excludeFirstRow property.
+	 *
+	 * @param excludeFirstRow
+	 *            the new value for excludeFirstRow
+	 */
+	@ConfigurationProperty(name = "excludeFirstRow", label = "Exclude First Row", description = "Excludes the first row from the import", required = false)
+	public void setExcludeFirstRow(boolean excludeFirstRow) {
+		this.excludeFirstRow = excludeFirstRow;
+	}
+
+	/**
+	 * Returns the ignoreBlankRows property. The default value is <code>false</code>.
+	 *
+	 * @return the value of ignoreBlankRows
+	 */
+	public boolean isIgnoreBlankRows() {
+		return ignoreBlankRows;
+	}
+
+	/**
+	 * Sets the ignoreBlankRows property.
+	 *
+	 * @param ignoreBlankRows the new value for ignoreBlankRows
+	 */
+	@ConfigurationProperty(name = "ignoreBlankRows", label = "Ignore Blank Rows", description = "Excludes blank rows from the import", required = false)
+	public void setIgnoreBlankRows(boolean ignoreBlankRows) {
+		this.ignoreBlankRows = ignoreBlankRows;
+	}
+
+	/**
+	 * Returns the emptyCellPolicy. The default value is
+	 * <code>SpreadsheetEmptyCellPolicy.EMPTY_STRING</code>.
+	 *
+	 * @return the value of emptyCellPolicy
+	 */
+	public SpreadsheetEmptyCellPolicy getEmptyCellPolicy() {
+		return emptyCellPolicy;
+	}
+
+	/**
+	 * Sets the emptyCellPolicy.
+	 *
+	 * @param emptyCellPolicy
+	 *            the new value for emptyCellPolicy
+	 */
+	@ConfigurationProperty(name = "emptyCellPolicy", label = "Empty Cell Policy", description = "Policy for handling empty cells", required = false)
+	public void setEmptyCellPolicy(SpreadsheetEmptyCellPolicy emptyCellPolicy) {
+		this.emptyCellPolicy = emptyCellPolicy;
+	}
+
+	/**
+	 * Returns the outputFormat. The default value is
+	 * <code>SpreadsheetOutputFormat.PORT_PER_COLUMN</code>.
+	 *
+	 * @return the value of outputFormat
+	 */
+	public SpreadsheetOutputFormat getOutputFormat() {
+		return outputFormat == null ? SpreadsheetOutputFormat.PORT_PER_COLUMN : outputFormat;
+	}
+
+	/**
+	 * Sets the outputFormat.
+	 *
+	 * @param outputFormat
+	 *            the new value for outputFormat
+	 */
+	@ConfigurationProperty(name = "outputFormat", label = "Output Format", description = "How the activity outputs are to be formatted", required = false)
+	public void setOutputFormat(SpreadsheetOutputFormat outputFormat) {
+		this.outputFormat = outputFormat;
+	}
+
+	/**
+	 * Returns the delimiter for CSV formatted output. The default value is
+	 * <code>","</code>.
+	 *
+	 * @return the delimiter for CSV formatted output
+	 */
+	public String getCsvDelimiter() {
+		return csvDelimiter == null ? "," : csvDelimiter;
+	}
+
+	/**
+	 * Sets the delimiter for CSV formatted output.
+	 *
+	 * @param outputFormat
+	 *            the new delimiter for CSV formatted output
+	 */
+	@ConfigurationProperty(name = "csvDelimiter", label = "CSV Delimiter", description = "The delimiter to use for CSV input files. The default is ','", required = false)
+	public void setCsvDelimiter(String csvDelimiter) {
+		this.csvDelimiter = csvDelimiter;
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + (allRows ? 1231 : 1237);
+		result = prime * result + ((columnNames == null) ? 0 : columnNames.hashCode());
+		result = prime * result + ((columnRange == null) ? 0 : columnRange.hashCode());
+		result = prime * result + ((csvDelimiter == null) ? 0 : csvDelimiter.hashCode());
+		result = prime * result + ((emptyCellPolicy == null) ? 0 : emptyCellPolicy.hashCode());
+		result = prime * result + ((emptyCellValue == null) ? 0 : emptyCellValue.hashCode());
+		result = prime * result + (excludeFirstRow ? 1231 : 1237);
+		result = prime * result + (ignoreBlankRows ? 1231 : 1237);
+		result = prime * result + ((outputFormat == null) ? 0 : outputFormat.hashCode());
+		result = prime * result + ((rowRange == null) ? 0 : rowRange.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+		if (obj == null) {
+			return false;
+		}
+		if (getClass() != obj.getClass()) {
+			return false;
+		}
+		SpreadsheetImportConfiguration other = (SpreadsheetImportConfiguration) obj;
+		if (allRows != other.allRows) {
+			return false;
+		}
+		if (columnNames == null) {
+			if (other.columnNames != null) {
+				return false;
+			}
+		} else if (!columnNames.equals(other.columnNames)) {
+			return false;
+		}
+		if (columnRange == null) {
+			if (other.columnRange != null) {
+				return false;
+			}
+		} else if (!columnRange.equals(other.columnRange)) {
+			return false;
+		}
+		if (csvDelimiter == null) {
+			if (other.csvDelimiter != null) {
+				return false;
+			}
+		} else if (!csvDelimiter.equals(other.csvDelimiter)) {
+			return false;
+		}
+		if (emptyCellPolicy == null) {
+			if (other.emptyCellPolicy != null) {
+				return false;
+			}
+		} else if (!emptyCellPolicy.equals(other.emptyCellPolicy)) {
+			return false;
+		}
+		if (emptyCellValue == null) {
+			if (other.emptyCellValue != null) {
+				return false;
+			}
+		} else if (!emptyCellValue.equals(other.emptyCellValue)) {
+			return false;
+		}
+		if (excludeFirstRow != other.excludeFirstRow) {
+			return false;
+		}
+		if (ignoreBlankRows != other.ignoreBlankRows) {
+			return false;
+		}
+		if (outputFormat == null) {
+			if (other.outputFormat != null) {
+				return false;
+			}
+		} else if (!outputFormat.equals(other.outputFormat)) {
+			return false;
+		}
+		if (rowRange == null) {
+			if (other.rowRange != null) {
+				return false;
+			}
+		} else if (!rowRange.equals(other.rowRange)) {
+			return false;
+		}
+		return true;
+	}
+
+	@ConfigurationBean(uri = SpreadsheetImportActivity.URI + "/Mapping")
+	public static class Mapping {
+		private String column, port;
+
+		public Mapping() {
+		}
+
+		public String getColumn() {
+			return column;
+		}
+
+		@ConfigurationProperty(name = "column", label = "Column", description = "The name of the column")
+		public void setColumn(String column) {
+			this.column = column;
+		}
+
+		public String getPort() {
+			return port;
+		}
+
+		@ConfigurationProperty(name = "port", label = "Port", description = "The name of the port")
+		public void setPort(String port) {
+			this.port = port;
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportHealthChecker.java b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportHealthChecker.java
new file mode 100644
index 0000000..35db532
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportHealthChecker.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (C) 2009 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.spreadsheet;
+
+import java.util.List;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import net.sf.taverna.t2.workflowmodel.Processor;
+import net.sf.taverna.t2.workflowmodel.health.HealthCheck;
+import net.sf.taverna.t2.workflowmodel.health.HealthChecker;
+import net.sf.taverna.t2.visit.VisitReport;
+import net.sf.taverna.t2.visit.VisitReport.Status;
+
+
+/**
+ * Health checker for SpreadsheetImport activities.
+ *
+ * @author David Withers
+ */
+public class SpreadsheetImportHealthChecker implements HealthChecker<SpreadsheetImportActivity> {
+
+	public boolean canVisit(Object subject) {
+		return (subject != null && subject instanceof SpreadsheetImportActivity);
+	}
+
+	public VisitReport visit(SpreadsheetImportActivity activity, List<Object> ancestors) {
+		Processor p = (Processor) VisitReport.findAncestor(ancestors, Processor.class);
+		if (p == null) {
+			return null;
+		}
+		JsonNode configuration = activity.getConfiguration();
+		if (configuration == null) {
+			return new VisitReport(HealthCheck.getInstance(), p, "Spreadsheet import has not been configured", HealthCheck.NO_CONFIGURATION, Status.SEVERE);
+		}
+		return new VisitReport(HealthCheck.getInstance(), p, "Spreadsheet OK", HealthCheck.NO_PROBLEM, Status.OK);
+	}
+
+	public boolean isTimeConsuming() {
+		return false;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetOutputFormat.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetOutputFormat.java b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetOutputFormat.java
new file mode 100644
index 0000000..d1aaca8
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetOutputFormat.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (C) 2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.spreadsheet;
+
+/**
+ * Enumeration of the formats for output of spreadsheet cell values.
+ * <p>
+ * <dl>
+ * <dt>PORT_PER_COLUMN</dt>
+ * <dd>One port of depth 1 (a list) per column</dd>
+ * <dt>SINGLE_PORT</dt>
+ * <dd>A single port of depth 0, formatted as CSV</dd>
+ * </dl>
+ *
+ * @author David Withers
+ */
+public enum SpreadsheetOutputFormat {
+	PORT_PER_COLUMN, SINGLE_PORT
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetReadException.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetReadException.java b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetReadException.java
new file mode 100644
index 0000000..9cd4ba8
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetReadException.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (C) 2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.spreadsheet;
+
+/**
+ * Exception thrown when a spreadsheet cannot be read due to an IO error or when the file format is
+ * not supported.
+ * 
+ * @author David Withers
+ */
+public class SpreadsheetReadException extends Exception {
+
+	private static final long serialVersionUID = -823966225836697180L;
+
+	/**
+	 * Constructs a new SpreadsheetReadException with null as its detail message.
+	 */
+	public SpreadsheetReadException() {
+	}
+
+	/**
+	 * Constructs a new SpreadsheetReadException with the specified detail message.
+	 * 
+	 * @param message
+	 */
+	public SpreadsheetReadException(String message) {
+		super(message);
+	}
+
+	/**
+	 * Constructs a new SpreadsheetReadException with the specified cause and a detail message of
+	 * (cause==null ? null : cause.toString()) (which typically contains the class and detail
+	 * message of cause).
+	 * 
+	 * @param cause
+	 */
+	public SpreadsheetReadException(Throwable cause) {
+		super(cause);
+	}
+
+	/**
+	 * Constructs a new SpreadsheetReadException with the specified detail message and cause.
+	 * 
+	 * @param message
+	 * @param cause
+	 */
+	public SpreadsheetReadException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetReader.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetReader.java b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetReader.java
new file mode 100644
index 0000000..79c92d1
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetReader.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (C) 2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.spreadsheet;
+
+import java.io.InputStream;
+
+/**
+ * Interface for reading a spreadsheet from an input stream.
+ * 
+ * @author David Withers
+ */
+public interface SpreadsheetReader {
+
+	/**
+	 * Reads an InputStream and passes spreadsheet cell data values, row by row, to the
+	 * rowProcessor.
+	 * 
+	 * @param inputStream
+	 *            the stream to read
+	 * @param rowProcessor
+	 *            the rowProcessor to write rows of data values to
+	 * @param rowRange
+	 *            the rows to read
+	 * @param columnRange
+	 *            the columns to read
+	 * @param ignoreBlankRows
+	 *            whether to ignore blank rows
+	 * @throws SpreadsheetReadException
+	 *             if there's an error reading the stream or the stream is not a valid spreadsheet
+	 */
+	public void read(InputStream inputStream, Range rowRange, Range columnRange, boolean ignoreBlankRows,
+			SpreadsheetRowProcessor rowProcessor) throws SpreadsheetReadException;
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetRowProcessor.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetRowProcessor.java b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetRowProcessor.java
new file mode 100644
index 0000000..98bc466
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetRowProcessor.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (C) 2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.spreadsheet;
+
+import java.util.SortedMap;
+
+/**
+ * Interface for processing a row of data from a {@link ExcelSpreadsheetReader}.
+ * 
+ * @author David Withers
+ */
+public interface SpreadsheetRowProcessor {
+
+	/**
+	 * Called by a {@link SpreadsheetReader} when all the cells of a row have been read.
+	 * 
+	 * @param rowIndex
+	 *            the index of the spreadsheet row
+	 * @param rowData
+	 *            the map of column index -> cell data for the spreadsheet row
+	 */
+	public void processRow(int rowIndex, SortedMap<Integer, String> rowData);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetUtils.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetUtils.java b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetUtils.java
new file mode 100644
index 0000000..970b3b9
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetUtils.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (C) 2009 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.spreadsheet;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Utility functions for handling spreadsheet column labels and indexes.
+ *
+ * @author David Withers
+ */
+public class SpreadsheetUtils {
+
+	/**
+	 * Converts a column label to a (0 based) column index.
+	 * <p>
+	 * Label must match the format [A-Z]+ for result to be valid.
+	 *
+	 * @param column
+	 *            the column label
+	 * @return the (0 based) column index
+	 */
+	public static int getColumnIndex(String column) {
+		int result = -1;
+		char a = 'A' - 1;
+		char[] chars = column.toCharArray();
+		for (int i = 0; i < chars.length; i++) {
+			int pos = (chars[i] - a);
+			result += pos * Math.pow(26, chars.length - i - 1);
+		}
+		return result;
+	}
+
+	/**
+	 * Converts a (0 based) column index to a column label.
+	 *
+	 * @param column
+	 *            the (0 based) column index
+	 * @return the column label
+	 */
+	public static String getColumnLabel(int column) {
+		StringBuilder result = new StringBuilder();
+		while (column >= 0) {
+			result.insert(0, (char) ((char) (column % 26) + 'A'));
+			column = (column / 26) - 1;
+		}
+		return result.toString();
+	}
+
+	/**
+	 * Returns the port name for the column label.
+	 *
+	 * @param columnLabel
+	 *            the column label
+	 * @param columnNameMapping
+	 * @return the port name for the column label
+	 */
+	public static String getPortName(String columnLabel, JsonNode jsonNode) {
+		String portName = columnLabel;
+		if (jsonNode != null && jsonNode.has("columnNames")) {
+			for (JsonNode mappingNode : jsonNode.get("columnNames")) {
+				if (columnLabel.equals(mappingNode.get("column").textValue())) {
+					portName = mappingNode.get("port").textValue();
+					break;
+				}
+			}
+		}
+		return portName;
+	}
+
+	/**
+	 * Returns the port name for the column index.
+	 *
+	 * @param columnIndex
+	 *            the column index
+	 * @param columnNameMapping
+	 * @return the port name for the column index
+	 */
+	public static String getPortName(int columnIndex, JsonNode jsonNode) {
+		return getPortName(getColumnLabel(columnIndex), jsonNode);
+	}
+
+	/**
+	 * @param jsonNode
+	 * @return
+	 */
+	public static Range getRange(JsonNode jsonNode) {
+		Range range = new Range();
+		if (jsonNode != null) {
+			if (jsonNode.has("start")) {
+				range.setStart(jsonNode.get("start").intValue());
+			}
+			if (jsonNode.has("end")) {
+				range.setEnd(jsonNode.get("end").intValue());
+			}
+			if (jsonNode.has("excludes")) {
+				List<Range> excludes = new ArrayList<>();
+				for (JsonNode rangeNode : jsonNode.get("excludes")) {
+					excludes.add(getRange(rangeNode));
+				}
+				range.setExcludes(excludes);
+			}
+		}
+		return range;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/package.html
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/package.html b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/package.html
new file mode 100644
index 0000000..356b9b2
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/java/net/sf/taverna/t2/activities/spreadsheet/package.html
@@ -0,0 +1,3 @@
+<body>
+Contains the activity classes required to include spreadsheet files within a DataFlow.
+</body>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker b/taverna-spreadsheet-import-activity/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker
new file mode 100644
index 0000000..e8dfa9a
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker
@@ -0,0 +1 @@
+net.sf.taverna.t2.activities.spreadsheet.SpreadsheetImportHealthChecker
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/resources/META-INF/spring/spreadsheetimport-activity-context-osgi.xml
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/resources/META-INF/spring/spreadsheetimport-activity-context-osgi.xml b/taverna-spreadsheet-import-activity/src/main/resources/META-INF/spring/spreadsheetimport-activity-context-osgi.xml
new file mode 100644
index 0000000..577b30b
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/resources/META-INF/spring/spreadsheetimport-activity-context-osgi.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans:beans xmlns="http://www.springframework.org/schema/osgi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:beans="http://www.springframework.org/schema/beans"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                                 http://www.springframework.org/schema/beans/spring-beans.xsd
+                                 http://www.springframework.org/schema/osgi
+                                 http://www.springframework.org/schema/osgi/spring-osgi.xsd">
+
+	<service ref="spreadsheetImportActivityHealthChecker" interface="net.sf.taverna.t2.workflowmodel.health.HealthChecker" />
+
+	<service ref="spreadsheetImportActivityFactory" interface="net.sf.taverna.t2.workflowmodel.processor.activity.ActivityFactory" />
+
+	<reference id="edits" interface="net.sf.taverna.t2.workflowmodel.Edits" />
+
+</beans:beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/resources/META-INF/spring/spreadsheetimport-activity-context.xml
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/resources/META-INF/spring/spreadsheetimport-activity-context.xml b/taverna-spreadsheet-import-activity/src/main/resources/META-INF/spring/spreadsheetimport-activity-context.xml
new file mode 100644
index 0000000..031ab52
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/resources/META-INF/spring/spreadsheetimport-activity-context.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                           http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<bean id="spreadsheetImportActivityHealthChecker" class="net.sf.taverna.t2.activities.spreadsheet.SpreadsheetImportHealthChecker" />
+
+	<bean id="spreadsheetImportActivityFactory" class="net.sf.taverna.t2.activities.spreadsheet.SpreadsheetImportActivityFactory">
+		<property name="edits" ref="edits" />
+	</bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/main/resources/schema.json
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/main/resources/schema.json b/taverna-spreadsheet-import-activity/src/main/resources/schema.json
new file mode 100644
index 0000000..b351137
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/main/resources/schema.json
@@ -0,0 +1,126 @@
+{
+    "$schema": "http://json-schema.org/draft-03/schema#",
+    "id": "http://ns.taverna.org.uk/2010/activity/spreadsheet-import.schema.json",
+    "title": "Spreadsheet import activity configuration",
+    "type": "object",
+    "properties": {
+        "@context": {
+            "description": "JSON-LD context for interpreting the configuration as RDF",
+            "required": true,
+            "enum": ["http://ns.taverna.org.uk/2010/activity/spreadsheet-import.context.json"]
+        },
+        "columnRange": {
+            "title": "Column Range",
+            "description": "The range of columns to be imported (e.g. columns 2 to 7)",
+            "type": "object",
+            "$ref": "#/definitions/range",
+            "default": {"start": 0, "end": 1},
+            "required": true
+        },
+        "rowRange": {
+            "title": "Row Range",
+            "description": "The range of rows to be imported (e.g. rows 1 to 15)",
+            "type": "object",
+            "$ref": "#/definitions/range",
+            "default": {"start": 0, "end": -1},
+            "required": true
+        },
+        "emptyCellValue": {
+            "title": "Empty Cell Value",
+            "description": "The value to use for empty cells. The default is \"\"",
+            "type": "string",
+            "default": "",
+            "required": true
+        },
+        "columnNames": {
+            "title": "Column Name Mapping",
+            "description": "Mapping from column to port names",
+            "type": "array",
+            "elements": {
+            	"type": "object",
+                "properties": {
+           			"column": {
+            			"title": "Column",
+            			"description": "The name of the column",
+            			"type": "string",
+ 		         		"required": true
+            		},
+           			"port": {
+            			"title": "Port",
+            			"description": "The name of the port",
+            			"type": "string",
+		          		"required": true
+           			}
+            	}
+            },
+            "required": false
+        },
+        "allRows": {
+            "title": "Import All Rows",
+            "description": "Imports all the rows containing data",
+            "type": "boolean",
+            "default": true,
+            "required": true
+        },
+        "excludeFirstRow": {
+            "title": "Exclude First Row",
+            "description": "Excludes the first row from the import",
+            "type": "boolean",
+            "default": false,
+            "required": true
+        },
+        "ignoreBlankRows": {
+            "title": "Ignore Blank Rows",
+            "description": "Excludes blank rows from the import",
+            "type": "boolean",
+            "default": false,
+            "required": true
+        },
+        "emptyCellPolicy": {
+            "title": "Empty Cell Policy",
+            "description": "Policy for handling empty cells",
+            "enum": ["EMPTY_STRING", "USER_DEFINED", "GENERATE_ERROR"],
+            "default": "EMPTY_STRING",
+            "required": true
+        },
+        "outputFormat": {
+            "title": "Output Format",
+            "description": "How the activity outputs are to be formatted",
+            "enum": ["PORT_PER_COLUMN", "SINGLE_PORT"],
+            "default": "PORT_PER_COLUMN",
+            "required": true
+        },
+        "csvDelimiter": {
+            "title": "CSV Delimiter",
+            "description": "The delimiter to use for CSV input files. The default is ','",
+            "type": "string",
+            "default": ",",
+            "required": true
+        }
+    },
+    "definitions": {
+    	"range": {
+            "properties": {
+           		"start": {
+            		"title": "Start",
+            		"description": "The start of the range",
+            		"type": "integer",
+		          	"required": true
+           		},
+           		"end": {
+            		"title": "End",
+            		"description": "The end of the range",
+            		"type": "integer",
+ 		         	"required": true
+            	},
+           		"excludes": {
+            		"title": "Excludes Ranges",
+            		"description": "The ranges to exclude from this range",
+            		"type": "array",
+             		"items": { "type": "object", "$ref": "#/definitions/range" },
+ 		         	"required": false
+            	}
+            }
+    	}
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/CSVSpreadsheetReaderTest.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/CSVSpreadsheetReaderTest.java b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/CSVSpreadsheetReaderTest.java
new file mode 100644
index 0000000..fc04468
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/CSVSpreadsheetReaderTest.java
@@ -0,0 +1,259 @@
+package net.sf.taverna.t2.activities.spreadsheet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.Map.Entry;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class CSVSpreadsheetReaderTest {
+
+	private SpreadsheetReader spreadsheetReader;
+
+	@Before
+	public void setUp() throws Exception {
+		spreadsheetReader = new CSVSpreadsheetReader();
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.OdfSpreadsheetReader#read(java.io.InputStream, net.sf.taverna.t2.activities.spreadsheet.Range, net.sf.taverna.t2.activities.spreadsheet.Range, net.sf.taverna.t2.activities.spreadsheet.SpreadsheetRowProcessor)}.
+	 */
+	@Test
+	public void testRead() throws Exception {
+		String[] testFiles2 = new String[] { "/test-spreadsheet.csv" };
+		for (int i = 0; i < testFiles2.length; i++) {
+			final List<Integer> rows = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 5));
+			spreadsheetReader.read(getClass().getResourceAsStream(testFiles2[i]), new Range(0, 5), new Range(0, 4), false,
+					new SpreadsheetRowProcessor() {
+
+						public void processRow(int rowIndex, SortedMap<Integer, String> row) {
+							assertTrue(rows.remove((Integer) rowIndex));
+							List<Integer> columns = new ArrayList<Integer>(Arrays.asList(0, 1, 2,
+									3, 4));
+							for (Entry<Integer, String> cell : row.entrySet()) {
+								assertTrue(columns.remove(cell.getKey()));
+								if (rowIndex == 0) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 1) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 2) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("TRUE", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("15/06/09", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertNull(cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("2", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 3 || rowIndex == 4) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("X", cell.getValue());
+									}
+								} else {
+									assertNull(cell.getValue());
+								}
+							}
+							assertTrue(columns.isEmpty());
+						}
+					});
+			assertTrue(rows.isEmpty());
+
+		}
+
+	}
+
+	@Test(expected=SpreadsheetReadException.class)
+	public void testReadException() throws Exception {
+		spreadsheetReader.read(new InputStream() {
+			public int read() throws IOException {
+				throw new IOException();
+			}			
+		}, new Range(0,1), new Range(0,1), false, new SpreadsheetRowProcessor() {
+			public void processRow(int rowIndex, SortedMap<Integer, String> rowData) {				
+			}			
+		});
+	}	
+	
+	@Test
+	public void testReadAllRows() throws Exception {
+		String[] testFiles2 = new String[] { "/test-spreadsheet.csv" };
+		for (int i = 0; i < testFiles2.length; i++) {
+			final List<Integer> rows = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7,
+					8, 9, 10, 11, 12, 13, 14));
+			spreadsheetReader.read(getClass().getResourceAsStream(testFiles2[i]), new Range(0, -1), new Range(0, 4), false,
+					new SpreadsheetRowProcessor() {
+
+						public void processRow(int rowIndex, SortedMap<Integer, String> row) {
+							assertTrue(rows.remove((Integer) rowIndex));
+							List<Integer> columns = new ArrayList<Integer>(Arrays.asList(0, 1, 2,
+									3, 4));
+							for (Entry<Integer, String> cell : row.entrySet()) {
+								assertTrue(columns.remove(cell.getKey()));
+								if (rowIndex == 0) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 1) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 2) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("TRUE", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("15/06/09", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertNull(cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("2", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 3 || rowIndex == 4) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("X", cell.getValue());
+									}
+								} else if (rowIndex == 5 || rowIndex == 6 || rowIndex == 7
+										|| rowIndex == 8) {
+									assertNull(cell.getValue());
+								} else if (rowIndex == 9 || rowIndex == 10 || rowIndex == 11
+										|| rowIndex == 12 || rowIndex == 13 || rowIndex == 14) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("y", cell.getValue());
+									}
+								}
+							}
+							assertTrue(columns.isEmpty());
+						}
+					});
+			assertTrue(rows.isEmpty());
+		}
+	}
+
+	@Test
+	public void testIgnoreBlankRows() throws Exception {
+		String[] testFiles2 = new String[] { "/test-spreadsheet.csv" };
+		for (int i = 0; i < testFiles2.length; i++) {
+			final List<Integer> rows = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 9, 10, 11, 12, 13, 14));
+			spreadsheetReader.read(getClass().getResourceAsStream(testFiles2[i]), new Range(0, -1), new Range(0, 4), true,
+					new SpreadsheetRowProcessor() {
+
+						public void processRow(int rowIndex, SortedMap<Integer, String> row) {
+							assertTrue(rows.remove((Integer) rowIndex));
+							List<Integer> columns = new ArrayList<Integer>(Arrays.asList(0, 1, 2,
+									3, 4));
+							for (Entry<Integer, String> cell : row.entrySet()) {
+								assertTrue(columns.remove(cell.getKey()));
+								if (rowIndex == 0) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 1) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 2) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("TRUE", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("15/06/09", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertNull(cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("2", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 3 || rowIndex == 4) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("X", cell.getValue());
+									}
+								} else if (rowIndex == 9 || rowIndex == 10 || rowIndex == 11
+										|| rowIndex == 12 || rowIndex == 13 || rowIndex == 14) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("y", cell.getValue());
+									}
+								}
+							}
+							assertTrue(columns.isEmpty());
+						}
+					});
+			assertTrue(rows.isEmpty());
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/ExcelSpreadsheetReaderTest.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/ExcelSpreadsheetReaderTest.java b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/ExcelSpreadsheetReaderTest.java
new file mode 100644
index 0000000..90960b6
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/ExcelSpreadsheetReaderTest.java
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (C) 2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.spreadsheet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.Map.Entry;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link net.sf.taverna.t2.activities.spreadsheet.ExcelSpreadsheetReader}.
+ * 
+ * @author David Withers
+ */
+public class ExcelSpreadsheetReaderTest {
+
+	private SpreadsheetReader spreadsheetReader;
+	private String[] testFiles = new String[] {"/test-spreadsheet.xlsx" , "/test-spreadsheet.xls"};
+
+	@Before
+	public void setUp() throws Exception {
+		spreadsheetReader = new ExcelSpreadsheetReader();
+	}
+
+	/**
+	 * Test method for
+	 * {@link net.sf.taverna.t2.activities.spreadsheet.ExcelSpreadsheetReader#read(java.io.InputStream, net.sf.taverna.t2.activities.spreadsheet.SpreadsheetRowProcessor)}
+	 * 
+	 * @throws Exception
+	 */
+	@Test
+	public void testRead() throws Exception {
+		for (int i = 0; i < testFiles.length; i++) {
+			final List<Integer> rows = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 5));
+			spreadsheetReader.read(getClass().getResourceAsStream(testFiles[i]), new Range(0, 5),
+					new Range(0, 4), false, new SpreadsheetRowProcessor() {
+
+						public void processRow(int rowIndex, SortedMap<Integer, String> row) {
+							assertTrue(rows.remove((Integer) rowIndex));
+							List<Integer> columns = new ArrayList<Integer>(Arrays.asList(0, 1, 2,
+									3, 4));
+							for (Entry<Integer, String> cell : row.entrySet()) {
+								assertTrue(columns.remove(cell.getKey()));
+								if (rowIndex == 0) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 1) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 2) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("true", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertTrue("Unexpected date format: " + cell.getValue(), cell.getValue().matches("Mon Jun 15 00:00:00 ....? 2009"));
+									} else if (cell.getKey().equals(2)) {
+										assertNull(cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("2.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 3 || rowIndex == 4) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("X", cell.getValue());
+									}
+								} else if (rowIndex == 5) {
+									assertNull(cell.getValue());
+								}
+							}
+							assertTrue(columns.isEmpty());
+						}
+					});
+			assertTrue(rows.isEmpty());
+		}
+	}
+
+	@Test(expected=SpreadsheetReadException.class)
+	public void testReadIOException() throws Exception {
+		spreadsheetReader.read(new InputStream() {
+			public int read() throws IOException {
+				throw new IOException();
+			}			
+		}, new Range(0,1), new Range(0,1), false, new SpreadsheetRowProcessor() {
+			public void processRow(int rowIndex, SortedMap<Integer, String> rowData) {				
+			}			
+		});
+	}	
+	
+	@Test(expected=SpreadsheetReadException.class)
+	public void testReadInvalidFormatException() throws Exception {
+		spreadsheetReader.read(getClass().getResourceAsStream("/test-spreadsheet.ods"), new Range(0,1), new Range(0,1), false, new SpreadsheetRowProcessor() {
+			public void processRow(int rowIndex, SortedMap<Integer, String> rowData) {				
+			}			
+		});
+	}	
+	
+	@Test(expected=SpreadsheetReadException.class)
+	public void testReadIllegalArgumentException() throws Exception {
+		spreadsheetReader.read(getClass().getResourceAsStream("/test-spreadsheet.csv"), new Range(0,1), new Range(0,1), false, new SpreadsheetRowProcessor() {
+			public void processRow(int rowIndex, SortedMap<Integer, String> rowData) {				
+			}			
+		});
+	}	
+	
+	@Test
+	public void testReadAllRows() throws Exception {
+		for (int i = 0; i < testFiles.length; i++) {
+			final List<Integer> rows = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7,
+					8, 9, 10, 11, 12, 13, 14));
+			spreadsheetReader.read(getClass().getResourceAsStream(testFiles[i]), new Range(0, -1), new Range(0, 4), false,
+					new SpreadsheetRowProcessor() {
+
+						public void processRow(int rowIndex, SortedMap<Integer, String> row) {
+							assertTrue(rows.remove((Integer) rowIndex));
+							List<Integer> columns = new ArrayList<Integer>(Arrays.asList(0, 1, 2,
+									3, 4));
+							for (Entry<Integer, String> cell : row.entrySet()) {
+								assertTrue(columns.remove(cell.getKey()));
+								if (rowIndex == 0) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 1) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 2) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("true", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertTrue("Unexpected date format: " + cell.getValue(), cell.getValue().matches("Mon Jun 15 00:00:00 ....? 2009"));
+									} else if (cell.getKey().equals(2)) {
+										assertNull(cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("2.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 3 || rowIndex == 4) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("X", cell.getValue());
+									}
+								} else if (rowIndex == 5 || rowIndex == 6 || rowIndex == 7
+										|| rowIndex == 8) {
+									assertNull(cell.getValue());
+								} else if (rowIndex == 9 || rowIndex == 10 || rowIndex == 11
+										|| rowIndex == 12 || rowIndex == 13 || rowIndex == 14) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("y", cell.getValue());
+									}
+								}
+							}
+							assertTrue(columns.isEmpty());
+						}
+					});
+			assertTrue(rows.isEmpty());
+		}
+	}
+
+	@Test
+	public void testIgnoreBlankRows() throws Exception {
+		for (int i = 0; i < testFiles.length; i++) {
+			final List<Integer> rows = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 9, 10, 11, 12, 13, 14));
+			spreadsheetReader.read(getClass().getResourceAsStream(testFiles[i]), new Range(0, -1), new Range(0, 4), true,
+					new SpreadsheetRowProcessor() {
+
+						public void processRow(int rowIndex, SortedMap<Integer, String> row) {
+							assertTrue(rows.remove((Integer) rowIndex));
+							List<Integer> columns = new ArrayList<Integer>(Arrays.asList(0, 1, 2,
+									3, 4));
+							for (Entry<Integer, String> cell : row.entrySet()) {
+								assertTrue(columns.remove(cell.getKey()));
+								if (rowIndex == 0) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 1) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 2) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("true", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertTrue("Unexpected date format: " + cell.getValue(), cell.getValue().matches("Mon Jun 15 00:00:00 ....? 2009"));
+									} else if (cell.getKey().equals(2)) {
+										assertNull(cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("2.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 3 || rowIndex == 4) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("X", cell.getValue());
+									}
+								} else if (rowIndex == 9 || rowIndex == 10 || rowIndex == 11
+										|| rowIndex == 12 || rowIndex == 13 || rowIndex == 14) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("y", cell.getValue());
+									}
+								}
+							}
+							assertTrue(columns.isEmpty());
+						}
+					});
+			assertTrue(rows.isEmpty());
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/ODFSpreadsheetReaderTest.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/ODFSpreadsheetReaderTest.java b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/ODFSpreadsheetReaderTest.java
new file mode 100644
index 0000000..055ef09
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/ODFSpreadsheetReaderTest.java
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright (C) 2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.spreadsheet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.Map.Entry;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link net.sf.taverna.t2.activities.spreadsheet.ODFSpreadsheetReader}.
+ *
+ * @author David Withers
+ */
+public class ODFSpreadsheetReaderTest {
+
+	private SpreadsheetReader spreadsheetReader;
+
+	@Before
+	public void setUp() throws Exception {
+		spreadsheetReader = new ODFSpreadsheetReader();
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.OdfSpreadsheetReader#read(java.io.InputStream, net.sf.taverna.t2.activities.spreadsheet.Range, net.sf.taverna.t2.activities.spreadsheet.Range, net.sf.taverna.t2.activities.spreadsheet.SpreadsheetRowProcessor)}.
+	 */
+	@Test
+	public void testRead() throws Exception {
+		String[] testFiles2 = new String[] { "/test-spreadsheet.ods" };
+		for (int i = 0; i < testFiles2.length; i++) {
+			final List<Integer> rows = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 5));
+			spreadsheetReader.read(getClass().getResourceAsStream(testFiles2[i]), new Range(0, 5), new Range(0, 4), false,
+					new SpreadsheetRowProcessor() {
+
+						public void processRow(int rowIndex, SortedMap<Integer, String> row) {
+							assertTrue(rows.remove((Integer) rowIndex));
+							List<Integer> columns = new ArrayList<Integer>(Arrays.asList(0, 1, 2,
+									3, 4));
+							for (Entry<Integer, String> cell : row.entrySet()) {
+								assertTrue(columns.remove(cell.getKey()));
+								if (rowIndex == 0) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 1) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 2) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("true", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("2009-06-15", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertNull(cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("2.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 3 || rowIndex == 4) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("X", cell.getValue());
+									}
+								} else {
+									assertNull(cell.getValue());
+								}
+							}
+							assertTrue(columns.isEmpty());
+						}
+					});
+			assertTrue(rows.isEmpty());
+
+		}
+
+	}
+
+	@Test(expected=SpreadsheetReadException.class)
+	public void testReadException() throws Exception {
+		spreadsheetReader.read(getClass().getResourceAsStream("/test-spreadsheet.csv"), new Range(0,1), new Range(0,1), false, new SpreadsheetRowProcessor() {
+			public void processRow(int rowIndex, SortedMap<Integer, String> rowData) {				
+			}
+			
+		});
+	}	
+	
+	@Test(expected=RuntimeException.class)
+	public void testReadRuntimeException() throws Exception {
+		spreadsheetReader.read(new InputStream() {
+			public int read() throws IOException {
+				throw new RuntimeException();
+			}			
+		}, new Range(0,1), new Range(0,1), false, new SpreadsheetRowProcessor() {
+			public void processRow(int rowIndex, SortedMap<Integer, String> rowData) {				
+			}			
+		});
+	}	
+	
+	@Test
+	public void testReadAllRows() throws Exception {
+		String[] testFiles2 = new String[] { "/test-spreadsheet.ods" };
+		for (int i = 0; i < testFiles2.length; i++) {
+			final List<Integer> rows = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7,
+					8, 9, 10, 11, 12, 13, 14));
+			spreadsheetReader.read(getClass().getResourceAsStream(testFiles2[i]), new Range(0, -1), new Range(0, 4), false,
+					new SpreadsheetRowProcessor() {
+
+						public void processRow(int rowIndex, SortedMap<Integer, String> row) {
+							assertTrue(rows.remove((Integer) rowIndex));
+							List<Integer> columns = new ArrayList<Integer>(Arrays.asList(0, 1, 2,
+									3, 4));
+							for (Entry<Integer, String> cell : row.entrySet()) {
+								assertTrue(columns.remove(cell.getKey()));
+								if (rowIndex == 0) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 1) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 2) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("true", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("2009-06-15", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertNull(cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("2.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 3 || rowIndex == 4) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("X", cell.getValue());
+									}
+								} else if (rowIndex == 5 || rowIndex == 6 || rowIndex == 7
+										|| rowIndex == 8) {
+									assertNull(cell.getValue());
+								} else if (rowIndex == 9 || rowIndex == 10 || rowIndex == 11
+										|| rowIndex == 12 || rowIndex == 13 || rowIndex == 14) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("y", cell.getValue());
+									}
+								}
+							}
+							assertTrue(columns.isEmpty());
+						}
+					});
+			assertTrue(rows.isEmpty());
+		}
+	}
+
+	@Test
+	public void testIgnoreBlankRows() throws Exception {
+		String[] testFiles2 = new String[] { "/test-spreadsheet.ods" };
+		for (int i = 0; i < testFiles2.length; i++) {
+			final List<Integer> rows = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 9, 10, 11, 12, 13, 14));
+			spreadsheetReader.read(getClass().getResourceAsStream(testFiles2[i]), new Range(0, -1), new Range(0, 4), true,
+					new SpreadsheetRowProcessor() {
+
+						public void processRow(int rowIndex, SortedMap<Integer, String> row) {
+							assertTrue(rows.remove((Integer) rowIndex));
+							List<Integer> columns = new ArrayList<Integer>(Arrays.asList(0, 1, 2,
+									3, 4));
+							for (Entry<Integer, String> cell : row.entrySet()) {
+								assertTrue(columns.remove(cell.getKey()));
+								if (rowIndex == 0) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 1) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("A", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("5.0", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertEquals("C", cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("1.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 2) {
+									if (cell.getKey().equals(0)) {
+										assertEquals("true", cell.getValue());
+									} else if (cell.getKey().equals(1)) {
+										assertEquals("2009-06-15", cell.getValue());
+									} else if (cell.getKey().equals(2)) {
+										assertNull(cell.getValue());
+									} else if (cell.getKey().equals(3)) {
+										assertEquals("2.0", cell.getValue());
+									} else {
+										assertNull(cell.getValue());
+									}
+								} else if (rowIndex == 3 || rowIndex == 4) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("X", cell.getValue());
+									}
+								} else if (rowIndex == 9 || rowIndex == 10 || rowIndex == 11
+										|| rowIndex == 12 || rowIndex == 13 || rowIndex == 14) {
+									if (cell.getKey().equals(4)) {
+										assertNull(cell.getValue());
+									} else {
+										assertEquals("y", cell.getValue());
+									}
+								}
+							}
+							assertTrue(columns.isEmpty());
+						}
+					});
+			assertTrue(rows.isEmpty());
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/RangeTest.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/RangeTest.java b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/RangeTest.java
new file mode 100644
index 0000000..ffe9032
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/RangeTest.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (C) 2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.spreadsheet;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link net.sf.taverna.t2.activities.spreadsheet.Range}.
+ * 
+ * @author David Withers
+ */
+public class RangeTest {
+
+	private Range range;
+
+	@Before
+	public void setUp() throws Exception {
+		range = new Range(1, 5);
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.Range#Range(int, int)}.
+	 */
+	@Test
+	public void testRangeIntInt() {
+		Range range = new Range(3, 9);
+		assertEquals(3, range.getStart());
+		assertEquals(9, range.getEnd());
+	}
+
+	/**
+	 * Test method for
+	 * {@link net.sf.taverna.t2.activities.spreadsheet.Range#Range(int, int, net.sf.taverna.t2.activities.spreadsheet.Range)}
+	 * .
+	 */
+	@Test
+	public void testRangeIntIntRange() {
+		Range range = new Range(0, 12, new Range(3, 9));
+		assertEquals(0, range.getStart());
+		assertEquals(12, range.getEnd());
+		assertTrue(range.contains(0));
+		assertTrue(range.contains(2));
+		assertFalse(range.contains(5));
+	}
+
+	/**
+	 * Test method for
+	 * {@link net.sf.taverna.t2.activities.spreadsheet.Range#Range(int, int, java.util.List)}.
+	 */
+	@Test
+	public void testRangeIntIntListOfRange() {
+		Range range = new Range(-2, 12, Arrays.asList(new Range(3, 5), new Range(10, 11)));
+		assertEquals(-2, range.getStart());
+		assertEquals(12, range.getEnd());
+		assertTrue(range.contains(-2));
+		assertTrue(range.contains(-0));
+		assertTrue(range.contains(6));
+		assertTrue(range.contains(12));
+		assertFalse(range.contains(4));
+		assertFalse(range.contains(11));
+	}
+
+	/**
+	 * Test method for
+	 * {@link net.sf.taverna.t2.activities.spreadsheet.Range#Range(net.sf.taverna.t2.activities.spreadsheet.Range)}
+	 * .
+	 */
+	@Test
+	public void testRangeRange() {
+		Range rangeCopy = new Range(range);
+		assertEquals(rangeCopy, range);
+		assertEquals(range.getStart(), rangeCopy.getStart());
+		assertEquals(range.getEnd(), rangeCopy.getEnd());
+		range = new Range(0, 7, range);
+		rangeCopy = new Range(range);
+		assertFalse(rangeCopy.equals(new Range(2,3)));
+		assertEquals(rangeCopy, range);
+		assertEquals(range.getStart(), rangeCopy.getStart());
+		assertEquals(range.getEnd(), rangeCopy.getEnd());
+		assertArrayEquals(range.getRangeValues(), rangeCopy.getRangeValues());
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.Range#contains(int)}.
+	 */
+	@Test
+	public void testContains() {
+		assertTrue(range.contains(2));
+		assertFalse(range.contains(7));
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.Range#getRangeValues()}.
+	 */
+	@Test
+	public void testGetRangeValues() {
+		assertArrayEquals(new int[] { 1, 2, 3, 4, 5 }, range.getRangeValues());
+		Range range2 = new Range(0, 7, range);
+		assertArrayEquals(new int[] { 0, 6, 7 }, range2.getRangeValues());
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.Range#getStart()}.
+	 */
+	@Test
+	public void testGetStart() {
+		assertEquals(1, range.getStart());
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.Range#setStart(int)}.
+	 */
+	@Test
+	public void testSetStart() {
+		range.setStart(2);
+		assertEquals(2, range.getStart());
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.Range#getEnd()}.
+	 */
+	@Test
+	public void testGetEnd() {
+		assertEquals(5, range.getEnd());
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.Range#setEnd(int)}.
+	 */
+	@Test
+	public void testSetEnd() {
+		range.setEnd(7);
+		assertEquals(7, range.getEnd());
+	}
+
+	/**
+	 * Test method for
+	 * {@link net.sf.taverna.t2.activities.spreadsheet.Range#addExclude(net.sf.taverna.t2.activities.spreadsheet.Range)}
+	 * .
+	 */
+	@Test
+	public void testAddExclude() {
+		range.addExclude(new Range(4, 4));
+		assertTrue(range.contains(2));
+		assertTrue(range.contains(5));
+		assertFalse(range.contains(4));
+	}
+
+	/**
+	 * Test method for
+	 * {@link net.sf.taverna.t2.activities.spreadsheet.Range#removeExclude(net.sf.taverna.t2.activities.spreadsheet.Range)}
+	 * .
+	 */
+	@Test
+	public void testRemoveExclude() {
+		range.addExclude(new Range(4, 4));
+		range.removeExclude(new Range(4, 4));
+		assertTrue(range.contains(4));
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.Range#toString()}.
+	 */
+	@Test
+	public void testToString() {
+		assertEquals("[1..5]", range.toString());
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportActivityFactoryTest.java
----------------------------------------------------------------------
diff --git a/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportActivityFactoryTest.java b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportActivityFactoryTest.java
new file mode 100644
index 0000000..f97eb0b
--- /dev/null
+++ b/taverna-spreadsheet-import-activity/src/test/java/net/sf/taverna/t2/activities/spreadsheet/SpreadsheetImportActivityFactoryTest.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (C) 2010 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.spreadsheet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URI;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ *
+ * @author David Withers
+ */
+public class SpreadsheetImportActivityFactoryTest {
+
+	private SpreadsheetImportActivityFactory factory;
+
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@Before
+	public void setUp() throws Exception {
+		factory = new SpreadsheetImportActivityFactory();
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.SpreadsheetImportActivity#createActivity()}.
+	 */
+	@Test
+	public void testCreateActivity() {
+		SpreadsheetImportActivity createActivity = factory.createActivity();
+		assertNotNull(createActivity);
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.spreadsheet.SpreadsheetImportActivity#getActivityType()}.
+	 */
+	@Test
+	public void testGetActivityURI() {
+		assertEquals(URI.create(SpreadsheetImportActivity.URI), factory.getActivityType());
+	}
+
+	/**
+	 * Test method for {@link net.sf.taverna.t2.activities.rshell.RshellActivityFactory#getActivityConfigurationSchema()}.
+	 */
+	@Test
+	public void testGetActivityConfigurationSchema() {
+		assertTrue(factory.getActivityConfigurationSchema() instanceof JsonNode);
+	}
+
+}