package com.eleybourn.bookcatalogue;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import com.eleybourn.bookcatalogue.backup.CsvExporter;
import com.eleybourn.bookcatalogue.backup.Exporter;
import com.eleybourn.bookcatalogue.utils.Logger;
import com.eleybourn.bookcatalogue.utils.StorageUtils;
/**
* Class to handle export in a separate thread.
*
* @author Philip Warner
*/
public class ExportThread extends ManagedTask {
// Changed the paths to non-static variable because if this code is called
// while a phone sync is in progress, they will not be set correctly
private String mFilePath = StorageUtils.getSharedStorage().getAbsolutePath();
private String mExportFileName = mFilePath + "/export.csv";
private String mTempFileName = mFilePath + "/export.tmp";
private static String UTF8 = "utf8";
private static int BUFFER_SIZE = 8192;
private CatalogueDBAdapter mDbHelper;
public ExportThread(TaskManager ctx) {
super(ctx);
mDbHelper = new CatalogueDBAdapter(BookCatalogueApp.context);
mDbHelper.open();
}
@Override
protected void onThreadFinish() {
cleanup();
}
private Exporter.ExportListener mOnExportListener = new Exporter.ExportListener() {
@Override
public void onProgress(String message, int position) {
if (position > 0) {
mManager.doProgress(ExportThread.this, message, position);
} else {
mManager.doProgress(message);
}
}
@Override
public boolean isCancelled() {
return ExportThread.this.isCancelled();
}
@Override
public void setMax(int max) {
mManager.setMax(ExportThread.this, max);
}
};
@Override
protected void onRun() {
if (!StorageUtils.sdCardWritable()) {
mManager.doToast("Export Failed - Could not write to SDCard");
return;
}
try {
FileOutputStream out = new FileOutputStream(mTempFileName);
CsvExporter exporter = new CsvExporter();
exporter.export(out, mOnExportListener, Exporter.EXPORT_ALL, null);
if (out != null && out.getChannel().isOpen()) {
out.close();
}
renameFiles();
} catch (IOException e) {
Logger.logError(e);
mManager.doToast(getString(R.string.export_failed_sdcard));
}
// mManager.doProgress(getString(R.string.export_starting_ellipsis));
// boolean displayingStartupMessage = true;
//
// StringBuilder export = new StringBuilder(
// '"' + CatalogueDBAdapter.KEY_ROWID + "\"," + //0
// '"' + CatalogueDBAdapter.KEY_AUTHOR_DETAILS + "\"," + //2
// '"' + CatalogueDBAdapter.KEY_TITLE + "\"," + //4
// '"' + CatalogueDBAdapter.KEY_ISBN + "\"," + //5
// '"' + CatalogueDBAdapter.KEY_PUBLISHER + "\"," + //6
// '"' + CatalogueDBAdapter.KEY_DATE_PUBLISHED + "\"," + //7
// '"' + CatalogueDBAdapter.KEY_RATING + "\"," + //8
// '"' + "bookshelf_id\"," + //9
// '"' + CatalogueDBAdapter.KEY_BOOKSHELF + "\"," + //10
// '"' + CatalogueDBAdapter.KEY_READ + "\"," + //11
// '"' + CatalogueDBAdapter.KEY_SERIES_DETAILS + "\"," + //12
// '"' + CatalogueDBAdapter.KEY_PAGES + "\"," + //14
// '"' + CatalogueDBAdapter.KEY_NOTES + "\"," + //15
// '"' + CatalogueDBAdapter.KEY_LIST_PRICE + "\"," + //16
// '"' + CatalogueDBAdapter.KEY_ANTHOLOGY_MASK+ "\"," + //17
// '"' + CatalogueDBAdapter.KEY_LOCATION+ "\"," + //18
// '"' + CatalogueDBAdapter.KEY_READ_START+ "\"," + //19
// '"' + CatalogueDBAdapter.KEY_READ_END+ "\"," + //20
// '"' + CatalogueDBAdapter.KEY_FORMAT+ "\"," + //21
// '"' + CatalogueDBAdapter.KEY_SIGNED+ "\"," + //22
// '"' + CatalogueDBAdapter.KEY_LOANED_TO+ "\"," + //23
// '"' + "anthology_titles" + "\"," + //24
// '"' + CatalogueDBAdapter.KEY_DESCRIPTION+ "\"," + //25
// '"' + CatalogueDBAdapter.KEY_GENRE+ "\"," + //26
// '"' + CatalogueDBAdapter.KEY_DATE_ADDED+ "\"," + //27
// '"' + DatabaseDefinitions.DOM_GOODREADS_BOOK_ID + "\"," + //28
// '"' + DatabaseDefinitions.DOM_LAST_GOODREADS_SYNC_DATE + "\"," + //29
// '"' + DatabaseDefinitions.DOM_LAST_UPDATE_DATE + "\"," + //30
// '"' + DatabaseDefinitions.DOM_BOOK_UUID + "\"," + //31
// "\n");
//
// long lastUpdate = 0;
//
// StringBuilder row = new StringBuilder();
//
// BooksCursor books = mDbHelper.exportBooks();
// BooksRowView rv = books.getRowView();
//
// try {
// final int totalBooks = books.getCount();
//
// if (!isCancelled()) {
//
// mManager.setMax(this, totalBooks);
//
// /* write to the SDCard */
// BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mTempFileName), UTF8), BUFFER_SIZE);
// out.write(export.toString());
// if (books.moveToFirst()) {
// do {
// num++;
// long id = books.getLong(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ROWID));
// // Just get the string from the database and save it. It should be in standard SQL form already.
// String dateString = "";
// try {
// dateString = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_DATE_PUBLISHED));
// } catch (Exception e) {
// //do nothing
// }
// // Just get the string from the database and save it. It should be in standard SQL form already.
// String dateReadStartString = "";
// try {
// dateReadStartString = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_START));
// } catch (Exception e) {
// Logger.logError(e);
// //do nothing
// }
// // Just get the string from the database and save it. It should be in standard SQL form already.
// String dateReadEndString = "";
// try {
// dateReadEndString = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_END));
// } catch (Exception e) {
// Logger.logError(e);
// //do nothing
// }
// // Just get the string from the database and save it. It should be in standard SQL form already.
// String dateAddedString = "";
// try {
// dateAddedString = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_DATE_ADDED));
// } catch (Exception e) {
// //do nothing
// }
//
// String anthology = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ANTHOLOGY_MASK));
// String anthology_titles = "";
// if (anthology.equals(CatalogueDBAdapter.ANTHOLOGY_MULTIPLE_AUTHORS + "") || anthology.equals(CatalogueDBAdapter.ANTHOLOGY_IS_ANTHOLOGY + "")) {
// Cursor titles = mDbHelper.fetchAnthologyTitlesByBook(id);
// try {
// if (titles.moveToFirst()) {
// do {
// String anth_title = titles.getString(titles.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_TITLE));
// String anth_author = titles.getString(titles.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_AUTHOR_NAME));
// anthology_titles += anth_title + " * " + anth_author + "|";
// } while (titles.moveToNext());
// }
// } finally {
// if (titles != null)
// titles.close();
// }
// }
// String title = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_TITLE));
// //Display the selected bookshelves
// Cursor bookshelves = mDbHelper.fetchAllBookshelvesByBook(id);
// String bookshelves_id_text = "";
// String bookshelves_name_text = "";
// while (bookshelves.moveToNext()) {
// bookshelves_id_text += bookshelves.getString(bookshelves.getColumnIndex(CatalogueDBAdapter.KEY_ROWID)) + BookEditFields.BOOKSHELF_SEPERATOR;
// bookshelves_name_text += Utils.encodeListItem(bookshelves.getString(bookshelves.getColumnIndex(CatalogueDBAdapter.KEY_BOOKSHELF)),BookEditFields.BOOKSHELF_SEPERATOR) + BookEditFields.BOOKSHELF_SEPERATOR;
// }
// bookshelves.close();
//
// String authorDetails = Utils.getAuthorUtils().encodeList( mDbHelper.getBookAuthorList(id), '|' );
// String seriesDetails = Utils.getSeriesUtils().encodeList( mDbHelper.getBookSeriesList(id), '|' );
//
// row.setLength(0);
// row.append("\"" + formatCell(id) + "\",");
// row.append("\"" + formatCell(authorDetails) + "\",");
// row.append( "\"" + formatCell(title) + "\"," );
// row.append("\"" + formatCell(rv.getIsbn()) + "\",");
// row.append("\"" + formatCell(rv.getPublisher()) + "\",");
// row.append("\"" + formatCell(dateString) + "\",");
// row.append("\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_RATING))) + "\",");
// row.append("\"" + formatCell(bookshelves_id_text) + "\",");
// row.append("\"" + formatCell(bookshelves_name_text) + "\",");
// row.append("\"" + formatCell(rv.getRead()) + "\",");
// row.append("\"" + formatCell(seriesDetails) + "\",");
// row.append("\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_PAGES))) + "\",");
// row.append("\"" + formatCell(rv.getNotes()) + "\",");
// row.append("\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LIST_PRICE))) + "\",");
// row.append("\"" + formatCell(anthology) + "\",");
// row.append("\"" + formatCell(rv.getLocation()) + "\",");
// row.append("\"" + formatCell(dateReadStartString) + "\",");
// row.append("\"" + formatCell(dateReadEndString) + "\",");
// row.append("\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_FORMAT))) + "\",");
// row.append("\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SIGNED))) + "\",");
// row.append("\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LOANED_TO))+"") + "\",");
// row.append("\"" + formatCell(anthology_titles) + "\",");
// row.append("\"" + formatCell(rv.getDescription()) + "\",");
// row.append("\"" + formatCell(rv.getGenre()) + "\",");
// row.append("\"" + formatCell(dateAddedString) + "\",");
// row.append("\"" + formatCell(rv.getGoodreadsBookId()) + "\",");
// row.append("\"" + formatCell(books.getString(books.getColumnIndexOrThrow(DatabaseDefinitions.DOM_LAST_GOODREADS_SYNC_DATE.name))) + "\",");
// row.append("\"" + formatCell(books.getString(books.getColumnIndexOrThrow(DatabaseDefinitions.DOM_LAST_UPDATE_DATE.name))) + "\",");
// row.append("\"" + formatCell(rv.getBookUuid()) + "\",");
// row.append("\n");
// out.write(row.toString());
// //export.append(row);
//
// long now = System.currentTimeMillis();
// if ( (now - lastUpdate) > 200) {
// if (displayingStartupMessage) {
// mManager.doProgress("");
// displayingStartupMessage = false;
// }
// doProgress(title, num);
// lastUpdate = now;
// }
// }
// while (books.moveToNext() && !isCancelled());
// }
//
// out.close();
// //Toast.makeText(AdministrationFunctions.this, R.string.export_complete, Toast.LENGTH_LONG).show();
// renameFiles();
// }
//
// } catch (IOException e) {
// Logger.logError(e);
// mManager.doToast(getString(R.string.export_failed_sdcard));
// } finally {
// if (displayingStartupMessage) {
// mManager.doProgress("");
// displayingStartupMessage = false;
// }
// if (!isCancelled()) {
// mManager.doToast( getString(R.string.export_complete) );
// } else {
// mManager.doToast( getString(R.string.cancelled) );
// }
// if (books != null)
// books.close();
// }
}
/**
* Backup the current file
*/
private void renameFiles() {
File temp = new File(mTempFileName);
File export = new File(mExportFileName);
if (isCancelled()) {
if (temp.exists())
temp.delete();
} else {
String fmt = mFilePath + "/export.%s.csv";
File fLast = new File(String.format(fmt, 5));
if (fLast.exists())
fLast.delete();
for(int i = 4; i > 0; i--) {
File fCurr = new File(String.format(fmt, i));
if (fCurr.exists())
fCurr.renameTo(fLast);
fLast = fCurr;
}
if (export.exists())
export.renameTo(fLast);
if (temp.exists())
temp.renameTo(export);
}
}
/**
* Double quote all "'s and remove all newlines
*
* @param cell The cell the format
* @return The formatted cell
*/
private String formatCell(String cell) {
try {
if (cell.equals("null") || cell.trim().length() == 0) {
return "";
}
StringBuilder bld = new StringBuilder();
int endPos = cell.length() - 1;
int pos = 0;
while (pos <= endPos) {
char c = cell.charAt(pos);
switch(c) {
case '\r':
bld.append("\\r");
break;
case '\n':
bld.append("\\n");
break;
case '\t':
bld.append("\\t");
break;
case '"':
bld.append("\"\"");
break;
case '\\':
bld.append("\\\\");
break;
default:
bld.append(c);
}
pos++;
}
return bld.toString();
} catch (NullPointerException e) {
return "";
}
}
/**
* @see formatCell(String cell)
* @param cell The cell the format
* @return The formatted cell
*/
private String formatCell(long cell) {
String newcell = cell + "";
return formatCell(newcell);
}
/**
* Cleanup any DB connection etc after main task has run.
*/
private void cleanup() {
if (mDbHelper != null) {
mDbHelper.close();
mDbHelper = null;
}
}
@Override
protected void finalize() throws Throwable {
cleanup();
super.finalize();
}
}