package matrix.general;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import matrix.implementations.binary.BinaryDataMatrixInstance;
import matrix.implementations.binary.BinaryDataMatrixWriter;
import matrix.implementations.csv.CSVDataMatrixWriter;
import matrix.implementations.database.DatabaseDataMatrixWriter;
import org.molgenis.core.MolgenisFile;
import org.molgenis.data.Data;
import org.molgenis.framework.db.Database;
import org.molgenis.framework.db.DatabaseException;
import org.molgenis.util.CsvWriter;
import org.molgenis.util.SimpleTuple;
import org.molgenis.util.Tuple;
import decorators.NameConvention;
import filehandling.generic.PerformUpload;
public class Importer
{
public void performImport(Tuple request, Data data, Database db) throws Exception
{
File importFile = null;
// special: upload existing xQTL binary matrix
if (request.getString("__action").equals("uploadBinary"))
{
importFile = request.getFile("uploadBinaryFile");
// update this 'Data' with the info from the binary file
// but not name/investigationname
// additionally, set storage to Binary :)
BinaryDataMatrixInstance bmi = new BinaryDataMatrixInstance(importFile);
data.setFeatureType(bmi.getData().getFeatureType());
data.setTargetType(bmi.getData().getTargetType());
data.setValueType(bmi.getData().getValueType());
data.setStorage("Binary");
db.update(data);
// code from
// /molgenis_apps/modules/xgap/matrix/implementations/binary/BinaryDataMatrixWriter.java
// upload as a MolgenisFile, type 'BinaryDataMatrix'
HashMap<String, String> extraFields = new HashMap<String, String>();
extraFields.put("data_" + Data.ID, data.getId().toString());
extraFields.put("data_" + Data.NAME, data.getName());
PerformUpload.doUpload(db, true, data.getName() + ".bin", "BinaryDataMatrix", importFile, extraFields,
false);
return;
}
if (request.getString("__action").equals("uploadTextArea"))
{
String content = request.getString("inputTextArea");
File inputTextAreaContent = new File(System.getProperty("java.io.tmpdir") + File.separator
+ "tmpTextAreaInput" + System.nanoTime() + ".txt");
BufferedWriter out = new BufferedWriter(new FileWriter(inputTextAreaContent));
out.write(content);
out.close();
importFile = inputTextAreaContent;
}
else
{
importFile = request.getFile("upload");
}
// apply preprocessing if called for
PreProcessMatrix pm = null;
if (request.getString("prependToRows") != null || request.getString("prependToCols") != null
|| request.getString("escapeRows") != null || request.getString("escapeCols") != null
|| request.getString("trimTextElements") != null)
{
pm = new PreProcessMatrix(importFile);
}
if (request.getString("prependToRows") != null)
{
pm.prependUnderscoreToRowNames();
}
if (request.getString("prependToCols") != null)
{
pm.prependUnderscoreToColNames();
}
if (request.getString("escapeRows") != null)
{
pm.escapeRowNames();
}
if (request.getString("escapeCols") != null)
{
pm.escapeColNames();
}
if (request.getString("trimTextElements") != null)
{
pm.trimTextElements();
}
if (request.getString("prependToRows") != null || request.getString("prependToCols") != null
|| request.getString("escapeRows") != null || request.getString("escapeCols") != null
|| request.getString("trimTextElements") != null)
{
File result = pm.getResult();
if (!result.exists())
{
throw new Exception("Import file '" + result.getAbsolutePath() + " does not exist");
}
performImport(result, data, db);
}
else
{
if (importFile == null || !importFile.exists())
{
throw new Exception("No valid import file provided");
}
performImport(importFile, data, db);
}
}
public void performImport(File uploadedFile, Data data, Database db) throws Exception
{
DataMatrixHandler dmh = new DataMatrixHandler(db);
// check if uploaded file is there
if (uploadedFile == null || !uploadedFile.exists())
{
throw new DatabaseException("No file selected for upload.");
}
// check if the matrix elements exists in another source of data first
if (data.getStorage().equals("Database"))
{
if (dmh.isDataMatrixStoredInDatabase(data, db))
{
throw new DatabaseException("Database source already exists for source type '" + data.getStorage()
+ "'");
}
}
else
{
boolean realFilePresent;
try
{
String type = data.getStorage() + "DataMatrix";
dmh.getFileDirectly(NameConvention.escapeFileName(data.getName()), dmh.getExtension(data.getStorage()),
type, db);
realFilePresent = true;
}
catch (FileNotFoundException fnfe)
{
realFilePresent = false;
}
// original check here: dmh.findSourceFile(data, db) != null which
// failed when there is a leftover MF but no actual file
// so now there's this check instead
if (realFilePresent)
{
throw new DatabaseException("There is already a storage file named '"
+ NameConvention.escapeFileName(data.getName()) + "' which is used when escaping the name '"
+ data.getName() + "'. Please rename your Data matrix or contact your admin.");
}
// no file present, remove the MF link if there is one
// this is needed when you throw away the file on the file system
// 'without telling the database'
// and subsequently try to upload a new matrix, because otherwise
// the names would clash
MolgenisFile mf = dmh.findMolgenisFile(data, db);
if (mf != null)
{
db.remove(mf);
}
}
if (!(uploadedFile.getName().endsWith(".txt") || uploadedFile.getName().endsWith(".csv") || uploadedFile
.getName().endsWith(".xls")))
{
throw new Exception("Expecting a file with extension .txt, .csv or .xls");
}
if (uploadedFile.getName().endsWith(".xls"))
{
uploadedFile = excelToCsv(uploadedFile);
}
// do import
if (data.getStorage().equals("Database"))
{
// new DatabaseDataMatrixWriter(data, uploadedFile, db, false);
new DatabaseDataMatrixWriter(data, uploadedFile, db);
}
else if (data.getStorage().equals("Binary"))
{
new BinaryDataMatrixWriter(data, uploadedFile, db);
}
else if (data.getStorage().equals("CSV"))
{
new CSVDataMatrixWriter(data, uploadedFile, db);
}
else
{
throw new DatabaseException("Unknown matrix source: " + data.getStorage() + "");
}
}
private File excelToCsv(File excelFile) throws Exception
{
System.out.println("Converting Excel file " + excelFile.getName() + " to CSV..");
Workbook workbook = Workbook.getWorkbook(excelFile);
if (workbook.getSheetNames().length > 1)
{
throw new Exception("Expected 1 sheet in Excel file containing your matrix data");
}
Sheet sheet = workbook.getSheet(0);
List<String> headers = new ArrayList<String>();
Cell[] headerCells = sheet.getRow(0); // assume headers are on first
// line
if (headerCells.length == 0)
{
throw new Exception("No headers found in Excel file");
}
if (!headerCells[0].getContents().equals(""))
{
throw new Exception("Top-left cell must be empty to ensure correct matrix format");
}
else
{
headers.add("");
}
for (int i = 1; i < headerCells.length; i++)
{
if (headerCells[i].getContents().equals(""))
{
throw new Exception("Empty header at cell nr " + (i + 1));
}
else
{
headers.add(headerCells[i].getContents());
}
}
File out = new File(System.getProperty("java.io.tmpdir") + File.separator + "excel_to_csv_"
+ System.currentTimeMillis() + ".txt");
PrintWriter pw = new PrintWriter(out);
CsvWriter cw = new CsvWriter(pw, headers);
cw.setMissingValue("");
cw.writeHeader();
for (int rowIndex = 1; rowIndex < sheet.getRows(); rowIndex++)
{
Tuple t = new SimpleTuple();
Cell[] row = sheet.getRow(rowIndex);
for (int colIndex = 0; colIndex < row.length; colIndex++)
{
Cell c = row[colIndex];
if (colIndex > (headers.size() - 1))
{
throw new Exception("More columns than headers (bad element at rowindex " + rowIndex + " colindex "
+ colIndex + ")");
}
if (colIndex == 0 && c.getContents().equals(""))
{
throw new Exception("Empty first cell in row " + rowIndex);
}
if (c.getContents() != null)
{
t.set(headers.get(colIndex), c.getContents());
}
}
cw.writeRow(t);
}
cw.close();
System.out.println("..completed, returning " + out.getName());
return out;
}
}