diff --git a/TODO.library b/TODO.library
index 1808dc412..3250121a8 100644
--- a/TODO.library
+++ b/TODO.library
@@ -3,14 +3,16 @@
* Watch filesystem after loading
DONE Covers loading in background
DONE Wait messages
-* Favorites
+DONE Favorites
+* Show text if the favorites list is empty
DONE Search
* Show wait message during search
* File view
-* Activity caption
+DONE Activity caption
* Book deleting
* Show book info activity instead of immediate opening/menu
* Main menu
* Context menu
* Reload book info from file
* Reload book info for all the files
+* Highlight current book
diff --git a/assets/resources/application/en.xml b/assets/resources/application/en.xml
index 685eb90ff..45a182e27 100644
--- a/assets/resources/application/en.xml
+++ b/assets/resources/application/en.xml
@@ -29,6 +29,8 @@
+
+
diff --git a/res/layout/library.xml b/res/layout/library.xml
deleted file mode 100644
index 9bd3088c8..000000000
--- a/res/layout/library.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
diff --git a/res/layout/library_ng_tree_item.xml b/res/layout/library_ng_tree_item.xml
deleted file mode 100644
index f0a630e93..000000000
--- a/res/layout/library_ng_tree_item.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/library_tree_item.xml b/res/layout/library_tree_item.xml
index 5ec288073..d8a841a7e 100644
--- a/res/layout/library_tree_item.xml
+++ b/res/layout/library_tree_item.xml
@@ -9,39 +9,43 @@
>
-
+
-
-
-
+
+
+
+
+
diff --git a/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java b/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java
index 430baab1f..1fb83c69f 100644
--- a/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java
+++ b/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java
@@ -60,7 +60,7 @@ public final class SQLiteBooksDatabase extends BooksDatabase {
private void migrate(Context context) {
final int version = myDatabase.getVersion();
- final int currentVersion = 10;
+ final int currentVersion = 11;
if (version >= currentVersion) {
return;
}
@@ -89,6 +89,8 @@ public final class SQLiteBooksDatabase extends BooksDatabase {
updateTables8();
case 9:
updateTables9();
+ case 10:
+ updateTables10();
}
myDatabase.setTransactionSuccessful();
myDatabase.endTransaction();
@@ -646,6 +648,40 @@ public final class SQLiteBooksDatabase extends BooksDatabase {
return ids;
}
+ private SQLiteStatement myAddToFavoritesStatement;
+ protected void addToFavorites(long bookId) {
+ if (myAddToFavoritesStatement == null) {
+ myAddToFavoritesStatement = myDatabase.compileStatement(
+ "INSERT OR IGNORE INTO Favorites(book_id) VALUES (?)"
+ );
+ }
+ myAddToFavoritesStatement.bindLong(1, bookId);
+ myAddToFavoritesStatement.execute();
+ }
+
+ private SQLiteStatement myRemoveFromFavoritesStatement;
+ protected void removeFromFavorites(long bookId) {
+ if (myRemoveFromFavoritesStatement == null) {
+ myRemoveFromFavoritesStatement = myDatabase.compileStatement(
+ "DELETE FROM Favorites WHERE book_id = ?"
+ );
+ }
+ myRemoveFromFavoritesStatement.bindLong(1, bookId);
+ myRemoveFromFavoritesStatement.execute();
+ }
+
+ protected List loadFavoritesIds() {
+ final Cursor cursor = myDatabase.rawQuery(
+ "SELECT book_id FROM Favorites", null
+ );
+ final LinkedList ids = new LinkedList();
+ while (cursor.moveToNext()) {
+ ids.add(cursor.getLong(0));
+ }
+ cursor.close();
+ return ids;
+ }
+
protected List loadBookmarks(long bookId) {
LinkedList list = new LinkedList();
Cursor cursor = myDatabase.rawQuery(
@@ -1071,4 +1107,10 @@ public final class SQLiteBooksDatabase extends BooksDatabase {
private void updateTables9() {
myDatabase.execSQL("CREATE INDEX BookList_BookIndex ON BookList (book_id)");
}
+
+ private void updateTables10() {
+ myDatabase.execSQL(
+ "CREATE TABLE IF NOT EXISTS Favorites(" +
+ "book_id INTEGER UNIQUE NOT NULL REFERENCES Books(book_id))");
+ }
}
diff --git a/src/org/geometerplus/android/fbreader/library/LibraryBaseActivity.java b/src/org/geometerplus/android/fbreader/library/LibraryBaseActivity.java
index 1c1122cb5..b9e61c317 100644
--- a/src/org/geometerplus/android/fbreader/library/LibraryBaseActivity.java
+++ b/src/org/geometerplus/android/fbreader/library/LibraryBaseActivity.java
@@ -41,6 +41,7 @@ import org.geometerplus.zlibrary.ui.android.image.ZLAndroidImageLoader;
import org.geometerplus.fbreader.tree.FBTree;
import org.geometerplus.fbreader.library.*;
+import org.geometerplus.android.fbreader.FBReader;
import org.geometerplus.zlibrary.ui.android.R;
@@ -48,12 +49,21 @@ import org.geometerplus.android.util.UIUtil;
import org.geometerplus.android.fbreader.tree.ZLAndroidTree;
abstract class LibraryBaseActivity extends ListActivity {
+ public static final String SELECTED_BOOK_PATH_KEY = "SelectedBookPath";
+ static final String TREE_PATH_KEY = "TreePath";
+ static final String PARAMETER_KEY = "Parameter";
+
+ static final String PATH_FAVORITES = "favorites";
+ static final String PATH_SEARCH_RESULTS = "searchResults";
+ static final String PATH_RECENT = "recent";
+ static final String PATH_BY_AUTHOR = "byAuthor";
+ static final String PATH_BY_TAG = "byTag";
+
static Library Library;
+
static final ZLStringOption BookSearchPatternOption =
new ZLStringOption("BookSearch", "Pattern", "");
- public static final String SELECTED_BOOK_PATH_KEY = "SelectedBookPath";
-
protected final ZLResource myResource = ZLResource.resource("libraryView");
protected String mySelectedBookPath;
@@ -64,11 +74,6 @@ abstract class LibraryBaseActivity extends ListActivity {
mySelectedBookPath = getIntent().getStringExtra(SELECTED_BOOK_PATH_KEY);
}
- @Override
- public void onListItemClick(ListView listView, View view, int position, long rowId) {
- FBTree tree = ((LibraryAdapter)getListAdapter()).getItem(position);
- }
-
@Override
public boolean onSearchRequested() {
startSearch(BookSearchPatternOption.getValue(), true, null, false);
@@ -94,25 +99,45 @@ abstract class LibraryBaseActivity extends ListActivity {
).show();
}
- protected final class LibraryAdapter extends BaseAdapter {
+ protected final class LibraryAdapter extends BaseAdapter implements View.OnCreateContextMenuListener {
private final List myItems;
public LibraryAdapter(List items) {
myItems = items;
}
+ @Override
public final int getCount() {
return myItems.size();
}
+ @Override
public final FBTree getItem(int position) {
return myItems.get(position);
}
+ @Override
public final long getItemId(int position) {
return position;
}
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
+ final int position = ((AdapterView.AdapterContextMenuInfo)menuInfo).position;
+ final LibraryTree tree = (LibraryTree)getItem(position);
+ if (tree instanceof BookTree) {
+ menu.setHeaderTitle(tree.getName());
+ menu.add(0, OPEN_BOOK_ITEM_ID, 0, myResource.getResource("openBook").getValue());
+ if (Library.isBookInFavorites(((BookTree)tree).Book)) {
+ menu.add(0, REMOVE_FROM_FAVORITES_ITEM_ID, 0, myResource.getResource("removeFromFavorites").getValue());
+ } else {
+ menu.add(0, ADD_TO_FAVORITES_ITEM_ID, 0, myResource.getResource("addToFavorites").getValue());
+ }
+ if ((Library.getRemoveBookMode(((BookTree)tree).Book) & Library.REMOVE_FROM_DISK) != 0) {
+ menu.add(0, DELETE_BOOK_ITEM_ID, 0, myResource.getResource("deleteBook").getValue());
+ }
+ }
+ }
+
private int myCoverWidth = -1;
private int myCoverHeight = -1;
@@ -125,10 +150,10 @@ abstract class LibraryBaseActivity extends ListActivity {
public View getView(int position, View convertView, final ViewGroup parent) {
final FBTree tree = getItem(position);
final View view = (convertView != null) ? convertView :
- LayoutInflater.from(parent.getContext()).inflate(R.layout.library_ng_tree_item, parent, false);
+ LayoutInflater.from(parent.getContext()).inflate(R.layout.library_tree_item, parent, false);
- ((TextView)view.findViewById(R.id.library_ng_tree_item_name)).setText(tree.getName());
- ((TextView)view.findViewById(R.id.library_ng_tree_item_childrenlist)).setText(tree.getSecondString());
+ ((TextView)view.findViewById(R.id.library_tree_item_name)).setText(tree.getName());
+ ((TextView)view.findViewById(R.id.library_tree_item_childrenlist)).setText(tree.getSecondString());
if (myCoverWidth == -1) {
view.measure(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@@ -137,7 +162,7 @@ abstract class LibraryBaseActivity extends ListActivity {
view.requestLayout();
}
- final ImageView coverView = (ImageView)view.findViewById(R.id.library_ng_tree_item_icon);
+ final ImageView coverView = (ImageView)view.findViewById(R.id.library_tree_item_icon);
coverView.getLayoutParams().width = myCoverWidth;
coverView.getLayoutParams().height = myCoverHeight;
coverView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
@@ -182,12 +207,57 @@ abstract class LibraryBaseActivity extends ListActivity {
}
}
+ protected void openBook(Book book) {
+ startActivity(
+ new Intent(getApplicationContext(), FBReader.class)
+ .setAction(Intent.ACTION_VIEW)
+ .putExtra(FBReader.BOOK_PATH_KEY, book.File.getPath())
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
+ );
+ }
+
+ private static final int OPEN_BOOK_ITEM_ID = 0;
+ private static final int ADD_TO_FAVORITES_ITEM_ID = 1;
+ private static final int REMOVE_FROM_FAVORITES_ITEM_ID = 2;
+ private static final int DELETE_BOOK_ITEM_ID = 3;
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ final int position = ((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).position;
+ final FBTree tree = ((LibraryAdapter)getListAdapter()).getItem(position);
+ if (tree instanceof BookTree) {
+ final BookTree bookTree = (BookTree)tree;
+ switch (item.getItemId()) {
+ case OPEN_BOOK_ITEM_ID:
+ openBook(bookTree.Book);
+ return true;
+ case ADD_TO_FAVORITES_ITEM_ID:
+ Library.addBookToFavorites(bookTree.Book);
+ return true;
+ case REMOVE_FROM_FAVORITES_ITEM_ID:
+ Library.removeBookFromFavorites(bookTree.Book);
+ getListView().invalidateViews();
+ return true;
+ case DELETE_BOOK_ITEM_ID:
+ // TODO: implement
+ return true;
+ }
+ }
+ return super.onContextItemSelected(item);
+ }
+
protected class OpenTreeRunnable implements Runnable {
private final String myTreePath;
+ private final String myParameter;
private final String mySelectedBookPath;
public OpenTreeRunnable(String treePath, String selectedBookPath) {
+ this(treePath, null, selectedBookPath);
+ }
+
+ public OpenTreeRunnable(String treePath, String parameter, String selectedBookPath) {
myTreePath = treePath;
+ myParameter = parameter;
mySelectedBookPath = selectedBookPath;
}
@@ -197,7 +267,8 @@ abstract class LibraryBaseActivity extends ListActivity {
startActivity(
new Intent(LibraryBaseActivity.this, LibraryTreeActivity.class)
.putExtra(SELECTED_BOOK_PATH_KEY, mySelectedBookPath)
- .putExtra(LibraryTreeActivity.TREE_PATH_KEY, myTreePath)
+ .putExtra(TREE_PATH_KEY, myTreePath)
+ .putExtra(PARAMETER_KEY, myParameter)
);
}
};
diff --git a/src/org/geometerplus/android/fbreader/library/LibraryTopLevelActivity.java b/src/org/geometerplus/android/fbreader/library/LibraryTopLevelActivity.java
index fb1a956f4..fab34968e 100644
--- a/src/org/geometerplus/android/fbreader/library/LibraryTopLevelActivity.java
+++ b/src/org/geometerplus/android/fbreader/library/LibraryTopLevelActivity.java
@@ -60,24 +60,24 @@ public class LibraryTopLevelActivity extends LibraryBaseActivity {
myItems = new LinkedList();
myItems.add(new TopLevelTree(
- myResource.getResource("favorites"),
+ myResource.getResource(PATH_FAVORITES),
R.drawable.ic_list_library_favorites,
- new OpenTreeRunnable(LibraryTreeActivity.PATH_FAVORITES, mySelectedBookPath)
+ new OpenTreeRunnable(PATH_FAVORITES, mySelectedBookPath)
));
myItems.add(new TopLevelTree(
- myResource.getResource("recent"),
+ myResource.getResource(PATH_RECENT),
R.drawable.ic_list_library_recent,
- new OpenTreeRunnable(LibraryTreeActivity.PATH_RECENT, mySelectedBookPath)
+ new OpenTreeRunnable(PATH_RECENT, mySelectedBookPath)
));
myItems.add(new TopLevelTree(
- myResource.getResource("byAuthor"),
+ myResource.getResource(PATH_BY_AUTHOR),
R.drawable.ic_list_library_authors,
- new OpenTreeRunnable(LibraryTreeActivity.PATH_BY_AUTHOR, mySelectedBookPath)
+ new OpenTreeRunnable(PATH_BY_AUTHOR, mySelectedBookPath)
));
myItems.add(new TopLevelTree(
- myResource.getResource("byTag"),
+ myResource.getResource(PATH_BY_TAG),
R.drawable.ic_list_library_tags,
- new OpenTreeRunnable(LibraryTreeActivity.PATH_BY_TAG, mySelectedBookPath)
+ new OpenTreeRunnable(PATH_BY_TAG, mySelectedBookPath)
));
myItems.add(new TopLevelTree(
myResource.getResource("fileTree"),
@@ -109,11 +109,12 @@ public class LibraryTopLevelActivity extends LibraryBaseActivity {
if (myItems.get(0) == mySearchResultsItem) {
myItems.remove(0);
}
+ final String pattern = intent.getStringExtra(SearchManager.QUERY);
mySearchResultsItem = new TopLevelTree(
- myResource.getResource("searchResults"),
- intent.getStringExtra(SearchManager.QUERY),
+ myResource.getResource(PATH_SEARCH_RESULTS),
+ pattern,
R.drawable.ic_list_library_books,
- new OpenTreeRunnable(LibraryTreeActivity.PATH_SEARCH_RESULTS, mySelectedBookPath)
+ new OpenTreeRunnable(PATH_SEARCH_RESULTS, pattern, mySelectedBookPath)
);
myItems.add(0, mySearchResultsItem);
getListView().invalidateViews();
diff --git a/src/org/geometerplus/android/fbreader/library/LibraryTreeActivity.java b/src/org/geometerplus/android/fbreader/library/LibraryTreeActivity.java
index a3ddbaf43..c8615f671 100644
--- a/src/org/geometerplus/android/fbreader/library/LibraryTreeActivity.java
+++ b/src/org/geometerplus/android/fbreader/library/LibraryTreeActivity.java
@@ -29,17 +29,7 @@ import org.geometerplus.fbreader.tree.FBTree;
import org.geometerplus.fbreader.library.Library;
import org.geometerplus.fbreader.library.BookTree;
-import org.geometerplus.android.fbreader.FBReader;
-
public class LibraryTreeActivity extends LibraryBaseActivity {
- static final String TREE_PATH_KEY = "TreePath";
-
- static final String PATH_FAVORITES = "favorites";
- static final String PATH_SEARCH_RESULTS = "searchResults";
- static final String PATH_RECENT = "recent";
- static final String PATH_BY_AUTHOR = "author";
- static final String PATH_BY_TAG = "tag";
-
private String myTreePathString;
private String mySelectedBookPath;
@@ -59,34 +49,50 @@ public class LibraryTreeActivity extends LibraryBaseActivity {
showNotFoundToast();
finish();
}
+ return;
+ }
+
+ myTreePathString = intent.getStringExtra(TREE_PATH_KEY);
+ mySelectedBookPath = intent.getStringExtra(SELECTED_BOOK_PATH_KEY);
+
+ final String[] path = myTreePathString.split("\000");
+
+ String title = null;
+ if (path.length == 1) {
+ title = myResource.getResource(path[0]).getResource("summary").getValue();
+ final String parameter = intent.getStringExtra(PARAMETER_KEY);
+ if (parameter != null) {
+ title = title.replace("%s", parameter);
+ }
} else {
- myTreePathString = getIntent().getStringExtra(TREE_PATH_KEY);
- mySelectedBookPath = getIntent().getStringExtra(SELECTED_BOOK_PATH_KEY);
+ title = path[path.length - 1];
+ }
+ setTitle(title);
+
+ FBTree tree = null;
+ if (PATH_RECENT.equals(path[0])) {
+ tree = Library.recentBooks();
+ } else if (PATH_SEARCH_RESULTS.equals(path[0])) {
+ tree = Library.searchResults();
+ } else if (PATH_BY_AUTHOR.equals(path[0])) {
+ tree = Library.byAuthor();
+ } else if (PATH_BY_TAG.equals(path[0])) {
+ tree = Library.byTag();
+ } else if (PATH_FAVORITES.equals(path[0])) {
+ tree = Library.favorites();
+ }
- final String[] path = myTreePathString.split("\000");
-
- FBTree tree = null;
- if (PATH_RECENT.equals(path[0])) {
- tree = Library.recentBooks();
- } else if (PATH_SEARCH_RESULTS.equals(path[0])) {
- tree = Library.searchResults();
- } else if (PATH_BY_AUTHOR.equals(path[0])) {
- tree = Library.byAuthor();
- } else if (PATH_BY_TAG.equals(path[0])) {
- tree = Library.byTag();
- } else if (PATH_FAVORITES.equals(path[0])) {
+ for (int i = 1; i < path.length; ++i) {
+ if (tree == null) {
+ break;
}
+ tree = tree.getSubTreeByName(path[i]);
+ }
- for (int i = 1; i < path.length; ++i) {
- if (tree == null) {
- break;
- }
- tree = tree.getSubTreeByName(path[i]);
- }
-
- if (tree != null) {
- setListAdapter(new LibraryAdapter(tree.subTrees()));
- }
+ if (tree != null) {
+ final LibraryAdapter adapter = new LibraryAdapter(tree.subTrees());
+ setListAdapter(adapter);
+ getListView().setOnCreateContextMenuListener(adapter);
}
}
@@ -94,12 +100,7 @@ public class LibraryTreeActivity extends LibraryBaseActivity {
public void onListItemClick(ListView listView, View view, int position, long rowId) {
FBTree tree = ((LibraryAdapter)getListAdapter()).getItem(position);
if (tree instanceof BookTree) {
- startActivity(
- new Intent(getApplicationContext(), FBReader.class)
- .setAction(Intent.ACTION_VIEW)
- .putExtra(FBReader.BOOK_PATH_KEY, ((BookTree)tree).Book.File.getPath())
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
- );
+ openBook(((BookTree)tree).Book);
} else {
new OpenTreeRunnable(
myTreePathString + "\000" + tree.getName(),
diff --git a/src/org/geometerplus/fbreader/library/BooksDatabase.java b/src/org/geometerplus/fbreader/library/BooksDatabase.java
index e4259a9ba..08e8d71df 100644
--- a/src/org/geometerplus/fbreader/library/BooksDatabase.java
+++ b/src/org/geometerplus/fbreader/library/BooksDatabase.java
@@ -84,6 +84,10 @@ public abstract class BooksDatabase {
protected abstract List loadRecentBookIds();
protected abstract void saveRecentBookIds(final List ids);
+ protected abstract List loadFavoritesIds();
+ protected abstract void addToFavorites(long bookId);
+ protected abstract void removeFromFavorites(long bookId);
+
protected Bookmark createBookmark(long id, long bookId, String bookTitle, String text, Date creationDate, Date modificationDate, Date accessDate, int accessCounter, String modelId, int paragraphIndex, int wordIndex, int charIndex) {
return new Bookmark(id, bookId, bookTitle, text, creationDate, modificationDate, accessDate, accessCounter, modelId, paragraphIndex, wordIndex, charIndex);
}
diff --git a/src/org/geometerplus/fbreader/library/Library.java b/src/org/geometerplus/fbreader/library/Library.java
index d179f8487..279f303ce 100644
--- a/src/org/geometerplus/fbreader/library/Library.java
+++ b/src/org/geometerplus/fbreader/library/Library.java
@@ -36,6 +36,7 @@ public final class Library {
private final LibraryTree myLibraryByAuthor = new RootTree();
private final LibraryTree myLibraryByTag = new RootTree();
private final LibraryTree myRecentBooks = new RootTree();
+ private final LibraryTree myFavorites = new RootTree();
private final LibraryTree mySearchResult = new RootTree();
private volatile int myState = STATE_NOT_INITIALIZED;
@@ -268,6 +269,14 @@ public final class Library {
}
}
+ for (long id : db.loadFavoritesIds()) {
+ Book book = bookById.get(id);
+ if (book != null) {
+ myFavorites.createBookSubTree(book, true);
+ }
+ }
+ myFavorites.sortAllChildren();
+
db.executeAsATransaction(new Runnable() {
public void run() {
for (Book book : myBooks) {
@@ -309,6 +318,11 @@ public final class Library {
return (recentIds.size() > 0) ? Book.getById(recentIds.get(0)) : null;
}
+ public LibraryTree favorites() {
+ waitForState(STATE_FULLY_INITIALIZED);
+ return myFavorites;
+ }
+
public LibraryTree searchResults() {
return mySearchResult;
}
@@ -340,6 +354,27 @@ public final class Library {
db.saveRecentBookIds(ids);
}
+ public boolean isBookInFavorites(Book book) {
+ waitForState(STATE_FULLY_INITIALIZED);
+ return myFavorites.containsBook(book);
+ }
+
+ public void addBookToFavorites(Book book) {
+ waitForState(STATE_FULLY_INITIALIZED);
+ if (!myFavorites.containsBook(book)) {
+ myFavorites.createBookSubTree(book, true);
+ myFavorites.sortAllChildren();
+ BooksDatabase.Instance().addToFavorites(book.getId());
+ }
+ }
+
+ public void removeBookFromFavorites(Book book) {
+ waitForState(STATE_FULLY_INITIALIZED);
+ if (myFavorites.removeBook(book)) {
+ BooksDatabase.Instance().removeFromFavorites(book.getId());
+ }
+ }
+
public static final int REMOVE_DONT_REMOVE = 0x00;
public static final int REMOVE_FROM_LIBRARY = 0x01;
public static final int REMOVE_FROM_DISK = 0x02;
@@ -380,6 +415,7 @@ public final class Library {
db.saveRecentBookIds(ids);
}
mySearchResult.removeBook(book);
+ myFavorites.removeBook(book);
BooksDatabase.Instance().deleteFromBookList(book.getId());
if ((removeMode & REMOVE_FROM_DISK) != 0) {
diff --git a/src/org/geometerplus/fbreader/library/LibraryTree.java b/src/org/geometerplus/fbreader/library/LibraryTree.java
index 299b25b07..1238f1e6e 100644
--- a/src/org/geometerplus/fbreader/library/LibraryTree.java
+++ b/src/org/geometerplus/fbreader/library/LibraryTree.java
@@ -46,6 +46,15 @@ public abstract class LibraryTree extends FBTree {
return new BookTree(this, book, showAuthors);
}
+ public boolean containsBook(Book book) {
+ for (FBTree tree : this) {
+ if ((tree instanceof BookTree) && ((BookTree)tree).Book.equals(book)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public boolean removeBook(Book book) {
final LinkedList toRemove = new LinkedList();
for (FBTree tree : this) {