Book-Catalogue/src/com/eleybourn/bookcatalogue/AdministrationFunctions.java

1095 lines
36 KiB
Java

/*
* @copyright 2010 Evan Leybourn
* @license GNU General Public License
*
* This file is part of Book Catalogue.
*
* Book Catalogue is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Book Catalogue 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Book Catalogue. If not, see <http://www.gnu.org/licenses/>.
*/
package com.eleybourn.bookcatalogue;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
/**
*
* This is the Administration page. It contains details about the app, links
* to my website and email, functions to export and import books and functions to
* manage bookshelves.
*
* @author Evan Leybourn
*/
public class AdministrationFunctions extends Activity {
private static final int ACTIVITY_BOOKSHELF=1;
private static final int ACTIVITY_FIELD_VISIBILITY=2;
private CatalogueDBAdapter mDbHelper;
private int importUpdated = 0;
private int importCreated = 0;
public static String filePath = Environment.getExternalStorageDirectory() + "/" + BookCatalogue.LOCATION;
public static String fileName = filePath + "/export.csv";
public static String UTF8 = "utf8";
public static int BUFFER_SIZE = 8192;
private ProgressDialog pd = null;
private int num = 0;
private boolean finish_after = false;
public static final String DOAUTO = "do_auto";
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
int total = msg.getData().getInt("total");
String title = msg.getData().getString("title");
if (total == 0) {
pd.dismiss();
if (finish_after == true) {
finish();
}
Toast.makeText(AdministrationFunctions.this, title, Toast.LENGTH_LONG).show();
//progressThread.setState(UpdateThumbnailsThread.STATE_DONE);
} else {
num += 1;
pd.incrementProgressBy(1);
if (title.length() > 21) {
title = title.substring(0, 20) + "...";
}
pd.setMessage(title);
}
}
};
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
try {
super.onCreate(savedInstanceState);
mDbHelper = new CatalogueDBAdapter(this);
mDbHelper.open();
setContentView(R.layout.administration_functions);
Bundle extras = getIntent().getExtras();
try {
if (extras.getString(DOAUTO).equals("export")) {
finish_after = true;
exportData();
} else if (extras.getString(DOAUTO).equals("update_fields")) {
finish_after = true;
updateThumbnails(false);
}
} catch (NullPointerException e) {
//do nothing
}
setupAdmin();
} catch (Exception e) {
//Log.e("Book Catalogue", "Unknown Exception - BC onCreate - " + e.getMessage() );
}
}
/**
* This function builds the Administration page in 4 sections.
* 1. The button to goto the manage bookshelves activity
* 2. The button to export the database
* 3. The button to import the exported file into the database
* 4. The application version and link details
* 5. The link to paypal for donation
*/
public void setupAdmin() {
/* Bookshelf Link */
TextView bookshelf = (TextView) findViewById(R.id.bookshelf_label);
bookshelf.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
manageBookselves();
return;
}
});
/* Manage Fields Link */
TextView fields = (TextView) findViewById(R.id.fields_label);
fields.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
manageFields();
return;
}
});
/* Export Link */
TextView export = (TextView) findViewById(R.id.export_label);
export.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
exportData();
return;
}
});
/* Import Link */
TextView imports = (TextView) findViewById(R.id.import_label);
/* Hack to pass this into the class */
final AdministrationFunctions pthis = this;
imports.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Verify - this can be a dangerous operation
AlertDialog alertDialog = new AlertDialog.Builder(pthis).setMessage(R.string.import_alert).create();
alertDialog.setTitle(R.string.import_data);
alertDialog.setIcon(android.R.drawable.ic_menu_info_details);
alertDialog.setButton(pthis.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
importData();
//Toast.makeText(pthis, importUpdated + " Existing, " + importCreated + " Created", Toast.LENGTH_LONG).show();
return;
}
});
alertDialog.setButton2(pthis.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//do nothing
return;
}
});
alertDialog.show();
return;
}
});
// // Debug ONLY!
// /* Backup Link */
// TextView backup = (TextView) findViewById(R.id.backup_label);
// backup.setOnClickListener(new OnClickListener() {
// @Override
// public void onClick(View v) {
// mDbHelper.backupDbFile();
// return;
// }
// });
/* Export Link */
TextView thumb = (TextView) findViewById(R.id.thumb_label);
thumb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Verify - this can be a dangerous operation
AlertDialog alertDialog = new AlertDialog.Builder(pthis).setMessage(R.string.overwrite_thumbnail).create();
alertDialog.setTitle(R.string.update_thumbnails);
alertDialog.setIcon(android.R.drawable.ic_menu_info_details);
alertDialog.setButton(pthis.getResources().getString(R.string.yes), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
updateThumbnails(true);
return;
}
});
alertDialog.setButton2(pthis.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//do nothing
return;
}
});
alertDialog.setButton3(pthis.getResources().getString(R.string.no), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
updateThumbnails(false);
return;
}
});
alertDialog.show();
return;
}
});
}
/**
* Load the Bookshelf Activity
*/
private void manageBookselves() {
Intent i = new Intent(this, Bookshelf.class);
startActivityForResult(i, ACTIVITY_BOOKSHELF);
}
/**
* Load the Manage Field Visibility Activity
*/
private void manageFields() {
Intent i = new Intent(this, FieldVisibility.class);
startActivityForResult(i, ACTIVITY_FIELD_VISIBILITY);
}
private class UpdateThumbnailsThread extends Thread {
public boolean overwrite = false;
public Cursor books = null;
private Handler mHandler;
/**
* @param handler
*/
public UpdateThumbnailsThread(Handler handler) {
mHandler = handler;
}
private void sendMessage(int num, String title) {
/* Send message to the handler */
Message msg = mHandler.obtainMessage();
Bundle b = new Bundle();
b.putInt("total", num);
b.putString("title", title);
msg.setData(b);
mHandler.sendMessage(msg);
return;
}
@Override
public void run() {
Looper.prepare();
/* Test write to the SDCard */
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath + "/.nomedia"), UTF8), BUFFER_SIZE);
out.write("");
out.close();
} catch (IOException e) {
sendMessage(0, "Thumbnail Download Failed - Could not write to SDCard");
return;
}
startManagingCursor(books);
int num = 0;
//try {
while (books.moveToNext()) {
long id = books.getLong(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ROWID));
String isbn = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ISBN));
String title = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_TITLE));
String genre = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_GENRE));
String description = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_DESCRIPTION));
try {
genre.equals("");
} catch (NullPointerException e) {
genre = "";
}
try {
description.equals("");
} catch (NullPointerException e) {
description = "";
}
String author = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_AUTHOR_FORMATTED));
String publisher = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_PUBLISHER));
String date_published = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_DATE_PUBLISHED));
String series = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SERIES));
String series_num = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SERIES_NUM));
String list_price = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LIST_PRICE));
int pages = books.getInt(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_PAGES));
String format = books.getString(books.getColumnIndex(CatalogueDBAdapter.KEY_FORMAT));
int anthology = books.getInt(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ANTHOLOGY));
float rating = books.getFloat(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_RATING));
//Display the selected bookshelves
Cursor bookshelves = mDbHelper.fetchAllBookshelvesByBook(id);
String bookshelf = "";
while (bookshelves.moveToNext()) {
bookshelf += bookshelves.getString(bookshelves.getColumnIndex(CatalogueDBAdapter.KEY_BOOKSHELF)) + BookEditFields.BOOKSHELF_SEPERATOR;
}
boolean read = (books.getInt(books.getColumnIndex(CatalogueDBAdapter.KEY_READ))==0 ? false:true);
String notes = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_NOTES));
String location = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LOCATION));
String read_start = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_START));
String read_end = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_END));
boolean signed = (books.getInt(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SIGNED))==0 ? false:true);
num++;
// delete any tmp thumbnails //
try {
File delthumb = CatalogueDBAdapter.fetchThumbnail(0);
delthumb.delete();
} catch (Exception e) {
// do nothing - this is the expected behaviour
}
String[] book = null;
File thumb = CatalogueDBAdapter.fetchThumbnail(id);
if (isbn.equals("") && author.equals("") && title.equals("")) {
// Must have an ISBN to be able to search
sendMessage(num, "Skip - " + title);
//TODO: searchGoogle(AUTHOR)
} else if (overwrite == true || !thumb.exists() || genre.equals("") || description.equals("")) {
sendMessage(num, title);
BookISBNSearch bis = new BookISBNSearch();
//String[] book = {0=author, 1=title, 2=isbn, 3=publisher, 4=date_published, 5=rating, 6=bookshelf,
// 7=read, 8=series, 9=pages, 10=series_num, 11=list_price, 12=anthology, 13=location, 14=read_start,
// 15=read_end, 16=audiobook, 17=signed, 18=description, 19=genre};
book = bis.searchGoogle(isbn, author, title);
File tmpthumb = CatalogueDBAdapter.fetchThumbnail(0);
String[] bookAmazon = bis.searchAmazon(isbn, author, title);
tmpthumb = CatalogueDBAdapter.fetchThumbnail(0);
/* Fill blank fields as required */
for (int i = 0; i<book.length; i++) {
if (book[i] == "" || book[i] == "0") {
book[i] = bookAmazon[i];
}
}
/* Copy tmpthumb over realthumb */
if (overwrite == true || !thumb.exists()) {
try {
tmpthumb.renameTo(thumb);
} catch (Exception e) {
//do nothing
}
}
if (description.equals("")) {
description = book[18];
}
if (genre.equals("")) {
genre = book[19];
}
mDbHelper.updateBook(id, author, title, isbn, publisher, date_published, rating, bookshelf, read, series, pages, series_num, notes, list_price, anthology, location, read_start, read_end, format, signed, description, genre);
} else {
sendMessage(num, "Skip - " + title);
}
}
//} catch (Exception e) {
// do nothing
//}
sendMessage(0, num + " Books Searched");
}
}
/**
* Update all (non-existent) thumbnails
*
* There is a current limitation that restricts the search to only books with an ISBN
*/
private void updateThumbnails(boolean overwrite) {
Cursor books = mDbHelper.fetchAllBooks("b." + CatalogueDBAdapter.KEY_ROWID, "All Books");
pd = new ProgressDialog(AdministrationFunctions.this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Updating...");
pd.setCancelable(false);
pd.setMax(books.getCount());
pd.show();
UpdateThumbnailsThread thread = new UpdateThumbnailsThread(handler);
thread.overwrite = overwrite;
thread.books = books;
thread.start();
//Toast.makeText(AdministrationFunctions.this, R.string.download_thumbs, Toast.LENGTH_LONG).show();
}
private class ExportThread extends Thread {
public Cursor books = null;
private Handler mHandler;
/**
* @param handler
*/
public ExportThread(Handler handler) {
mHandler = handler;
}
private void sendMessage(int num, String title) {
/* Send message to the handler */
Message msg = mHandler.obtainMessage();
Bundle b = new Bundle();
b.putInt("total", num);
b.putString("title", title);
msg.setData(b);
mHandler.sendMessage(msg);
return;
}
@Override
public void run() {
Looper.prepare();
int num = 0;
/* Test write to the SDCard */
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath + "/.nomedia"), UTF8), BUFFER_SIZE);
out.write("");
out.close();
} catch (IOException e) {
sendMessage(0, "Export Failed - Could not write to SDCard");
return;
}
String export =
'"' + CatalogueDBAdapter.KEY_ROWID + "\"," + //0
'"' + CatalogueDBAdapter.KEY_FAMILY_NAME + "\"," + //1
'"' + CatalogueDBAdapter.KEY_GIVEN_NAMES + "\"," + //2
'"' + CatalogueDBAdapter.KEY_AUTHOR + "\"," + //3
'"' + 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 + "\"," + //12
'"' + CatalogueDBAdapter.KEY_SERIES_NUM + "\"," + //13
'"' + CatalogueDBAdapter.KEY_PAGES + "\"," + //14
'"' + CatalogueDBAdapter.KEY_NOTES + "\"," + //15
'"' + CatalogueDBAdapter.KEY_LIST_PRICE + "\"," + //16
'"' + CatalogueDBAdapter.KEY_ANTHOLOGY+ "\"," + //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
"\n";
if (books.moveToFirst()) {
do {
num++;
long id = books.getLong(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ROWID));
String dateString = "";
try {
String[] date = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_DATE_PUBLISHED)).split("-");
int yyyy = Integer.parseInt(date[0]);
int mm = Integer.parseInt(date[1])+1;
int dd = Integer.parseInt(date[2]);
dateString = yyyy + "-" + mm + "-" + dd;
} catch (Exception e) {
//do nothing
}
String dateReadStartString = "";
try {
Log.e("BC", "S" + books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_START)));
String[] date = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_START)).split("-");
int yyyy = Integer.parseInt(date[0]);
int mm = Integer.parseInt(date[1])+1;
int dd = Integer.parseInt(date[2]);
dateReadStartString = yyyy + "-" + mm + "-" + dd;
Log.e("BC", dateReadStartString);
} catch (Exception e) {
Log.e("BC", "EXPORT ERROR");
//do nothing
}
String dateReadEndString = "";
try {
Log.e("BC", "S" + books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_END)));
String[] date = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_END)).split("-");
int yyyy = Integer.parseInt(date[0]);
int mm = Integer.parseInt(date[1])+1;
int dd = Integer.parseInt(date[2]);
dateReadEndString = yyyy + "-" + mm + "-" + dd;
Log.e("BC", dateReadEndString);
} catch (Exception e) {
Log.e("BC", "EXPORT ERROR2");
//do nothing
}
String anthology = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ANTHOLOGY));
String anthology_titles = "";
if (anthology.equals(CatalogueDBAdapter.ANTHOLOGY_MULTIPLE_AUTHORS + "") || anthology.equals(CatalogueDBAdapter.ANTHOLOGY_SAME_AUTHOR + "")) {
Cursor titles = mDbHelper.fetchAnthologyTitlesByBook(id);
if (titles.moveToFirst()) {
do {
String anth_title = titles.getString(titles.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_TITLE));
String anth_author = titles.getString(titles.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_AUTHOR));
anthology_titles += anth_title + " * " + anth_author + "|";
} while (titles.moveToNext());
}
}
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 += bookshelves.getString(bookshelves.getColumnIndex(CatalogueDBAdapter.KEY_BOOKSHELF)) + BookEditFields.BOOKSHELF_SEPERATOR;
}
bookshelves.close();
String row = "";
row += "\"" + formatCell(id) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_FAMILY_NAME))) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_GIVEN_NAMES))) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_AUTHOR))) + "\",";
row += "\"" + formatCell(title) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ISBN))) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_PUBLISHER))) + "\",";
row += "\"" + formatCell(dateString) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_RATING))) + "\",";
row += "\"" + formatCell(bookshelves_id_text) + "\",";
row += "\"" + formatCell(bookshelves_name_text) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ))) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SERIES))) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SERIES_NUM))) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_PAGES))) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_NOTES))) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LIST_PRICE))) + "\",";
row += "\"" + formatCell(anthology) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LOCATION))) + "\",";
row += "\"" + formatCell(dateReadStartString) + "\",";
row += "\"" + formatCell(dateReadEndString) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_FORMAT))) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SIGNED))) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LOANED_TO))+"") + "\",";
row += "\"" + formatCell(anthology_titles) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_DESCRIPTION))) + "\",";
row += "\"" + formatCell(books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_GENRE))) + "\",";
row += "\n";
export += row;
sendMessage(num, title);
}
while (books.moveToNext());
}
/* write to the SDCard */
try {
backupExport();
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), UTF8), BUFFER_SIZE);
out.write(export);
out.close();
sendMessage(0, "Export Complete");
//Toast.makeText(AdministrationFunctions.this, R.string.export_complete, Toast.LENGTH_LONG).show();
} catch (IOException e) {
//Log.e("Book Catalogue", "Could not write to the SDCard");
//Toast.makeText(AdministrationFunctions.this, R.string.export_failed, Toast.LENGTH_LONG).show();
sendMessage(0, "Export Failed - Could not write to SDCard");
}
}
private void backupExport() {
File export = new File(fileName);
File backup = new File(fileName + ".bak");
export.renameTo(backup);
}
/**
* 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")) {
return "";
}
return cell.replaceAll("\"", "\"\"").replaceAll("\n", "").replaceAll("\r", "");
} 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);
}
}
/**
* Export all data to a CSV file
*
* return void
*/
public void exportData() {
Cursor books = mDbHelper.exportBooks();
pd = new ProgressDialog(AdministrationFunctions.this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Exporting...");
pd.setCancelable(false);
pd.setMax(books.getCount());
pd.show();
ExportThread thread = new ExportThread(handler);
thread.books = books;
thread.start();
}
/**
* This program reads a text file line by line and print to the console. It uses
* FileOutputStream to read the file.
*
*/
public ArrayList<String> readFile() {
ArrayList<String> importedString = new ArrayList<String>();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), UTF8),BUFFER_SIZE);
String line = "";
while ((line = in.readLine()) != null) {
importedString.add(line);
}
in.close();
} catch (FileNotFoundException e) {
Toast.makeText(this, R.string.import_failed, Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(this, R.string.import_failed, Toast.LENGTH_LONG).show();
}
return importedString;
}
private class ImportThread extends Thread {
public ArrayList<String> export = null;
private Handler mHandler;
/**
* @param handler
*/
public ImportThread(Handler handler) {
mHandler = handler;
}
private void sendMessage(int num, String title) {
/* Send message to the handler */
Message msg = mHandler.obtainMessage();
Bundle b = new Bundle();
b.putInt("total", num);
b.putString("title", title);
msg.setData(b);
mHandler.sendMessage(msg);
return;
}
//
// This CSV parser is not a complete parser, but it will parse files exported by older
// versions. At some stage in the future it would be good to allow full CSV export
// and import to allow for escape('\') chars so that cr/lf can be preserved.
//
private String[] returnRow(String row) {
// Need to handle double quotes etc
char sep = ','; // CSV seperator
char quoteChar = '"'; // CSV quote char
int pos = 0; // Current position
boolean inQuote = false; // In a quoted string
char c; // 'Current' char
char next // 'Next' char
= (row.length() > 0) ? row.charAt(0) : '\0';
int endPos // Last position in row
= row.length() - 1;
ArrayList<String> fields // Array of fields found in row
= new ArrayList<String>();
StringBuilder bld // Temp. storage for current field
= new StringBuilder();
while (next != '\0')
{
// Get current and next char
c = next;
next = (pos < endPos) ? row.charAt(pos+1) : '\0';
if (inQuote)
{
if (c == quoteChar) {
if (next == quoteChar)
{
// Double-quote: Advance one more and append a single quote
pos++;
next = (pos < endPos) ? row.charAt(pos+1) : '\0';
bld.append(c);
} else {
// Leave the quote
inQuote = false;
}
} else {
// Append anything else that appears in quotes
bld.append(c);
}
} else {
if (bld.length() == 0 && (c == ' ' || c == '\t') ) {
// Skip leading white space
} else if (c == quoteChar) {
if (bld.length() > 0) {
// Fields with quotes MUST be quoted...
throw new IllegalArgumentException();
} else {
inQuote = true;
}
} else if (c == sep) {
// Add this field and reset it.
fields.add(bld.toString());
bld = new StringBuilder();
} else {
// Just append the char
bld.append(c);
}
}
pos++;
};
// Add the remaining chunk
fields.add(bld.toString());
// Return the result as a String[].
String[] imported = new String[fields.size()];
fields.toArray(imported);
return imported;
}
@Override
public void run() {
Looper.prepare();
int row = 1;
int num = 0;
/* Iterate through each imported row */
while (row < export.size()) {
num++;
String[] imported = returnRow(export.get(row));
row++;
/* Setup aliases for each cell*/
Long id = null;
try {
id = Long.parseLong(imported[0]);
} catch(Exception e) {
id = Long.parseLong("0");
}
String family = "";
try {
family = imported[1];
} catch (Exception e) {
// family is a compulsory field
continue;
}
String given = "";
try {
given = imported[2];
} catch (Exception e) {
given = "";
}
//String author_id = imported[3];
String title = "";
try {
title = imported[4];
} catch (Exception e) {
//title is a compulsory field
continue;
}
String isbn = "";
try {
isbn = imported[5];
} catch (Exception e) {
isbn = "";
}
String publisher = "";
try {
publisher = imported[6];
} catch (Exception e) {
publisher = "";
}
String date_published = "";
try {
date_published = imported[7];
String[] date = date_published.split("-");
int yyyy = Integer.parseInt(date[0]);
int mm = Integer.parseInt(date[1])-1;
int dd = Integer.parseInt(date[2]);
date_published = yyyy + "-" + mm + "-" + dd;
} catch (Exception e) {
date_published = "";
}
float rating = 0;
try {
rating = Float.valueOf(imported[8]);
} catch (Exception e) {
rating = 0;
}
//String bookshelf_id = imported[9];
String bookshelf = "";
try {
bookshelf = imported[10];
} catch (Exception e) {
bookshelf = "";
}
boolean read = false;
try {
read = (imported[11].equals("0")? false:true);
} catch (Exception e) {
read = false;
}
String series = "";
try {
series = imported[12];
} catch (Exception e) {
series = "";
}
String series_num = "";
try {
series_num = imported[13];
} catch (Exception e) {
series_num = "";
}
int pages = 0;
try {
pages = Integer.parseInt(imported[14]);
} catch (Exception e) {
pages = 0;
}
String notes = "";
try {
notes = imported[15];
} catch (Exception e) {
notes = "";
}
String list_price = "";
try {
list_price = imported[16];
} catch (ArrayIndexOutOfBoundsException e) {
list_price = "";
}
int anthology = CatalogueDBAdapter.ANTHOLOGY_NO;
try {
anthology = Integer.parseInt(imported[17]);
} catch (Exception e) {
anthology = 0;
}
String location = "";
try {
location = imported[18];
} catch (Exception e) {
location = "";
}
String read_start = "";
try {
read_start = imported[19];
String[] date = read_start.split("-");
int yyyy = Integer.parseInt(date[0]);
int mm = Integer.parseInt(date[1])-1;
int dd = Integer.parseInt(date[2]);
read_start = yyyy + "-" + mm + "-" + dd;
} catch (Exception e) {
read_start = "";
}
String read_end = "";
try {
read_end = imported[20];
Log.e("BC", "R" + read_end);
String[] date = read_end.split("-");
int yyyy = Integer.parseInt(date[0]);
int mm = Integer.parseInt(date[1])-1;
int dd = Integer.parseInt(date[2]);
read_end = yyyy + "-" + mm + "-" + dd;
Log.e("BC", "C" + read_end);
} catch (Exception e) {
read_end = "";
Log.e("BC", "ERROR");
}
String format = "";
try {
format = imported[21];
} catch (Exception e) {
format = "";
}
boolean signed = false;
try {
signed = (imported[22].equals("0")? false:true);
} catch (Exception e) {
signed = false;
}
String loan = "";
try {
loan = imported[23];
} catch (Exception e) {
loan = "";
}
String anthology_titles = "";
try {
anthology_titles = imported[24];
} catch (Exception e) {
anthology_titles = "";
}
String description = "";
try {
description = imported[25];
} catch (Exception e) {
description = "";
}
String genre = "";
try {
genre = imported[26];
} catch (Exception e) {
genre = "";
}
String author = family + ", " + given;
try {
if (id == 0) {
// ID is unknown, may be new. Check if it exists in the current database.
Cursor book = null;
int rows = 0;
// If the ISBN is specified, use it as a definitive lookup.
if (isbn != "") {
book = mDbHelper.fetchBookByISBN(isbn);
rows = book.getCount();
} else {
if (rows == 0) {
book = mDbHelper.fetchByAuthorAndTitle(family, given, title);
rows = book.getCount();
}
}
if (rows != 0) {
book.moveToFirst();
// Its a new entry, but the ISBN exists
id = book.getLong(0);
book.moveToFirst();
mDbHelper.updateBook(id, author, title, isbn, publisher, date_published, rating, bookshelf, read, series, pages, series_num, notes, list_price, anthology, location, read_start, read_end, format, signed, description, genre);
importUpdated++;
} else {
id = mDbHelper.createBook(author, title, isbn, publisher, date_published, rating, bookshelf, read, series, pages, series_num, notes, list_price, anthology, location, read_start, read_end, format, signed, description, genre);
importCreated++;
}
} else {
Cursor book = mDbHelper.fetchBookById(id);
int rows = book.getCount();
if (rows == 0) {
mDbHelper.createBook(id, author, title, isbn, publisher, date_published, rating, bookshelf, read, series, pages, series_num, notes, list_price, anthology, location, read_start, read_end, format, signed, description, genre);
importCreated++;
} else {
// Book exists and should be updated if it has changed
mDbHelper.updateBook(id, author, title, isbn, publisher, date_published, rating, bookshelf, read, series, pages, series_num, notes, list_price, anthology, location, read_start, read_end, format, signed, description, genre);
importUpdated++;
}
}
} catch (Exception e) {
//Log.e("BC", "Import Book (Single) Error");
// do nothing
}
if (!loan.equals("")) {
mDbHelper.createLoan(id, loan);
}
if (anthology == CatalogueDBAdapter.ANTHOLOGY_MULTIPLE_AUTHORS || anthology == CatalogueDBAdapter.ANTHOLOGY_SAME_AUTHOR) {
int oldi = 0;
int i = anthology_titles.indexOf("|", oldi);
while (i > -1) {
String extracted_title = anthology_titles.substring(oldi, i).trim();
int j = extracted_title.indexOf("*");
if (j > -1) {
String anth_title = extracted_title.substring(0, j).trim();
String anth_author = extracted_title.substring((j+1)).trim();
mDbHelper.createAnthologyTitle(id, anth_author, anth_title);
}
oldi = i + 1;
i = anthology_titles.indexOf("|", oldi);
}
}
sendMessage(num, title);
}
sendMessage(0, "Import Complete");
}
}
/**
* Import all data from the CSV file
*
* return void
*/
private void importData() {
importUpdated = 0;
importCreated = 0;
ArrayList<String> export = readFile();
pd = new ProgressDialog(AdministrationFunctions.this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Importing...");
pd.setCancelable(false);
pd.setMax(export.size() - 1);
pd.show();
ImportThread thread = new ImportThread(handler);
thread.export = export;
thread.start();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
switch(requestCode) {
case ACTIVITY_BOOKSHELF:
case ACTIVITY_FIELD_VISIBILITY:
//do nothing (yet)
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mDbHelper.close();
}
}