/*
* @copyright 2013 Philip Warner
* @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.backup;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import android.content.SharedPreferences;
import com.eleybourn.bookcatalogue.BookCatalogueApp;
import com.eleybourn.bookcatalogue.BookCataloguePreferences;
import com.eleybourn.bookcatalogue.CatalogueDBAdapter;
import com.eleybourn.bookcatalogue.booklist.BooklistStyle;
import com.eleybourn.bookcatalogue.database.SerializationUtils.DeserializationException;
import com.eleybourn.bookcatalogue.utils.Logger;
import com.eleybourn.bookcatalogue.utils.StorageUtils;
/**
* Basic implementation of format-agnostic BackupReader methods using
* only a limited set of methods from the base interface.
*
* @author pjw
*/
public abstract class BackupReaderAbstract implements BackupReader {
private CatalogueDBAdapter mDbHelper;
private final File mSharedStorage = StorageUtils.getSharedStorage();
/**
* Constructor
*/
public BackupReaderAbstract() {
mDbHelper = new CatalogueDBAdapter(BookCatalogueApp.context);
mDbHelper.open();
}
/**
* Do a full restore, sending progress to the listener
*/
@Override
public void restore(BackupReaderListener listener, int importFlags) throws IOException {
// Just a stat for progress
int coverCount = 0;
// This is an estimate only; we actually don't know how many covers
// there are in the backup.
BackupInfo info = getInfo();
int maxSteps = (int) (info.getBookCount());
if (info.hasCoverCount())
maxSteps += info.getCoverCount();
else
maxSteps *= 2;
maxSteps++;
listener.setMax(maxSteps);
// Get first entity (this will be the entity AFTER the INFO entities)
ReaderEntity entity = nextEntity();
// While not at end, loop, processing each entry based on type
while (entity != null && !listener.isCancelled()) {
switch (entity.getType()) {
case Books:
restoreBooks(listener, entity, importFlags);
break;
case Cover:
coverCount++;
restoreCover(listener, entity, importFlags);
break;
case Database:
break;
case Preferences:
restorePreferences(listener, entity);
break;
case BooklistStyle:
restoreStyle(listener, entity);
break;
case Info:
break;
default:
throw new RuntimeException("Unknown Entity type: " + entity.getType().toString());
}
entity = nextEntity();
}
close();
System.out.println("Restored " + coverCount + " covers");
}
/**
* Restore the books from the export file.
*
* @param listener
* @param entity
* @throws IOException
*/
private void restoreBooks(final BackupReaderListener listener, ReaderEntity entity, int importFlags) throws IOException {
// Make a listener for the 'export' function that just passes on the progress to out listener
Importer.OnImporterListener importListener = new Importer.OnImporterListener() {
private int mLastPos = 0;
@Override
public void onProgress(String message, int position) {
// The progress is sent periodically and has jumps, so we calculate deltas
listener.step(message, position - mLastPos);
mLastPos = position;
}
@Override
public boolean isCancelled() {
return listener.isCancelled();
}
@Override
public void setMax(int max) {
// Ignore; we know how many books there are
}
};
// Now do the import
InputStream in = entity.getStream();
CsvImporter importer = new CsvImporter();
importer.importBooks(in, null, importListener, importFlags);
}
/**
* Restore a cover file.
*
* @param listener
* @param cover
* @throws IOException
*/
private void restoreCover(BackupReaderListener listener, ReaderEntity cover, int flags) throws IOException {
listener.step("Processing Covers...", 1);
final File curr = new File(mSharedStorage + "/" + cover.getName());
final Date covDate = cover.getDateModified();
if ( (flags & Importer.IMPORT_NEW_OR_UPDATED) != 0) {
if (curr.exists()) {
Date currFileDate = new Date(curr.lastModified());
if (currFileDate.compareTo(covDate) >= 0) {
return;
}
}
}
cover.saveToDirectory(mSharedStorage);
curr.setLastModified(covDate.getTime());
}
/**
* Restore the app preferences
*
* @param listener
* @param entity
* @throws IOException
*/
private void restorePreferences(BackupReaderListener listener, ReaderEntity entity) throws IOException {
listener.step("Preferences...", 1);
SharedPreferences prefs = BookCataloguePreferences.getSharedPreferences();
entity.getPreferences(prefs);
}
/**
* Restore a booklist style
*
* @param listener
* @param entity
* @throws IOException
*/
private void restoreStyle(BackupReaderListener listener, ReaderEntity entity) throws IOException {
listener.step("Booklist Styles...", 1);
BooklistStyle s = null;
try {
s = (BooklistStyle) entity.getSerializable();
} catch (DeserializationException e) {
Logger.logError(e, "Unable to restore style");
}
if (s != null) {
s.saveToDb(mDbHelper);
}
}
/**
* Close the reader
*/
public void close() throws IOException {
mDbHelper.close();
}
}