mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-04 18:29:23 +02:00
move code moved from Library to BookCollection
This commit is contained in:
parent
d2dd11cb45
commit
071a3d8787
3 changed files with 110 additions and 58 deletions
|
@ -36,19 +36,27 @@ public class LibraryService extends Service {
|
||||||
}
|
}
|
||||||
final BookCollection collection = new BookCollection(database);
|
final BookCollection collection = new BookCollection(database);
|
||||||
final long start = System.currentTimeMillis();
|
final long start = System.currentTimeMillis();
|
||||||
collection.addChangeListener(new BookCollection.ChangeListener() {
|
collection.addListener(new BookCollection.Listener() {
|
||||||
public void onCollectionChanged(Code code, Book book) {
|
public void onBookEvent(BookEvent event, Book book) {
|
||||||
switch (code) {
|
switch (event) {
|
||||||
case BookAdded:
|
case Added:
|
||||||
System.err.println("Added " + book.getTitle());
|
System.err.println("Added " + book.getTitle());
|
||||||
break;
|
break;
|
||||||
case BuildStarted:
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onBuildEvent(BuildEvent event) {
|
||||||
|
switch (event) {
|
||||||
|
case Started:
|
||||||
System.err.println("Build started");
|
System.err.println("Build started");
|
||||||
break;
|
break;
|
||||||
case BuildSucceeded:
|
case Succeeded:
|
||||||
System.err.println("Build succeeded");
|
System.err.println("Build succeeded");
|
||||||
break;
|
break;
|
||||||
case BuildCompleted:
|
case Failed:
|
||||||
|
System.err.println("Build failed");
|
||||||
|
break;
|
||||||
|
case Completed:
|
||||||
System.err.println("Build completed with " + collection.size() + " books in " + (System.currentTimeMillis() - start) + " milliseconds");
|
System.err.println("Build completed with " + collection.size() + " books in " + (System.currentTimeMillis() - start) + " milliseconds");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,39 +29,54 @@ import org.geometerplus.fbreader.Paths;
|
||||||
import org.geometerplus.fbreader.bookmodel.BookReadingException;
|
import org.geometerplus.fbreader.bookmodel.BookReadingException;
|
||||||
|
|
||||||
public class BookCollection {
|
public class BookCollection {
|
||||||
private final List<ChangeListener> myListeners = Collections.synchronizedList(new LinkedList<ChangeListener>());
|
private final List<Listener> myListeners = Collections.synchronizedList(new LinkedList<Listener>());
|
||||||
|
|
||||||
public interface ChangeListener {
|
public interface Listener {
|
||||||
public enum Code {
|
public enum BookEvent {
|
||||||
BookAdded,
|
Added,
|
||||||
BookRemoved,
|
Updated,
|
||||||
BuildStarted,
|
Removed
|
||||||
BuildNotStarted,
|
|
||||||
BuildSucceeded,
|
|
||||||
BuildCompleted
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCollectionChanged(Code code, Book book);
|
public enum BuildEvent {
|
||||||
|
Started,
|
||||||
|
NotStarted,
|
||||||
|
Succeeded,
|
||||||
|
Failed,
|
||||||
|
Completed
|
||||||
|
}
|
||||||
|
|
||||||
|
void onBookEvent(BookEvent event, Book book);
|
||||||
|
void onBuildEvent(BuildEvent event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addChangeListener(ChangeListener listener) {
|
public void addListener(Listener listener) {
|
||||||
myListeners.add(listener);
|
myListeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeChangeListener(ChangeListener listener) {
|
public void removeListener(Listener listener) {
|
||||||
myListeners.remove(listener);
|
myListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fireModelChangedEvent(ChangeListener.Code code, Book book) {
|
protected void fireBookEvent(Listener.BookEvent event, Book book) {
|
||||||
synchronized (myListeners) {
|
synchronized (myListeners) {
|
||||||
for (ChangeListener l : myListeners) {
|
for (Listener l : myListeners) {
|
||||||
l.onCollectionChanged(code, book);
|
l.onBookEvent(event, book);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected void fireBuildEvent(Listener.BuildEvent event) {
|
||||||
|
synchronized (myListeners) {
|
||||||
|
for (Listener l : myListeners) {
|
||||||
|
l.onBuildEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private final BooksDatabase myDatabase;
|
private final BooksDatabase myDatabase;
|
||||||
private final Map<ZLFile,Book> myBooks =
|
private final Map<ZLFile,Book> myBooksByFile =
|
||||||
Collections.synchronizedMap(new HashMap<ZLFile,Book>());
|
Collections.synchronizedMap(new LinkedHashMap<ZLFile,Book>());
|
||||||
|
private final Map<Long,Book> myBooksById =
|
||||||
|
Collections.synchronizedMap(new HashMap<Long,Book>());
|
||||||
private volatile boolean myBuildStarted = false;
|
private volatile boolean myBuildStarted = false;
|
||||||
|
|
||||||
public BookCollection(BooksDatabase db) {
|
public BookCollection(BooksDatabase db) {
|
||||||
|
@ -69,19 +84,27 @@ public class BookCollection {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return myBooks.size();
|
return myBooksByFile.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addBook(Book book) {
|
private void addBook(Book book) {
|
||||||
if (book == null || myBooks.containsKey(book.File)) {
|
if (book == null || myBooksByFile.containsKey(book.File)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
myBooks.put(book.File, book);
|
myBooksByFile.put(book.File, book);
|
||||||
fireModelChangedEvent(ChangeListener.Code.BookAdded, book);
|
addBookById(book);
|
||||||
|
fireBookEvent(Listener.BookEvent.Added, book);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addBookById(Book book) {
|
||||||
|
final long id = book.getId();
|
||||||
|
if (id != -1) {
|
||||||
|
myBooksById.put(id, book);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeBook(Book book, boolean deleteFromDisk) {
|
public void removeBook(Book book, boolean deleteFromDisk) {
|
||||||
myBooks.remove(book.File);
|
myBooksByFile.remove(book.File);
|
||||||
final List<Long> ids = myDatabase.loadRecentBookIds();
|
final List<Long> ids = myDatabase.loadRecentBookIds();
|
||||||
if (ids.remove(book.getId())) {
|
if (ids.remove(book.getId())) {
|
||||||
myDatabase.saveRecentBookIds(ids);
|
myDatabase.saveRecentBookIds(ids);
|
||||||
|
@ -90,12 +113,12 @@ public class BookCollection {
|
||||||
if (deleteFromDisk) {
|
if (deleteFromDisk) {
|
||||||
book.File.getPhysicalFile().delete();
|
book.File.getPhysicalFile().delete();
|
||||||
}
|
}
|
||||||
fireModelChangedEvent(ChangeListener.Code.BookRemoved, book);
|
fireBookEvent(Listener.BookEvent.Removed, book);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Book> books() {
|
public List<Book> books() {
|
||||||
synchronized (myBooks) {
|
synchronized (myBooksByFile) {
|
||||||
return new ArrayList<Book>(myBooks.values());
|
return new ArrayList<Book>(myBooksByFile.values());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +127,29 @@ public class BookCollection {
|
||||||
return recentIds.size() > index ? Book.getById(recentIds.get(index)) : null;
|
return recentIds.size() > index ? Book.getById(recentIds.get(index)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addBookToRecentList(Book book) {
|
||||||
|
final List<Long> ids = myDatabase.loadRecentBookIds();
|
||||||
|
final Long bookId = book.getId();
|
||||||
|
ids.remove(bookId);
|
||||||
|
ids.add(0, bookId);
|
||||||
|
if (ids.size() > 12) {
|
||||||
|
ids.remove(12);
|
||||||
|
}
|
||||||
|
myDatabase.saveRecentBookIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBookFavorite(Book book, boolean favorite) {
|
||||||
|
if (favorite) {
|
||||||
|
myDatabase.addToFavorites(book.getId());
|
||||||
|
} else {
|
||||||
|
myDatabase.removeFromFavorites(book.getId());
|
||||||
|
}
|
||||||
|
fireBookEvent(Listener.BookEvent.Updated, book);
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void startBuild() {
|
public synchronized void startBuild() {
|
||||||
if (myBuildStarted) {
|
if (myBuildStarted) {
|
||||||
fireModelChangedEvent(ChangeListener.Code.BuildNotStarted, null);
|
fireBuildEvent(Listener.BuildEvent.NotStarted);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
myBuildStarted = true;
|
myBuildStarted = true;
|
||||||
|
@ -114,11 +157,13 @@ public class BookCollection {
|
||||||
final Thread builder = new Thread("Library.build") {
|
final Thread builder = new Thread("Library.build") {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
fireModelChangedEvent(ChangeListener.Code.BuildStarted, null);
|
fireBuildEvent(Listener.BuildEvent.Started);
|
||||||
build();
|
build();
|
||||||
fireModelChangedEvent(ChangeListener.Code.BuildSucceeded, null);
|
fireBuildEvent(Listener.BuildEvent.Succeeded);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
fireBuildEvent(Listener.BuildEvent.Failed);
|
||||||
} finally {
|
} finally {
|
||||||
fireModelChangedEvent(ChangeListener.Code.BuildCompleted, null);
|
fireBuildEvent(Listener.BuildEvent.Completed);
|
||||||
myBuildStarted = false;
|
myBuildStarted = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,7 +258,7 @@ public class BookCollection {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//myRootTree.removeBook(book, true);
|
//myRootTree.removeBook(book, true);
|
||||||
//fireModelChangedEvent(ChangeListener.Code.BookRemoved);
|
//fireBookEvent(Listener.BookEvent.Removed);
|
||||||
orphanedBooks.add(book);
|
orphanedBooks.add(book);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,6 +304,7 @@ public class BookCollection {
|
||||||
public void run() {
|
public void run() {
|
||||||
for (Book book : newBooks) {
|
for (Book book : newBooks) {
|
||||||
book.save();
|
book.save();
|
||||||
|
addBookById(book);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -101,20 +101,25 @@ public final class Library {
|
||||||
public Library(BooksDatabase db) {
|
public Library(BooksDatabase db) {
|
||||||
myDatabase = db;
|
myDatabase = db;
|
||||||
myCollection = new BookCollection(db);
|
myCollection = new BookCollection(db);
|
||||||
myCollection.addChangeListener(new BookCollection.ChangeListener() {
|
myCollection.addListener(new BookCollection.Listener() {
|
||||||
public void onCollectionChanged(Code code, Book book) {
|
public void onBookEvent(BookEvent event, Book book) {
|
||||||
switch (code) {
|
switch (event) {
|
||||||
case BookAdded:
|
case Added:
|
||||||
addBookToLibraryWithNoCheck(book);
|
addBookToLibrary(book);
|
||||||
if (myCollection.size() % 16 == 0) {
|
if (myCollection.size() % 16 == 0) {
|
||||||
Library.this.fireModelChangedEvent(ChangeListener.Code.BookAdded);
|
Library.this.fireModelChangedEvent(ChangeListener.Code.BookAdded);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BuildStarted:
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onBuildEvent(BuildEvent event) {
|
||||||
|
switch (event) {
|
||||||
|
case Started:
|
||||||
Library.this.fireModelChangedEvent(ChangeListener.Code.StatusChanged);
|
Library.this.fireModelChangedEvent(ChangeListener.Code.StatusChanged);
|
||||||
setStatus(myStatusMask | STATUS_LOADING);
|
setStatus(myStatusMask | STATUS_LOADING);
|
||||||
break;
|
break;
|
||||||
case BuildCompleted:
|
case Completed:
|
||||||
Library.this.fireModelChangedEvent(ChangeListener.Code.BookAdded);
|
Library.this.fireModelChangedEvent(ChangeListener.Code.BookAdded);
|
||||||
setStatus(myStatusMask & ~STATUS_LOADING);
|
setStatus(myStatusMask & ~STATUS_LOADING);
|
||||||
break;
|
break;
|
||||||
|
@ -179,7 +184,7 @@ public final class Library {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void addBookToLibraryWithNoCheck(Book book) {
|
private synchronized void addBookToLibrary(Book book) {
|
||||||
final String xml = BookSerializerUtil.serialize(book);
|
final String xml = BookSerializerUtil.serialize(book);
|
||||||
book = BookSerializerUtil.deserialize(xml);
|
book = BookSerializerUtil.deserialize(xml);
|
||||||
|
|
||||||
|
@ -265,7 +270,7 @@ public final class Library {
|
||||||
removeFromTree(ROOT_BY_SERIES, book);
|
removeFromTree(ROOT_BY_SERIES, book);
|
||||||
removeFromTree(ROOT_BY_AUTHOR, book);
|
removeFromTree(ROOT_BY_AUTHOR, book);
|
||||||
removeFromTree(ROOT_BY_TAG, book);
|
removeFromTree(ROOT_BY_TAG, book);
|
||||||
addBookToLibraryWithNoCheck(book);
|
addBookToLibrary(book);
|
||||||
fireModelChangedEvent(ChangeListener.Code.BookAdded);
|
fireModelChangedEvent(ChangeListener.Code.BookAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,14 +341,7 @@ public final class Library {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBookToRecentList(Book book) {
|
public void addBookToRecentList(Book book) {
|
||||||
final List<Long> ids = myDatabase.loadRecentBookIds();
|
myCollection.addBookToRecentList(book);
|
||||||
final Long bookId = book.getId();
|
|
||||||
ids.remove(bookId);
|
|
||||||
ids.add(0, bookId);
|
|
||||||
if (ids.size() > 12) {
|
|
||||||
ids.remove(12);
|
|
||||||
}
|
|
||||||
myDatabase.saveRecentBookIds(ids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBookInFavorites(Book book) {
|
public boolean isBookInFavorites(Book book) {
|
||||||
|
@ -365,12 +363,12 @@ public final class Library {
|
||||||
}
|
}
|
||||||
final LibraryTree rootFavorites = getFirstLevelTree(ROOT_FAVORITES);
|
final LibraryTree rootFavorites = getFirstLevelTree(ROOT_FAVORITES);
|
||||||
rootFavorites.getBookSubTree(book, true);
|
rootFavorites.getBookSubTree(book, true);
|
||||||
myDatabase.addToFavorites(book.getId());
|
myCollection.setBookFavorite(book, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeBookFromFavorites(Book book) {
|
public void removeBookFromFavorites(Book book) {
|
||||||
if (getFirstLevelTree(ROOT_FAVORITES).removeBook(book, false)) {
|
if (getFirstLevelTree(ROOT_FAVORITES).removeBook(book, false)) {
|
||||||
myDatabase.removeFromFavorites(book.getId());
|
myCollection.setBookFavorite(book, false);
|
||||||
fireModelChangedEvent(ChangeListener.Code.BookRemoved);
|
fireModelChangedEvent(ChangeListener.Code.BookRemoved);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,11 +398,11 @@ public final class Library {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Bookmark> allBookmarks() {
|
public List<Bookmark> allBookmarks() {
|
||||||
return BooksDatabase.Instance().loadAllVisibleBookmarks();
|
return myDatabase.loadAllVisibleBookmarks();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Bookmark> invisibleBookmarks(Book book) {
|
public List<Bookmark> invisibleBookmarks(Book book) {
|
||||||
final List<Bookmark> list = BooksDatabase.Instance().loadBookmarks(book.getId(), false);
|
final List<Bookmark> list = myDatabase.loadBookmarks(book.getId(), false);
|
||||||
Collections.sort(list, new Bookmark.ByTimeComparator());
|
Collections.sort(list, new Bookmark.ByTimeComparator());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue