diff --git a/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemTree.java b/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemTree.java index d625d2c86..5a22fe7e4 100644 --- a/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemTree.java +++ b/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemTree.java @@ -53,7 +53,7 @@ public class AddCustomCatalogItemTree extends NetworkTree implements ZLAndroidTr } @Override - public String getUniqueKey() { - return null; + protected String getStringId() { + return "@Add Custom Catalog"; } } diff --git a/src/org/geometerplus/android/fbreader/network/ItemsLoadingService.java b/src/org/geometerplus/android/fbreader/network/ItemsLoadingService.java index 34ff845ca..2e91b5d4c 100644 --- a/src/org/geometerplus/android/fbreader/network/ItemsLoadingService.java +++ b/src/org/geometerplus/android/fbreader/network/ItemsLoadingService.java @@ -25,6 +25,7 @@ import android.os.Message; import android.app.Service; import android.content.Intent; +import org.geometerplus.fbreader.network.NetworkTree; public class ItemsLoadingService extends Service { @@ -53,7 +54,7 @@ public class ItemsLoadingService extends Service { super.onStart(intent, startId); doStart(); - final String key = intent.getStringExtra(ITEMS_LOADING_RUNNABLE_KEY); + final NetworkTree.Key key = (NetworkTree.Key)intent.getSerializableExtra(ITEMS_LOADING_RUNNABLE_KEY); if (key == null) { doStop(); return; diff --git a/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java b/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java index 8a666abbd..086517278 100644 --- a/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java +++ b/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java @@ -272,11 +272,10 @@ class NetworkCatalogActions extends NetworkTreeActions { private static class ExpandCatalogHandler extends ItemsLoadingHandler { - - private final String myKey; + private final NetworkTree.Key myKey; private final NetworkCatalogTree myTree; - ExpandCatalogHandler(NetworkCatalogTree tree, String key) { + ExpandCatalogHandler(NetworkCatalogTree tree, NetworkTree.Key key) { myTree = tree; myKey = key; } @@ -389,7 +388,7 @@ class NetworkCatalogActions extends NetworkTreeActions { } private void doExpandCatalog(final NetworkBaseActivity activity, final NetworkCatalogTree tree) { - final String key = tree.getUniqueKey(); + final NetworkTree.Key key = tree.getUniqueKey(); NetworkView.Instance().tryResumeLoading(activity, tree, key, new Runnable() { public void run() { boolean resumeNotLoad = false; @@ -434,7 +433,7 @@ class NetworkCatalogActions extends NetworkTreeActions { } public void doReloadCatalog(NetworkBaseActivity activity, final NetworkCatalogTree tree) { - final String key = tree.getUniqueKey(); + final NetworkTree.Key key = tree.getUniqueKey(); if (NetworkView.Instance().containsItemsLoadingRunnable(key)) { return; } diff --git a/src/org/geometerplus/android/fbreader/network/NetworkCatalogActivity.java b/src/org/geometerplus/android/fbreader/network/NetworkCatalogActivity.java index d69d84838..89ebdbc7d 100644 --- a/src/org/geometerplus/android/fbreader/network/NetworkCatalogActivity.java +++ b/src/org/geometerplus/android/fbreader/network/NetworkCatalogActivity.java @@ -36,7 +36,7 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR public static final String CATALOG_KEY_KEY = "org.geometerplus.android.fbreader.network.CatalogKey"; private NetworkTree myTree; - private String myCatalogKey; + private NetworkTree.Key myCatalogKey; private volatile boolean myInProgress; @Override @@ -57,7 +57,7 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR throw new RuntimeException("Catalog's Level was not specified!!!"); } - myCatalogKey = intent.getStringExtra(CATALOG_KEY_KEY); + myCatalogKey = (NetworkTree.Key)intent.getSerializableExtra(CATALOG_KEY_KEY); if (myCatalogKey == null) { throw new RuntimeException("Catalog's Key was not specified!!!"); } @@ -183,10 +183,10 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR } } - private static String getLoadableNetworkTreeKey(NetworkTree tree) { + private static NetworkTree.Key getLoadableNetworkTreeKey(NetworkTree tree) { if ((tree instanceof NetworkAuthorTree || tree instanceof NetworkSeriesTree) && tree.Parent instanceof NetworkTree) { - return getLoadableNetworkTreeKey((NetworkTree) tree.Parent); + return getLoadableNetworkTreeKey((NetworkTree)tree.Parent); } return tree.getUniqueKey(); } @@ -194,7 +194,7 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR @Override public void onModelChanged() { final NetworkView networkView = NetworkView.Instance(); - final String key = getLoadableNetworkTreeKey(myTree); + final NetworkTree.Key key = getLoadableNetworkTreeKey(myTree); myInProgress = key != null && networkView.isInitialized() && networkView.containsItemsLoadingRunnable(key); getListView().invalidateViews(); @@ -218,9 +218,9 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR } private void doStopLoading() { - final String key = myCatalogKey; - if (key != null && NetworkView.Instance().isInitialized()) { - final ItemsLoadingRunnable runnable = NetworkView.Instance().getItemsLoadingRunnable(key); + if (NetworkView.Instance().isInitialized()) { + final ItemsLoadingRunnable runnable = + NetworkView.Instance().getItemsLoadingRunnable(myCatalogKey); if (runnable != null) { runnable.interruptLoading(); } diff --git a/src/org/geometerplus/android/fbreader/network/NetworkLibraryActivity.java b/src/org/geometerplus/android/fbreader/network/NetworkLibraryActivity.java index 7ff160ae1..69af7232a 100644 --- a/src/org/geometerplus/android/fbreader/network/NetworkLibraryActivity.java +++ b/src/org/geometerplus/android/fbreader/network/NetworkLibraryActivity.java @@ -275,8 +275,7 @@ public class NetworkLibraryActivity extends NetworkBaseActivity { } private static boolean searchIsInProgress() { - return NetworkView.Instance().containsItemsLoadingRunnable( - NetworkSearchActivity.SEARCH_RUNNABLE_KEY); + return NetworkView.Instance().containsItemsLoadingRunnable(NetworkTree.SearchKey); } @Override diff --git a/src/org/geometerplus/android/fbreader/network/NetworkSearchActivity.java b/src/org/geometerplus/android/fbreader/network/NetworkSearchActivity.java index eafb52370..37b865e8e 100644 --- a/src/org/geometerplus/android/fbreader/network/NetworkSearchActivity.java +++ b/src/org/geometerplus/android/fbreader/network/NetworkSearchActivity.java @@ -35,9 +35,6 @@ import org.geometerplus.fbreader.network.*; public class NetworkSearchActivity extends Activity { - - static final String SEARCH_RUNNABLE_KEY = "org.geometerplus.android.fbreader.network.NetworkSearchActivity"; - @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -109,7 +106,7 @@ public class NetworkSearchActivity extends Activity { } if (msg != null) { if (NetworkView.Instance().isInitialized()) { - final NetworkCatalogActivity activity = NetworkView.Instance().getOpenedActivity(SEARCH_RUNNABLE_KEY); + final NetworkCatalogActivity activity = NetworkView.Instance().getOpenedActivity(NetworkTree.SearchKey); if (activity != null) { final ZLResource buttonResource = dialogResource.getResource("button"); new AlertDialog.Builder(activity) @@ -148,7 +145,7 @@ public class NetworkSearchActivity extends Activity { final NetworkLibrary library = NetworkLibrary.Instance(); library.NetworkSearchPatternOption.setValue(pattern); - if (NetworkView.Instance().containsItemsLoadingRunnable(SEARCH_RUNNABLE_KEY)) { + if (NetworkView.Instance().containsItemsLoadingRunnable(NetworkTree.SearchKey)) { return; } @@ -163,9 +160,9 @@ public class NetworkSearchActivity extends Activity { final SearchHandler handler = new SearchHandler(tree); NetworkView.Instance().startItemsLoading( this, - SEARCH_RUNNABLE_KEY, + NetworkTree.SearchKey, new SearchRunnable(handler, pattern) ); - NetworkView.Instance().openTree(this, tree, SEARCH_RUNNABLE_KEY); + NetworkView.Instance().openTree(this, tree, NetworkTree.SearchKey); } } diff --git a/src/org/geometerplus/android/fbreader/network/NetworkView.java b/src/org/geometerplus/android/fbreader/network/NetworkView.java index 44435fe34..9c41f24f3 100644 --- a/src/org/geometerplus/android/fbreader/network/NetworkView.java +++ b/src/org/geometerplus/android/fbreader/network/NetworkView.java @@ -141,9 +141,10 @@ class NetworkView { * Code for loading network items (running items-loading service and managing items-loading runnables). */ - private final HashMap myItemsLoadingRunnables = new HashMap(); + private final HashMap myItemsLoadingRunnables = + new HashMap(); - public void startItemsLoading(Context context, String key, ItemsLoadingRunnable runnable) { + public void startItemsLoading(Context context, NetworkTree.Key key, ItemsLoadingRunnable runnable) { boolean doDownload = false; synchronized (myItemsLoadingRunnables) { if (!myItemsLoadingRunnables.containsKey(key)) { @@ -159,13 +160,13 @@ class NetworkView { } } - ItemsLoadingRunnable getItemsLoadingRunnable(String key) { + ItemsLoadingRunnable getItemsLoadingRunnable(NetworkTree.Key key) { synchronized (myItemsLoadingRunnables) { return myItemsLoadingRunnables.get(key); } } - void removeItemsLoadingRunnable(String key) { + void removeItemsLoadingRunnable(NetworkTree.Key key) { synchronized (myItemsLoadingRunnables) { ItemsLoadingRunnable runnable = myItemsLoadingRunnables.remove(key); if (runnable != null) { @@ -174,11 +175,11 @@ class NetworkView { } } - public final boolean containsItemsLoadingRunnable(String key) { + public final boolean containsItemsLoadingRunnable(NetworkTree.Key key) { return getItemsLoadingRunnable(key) != null; } - public void tryResumeLoading(NetworkBaseActivity activity, NetworkCatalogTree tree, String key, Runnable expandRunnable) { + public void tryResumeLoading(NetworkBaseActivity activity, NetworkCatalogTree tree, NetworkTree.Key key, Runnable expandRunnable) { final ItemsLoadingRunnable runnable = getItemsLoadingRunnable(key); if (runnable != null && runnable.tryResumeLoading()) { openTree(activity, tree, key); @@ -266,9 +267,10 @@ class NetworkView { */ private final LinkedList myOpenedStack = new LinkedList(); - private final HashMap myOpenedActivities = new HashMap(); + private final HashMap myOpenedActivities = + new HashMap(); - public void openTree(Context context, NetworkTree tree, String key) { + public void openTree(Context context, NetworkTree tree, NetworkTree.Key key) { final int level = tree.Level - 1; // tree.Level == 1 for catalog's root element if (level > myOpenedStack.size()) { throw new RuntimeException("Unable to open catalog with Level greater than the number of opened catalogs.\n" @@ -288,7 +290,7 @@ class NetworkView { ); } - void setOpenedActivity(String key, NetworkCatalogActivity activity) { + void setOpenedActivity(NetworkTree.Key key, NetworkCatalogActivity activity) { if (activity == null) { myOpenedActivities.remove(key); } else { @@ -296,7 +298,7 @@ class NetworkView { } } - public NetworkCatalogActivity getOpenedActivity(String key) { + public NetworkCatalogActivity getOpenedActivity(NetworkTree.Key key) { return myOpenedActivities.get(key); } diff --git a/src/org/geometerplus/android/fbreader/network/RefillAccountTree.java b/src/org/geometerplus/android/fbreader/network/RefillAccountTree.java index 7d10da183..4cb9791f2 100644 --- a/src/org/geometerplus/android/fbreader/network/RefillAccountTree.java +++ b/src/org/geometerplus/android/fbreader/network/RefillAccountTree.java @@ -75,7 +75,7 @@ class RefillAccountTree extends NetworkTree implements ZLAndroidTree { } @Override - public String getUniqueKey() { - return null; + protected String getStringId() { + return "@TopUp Account"; } } diff --git a/src/org/geometerplus/android/fbreader/network/SearchItemActions.java b/src/org/geometerplus/android/fbreader/network/SearchItemActions.java index 74d4ff35f..0f40cae2d 100644 --- a/src/org/geometerplus/android/fbreader/network/SearchItemActions.java +++ b/src/org/geometerplus/android/fbreader/network/SearchItemActions.java @@ -26,7 +26,6 @@ import android.view.ContextMenu; import org.geometerplus.fbreader.network.NetworkTree; import org.geometerplus.fbreader.network.SearchResult; - class SearchItemActions extends NetworkTreeActions { public static final int RUN_SEARCH_ITEM_ID = 0; @@ -50,7 +49,7 @@ class SearchItemActions extends NetworkTreeActions { public void buildContextMenu(Activity activity, ContextMenu menu, NetworkTree tree) { menu.setHeaderTitle(tree.getName()); - final boolean isLoading = NetworkView.Instance().containsItemsLoadingRunnable(NetworkSearchActivity.SEARCH_RUNNABLE_KEY); + final boolean isLoading = NetworkView.Instance().containsItemsLoadingRunnable(NetworkTree.SearchKey); if (!isLoading) { addMenuItem(menu, RUN_SEARCH_ITEM_ID, "search"); @@ -61,7 +60,7 @@ class SearchItemActions extends NetworkTreeActions { @Override public int getDefaultActionCode(NetworkBaseActivity activity, NetworkTree tree) { - final boolean isLoading = NetworkView.Instance().containsItemsLoadingRunnable(NetworkSearchActivity.SEARCH_RUNNABLE_KEY); + final boolean isLoading = NetworkView.Instance().containsItemsLoadingRunnable(NetworkTree.SearchKey); if (!isLoading) { return RUN_SEARCH_ITEM_ID; } diff --git a/src/org/geometerplus/android/fbreader/network/SearchItemTree.java b/src/org/geometerplus/android/fbreader/network/SearchItemTree.java index 286074501..379664ca9 100644 --- a/src/org/geometerplus/android/fbreader/network/SearchItemTree.java +++ b/src/org/geometerplus/android/fbreader/network/SearchItemTree.java @@ -104,7 +104,7 @@ public class SearchItemTree extends NetworkTree implements ZLAndroidTree { } @Override - public String getUniqueKey() { - return NetworkSearchActivity.SEARCH_RUNNABLE_KEY; + protected String getStringId() { + return "@Search"; } } diff --git a/src/org/geometerplus/fbreader/formats/oeb/OEBAnnotationReader.java b/src/org/geometerplus/fbreader/formats/oeb/OEBAnnotationReader.java index a3ceb3fa6..219727575 100644 --- a/src/org/geometerplus/fbreader/formats/oeb/OEBAnnotationReader.java +++ b/src/org/geometerplus/fbreader/formats/oeb/OEBAnnotationReader.java @@ -32,7 +32,7 @@ class OEBAnnotationReader extends ZLXMLReaderAdapter implements XMLNamespaces { private static final int READ_DESCRIPTION = 1; private int myReadState; - private final StringBuffer myBuffer = new StringBuffer(); + private final StringBuilder myBuffer = new StringBuilder(); String readAnnotation(ZLFile file) { myReadState = READ_NONE; diff --git a/src/org/geometerplus/fbreader/formats/oeb/OEBMetaInfoReader.java b/src/org/geometerplus/fbreader/formats/oeb/OEBMetaInfoReader.java index 6588e4d99..a3d8d4fa9 100644 --- a/src/org/geometerplus/fbreader/formats/oeb/OEBMetaInfoReader.java +++ b/src/org/geometerplus/fbreader/formats/oeb/OEBMetaInfoReader.java @@ -83,7 +83,7 @@ class OEBMetaInfoReader extends ZLXMLReaderAdapter implements XMLNamespaces { private int myReadState; private boolean myReadMetaData; - private final StringBuffer myBuffer = new StringBuffer(); + private final StringBuilder myBuffer = new StringBuilder(); @Override public boolean processNamespaces() { diff --git a/src/org/geometerplus/fbreader/network/NetworkBookItem.java b/src/org/geometerplus/fbreader/network/NetworkBookItem.java index 5d151b0f6..6e8da3cbb 100644 --- a/src/org/geometerplus/fbreader/network/NetworkBookItem.java +++ b/src/org/geometerplus/fbreader/network/NetworkBookItem.java @@ -59,7 +59,7 @@ public final class NetworkBookItem extends NetworkLibraryItem { return false; } final AuthorData data = (AuthorData) o; - return SortKey == data.SortKey && DisplayName == data.DisplayName; + return SortKey.equals(data.SortKey) && DisplayName.equals(data.DisplayName); } @Override diff --git a/src/org/geometerplus/fbreader/network/NetworkTree.java b/src/org/geometerplus/fbreader/network/NetworkTree.java index b79a30334..2697ed2f2 100644 --- a/src/org/geometerplus/fbreader/network/NetworkTree.java +++ b/src/org/geometerplus/fbreader/network/NetworkTree.java @@ -21,6 +21,7 @@ package org.geometerplus.fbreader.network; import java.util.LinkedList; import java.util.Set; +import java.io.*; import org.geometerplus.zlibrary.core.constants.MimeTypes; import org.geometerplus.zlibrary.core.image.ZLImage; @@ -28,6 +29,71 @@ import org.geometerplus.zlibrary.core.image.ZLImage; import org.geometerplus.fbreader.tree.FBTree; public abstract class NetworkTree extends FBTree { + public static final Key SearchKey = new Key(null, "@Search"); + + public static class Key implements Serializable { + private Key myParent; + private String myId; + + private Key(Key parent, String id) { + if (id == null) { + throw new IllegalArgumentException("NetworkTree string id must be non-null"); + } + myParent = parent; + myId = id; + } + + private Key() { + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if (!(other instanceof NetworkTree.Key)) { + return false; + } + final NetworkTree.Key key = (NetworkTree.Key)other; + return myParent == key.myParent && myId.equals(key.myId); + } + + @Override + public int hashCode() { + return myId.hashCode(); + } + + private void writeObject(ObjectOutputStream os) throws IOException { + if (myParent != null) { + myParent.writeObject(os); + } + os.writeBytes(myId); + os.writeBytes("\000"); + } + + private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException { + myParent = null; + myId = null; + + final StringBuilder builder = new StringBuilder(); + try { + while (true) { + char c = is.readChar(); + if (c != '\000') { + builder.append(c); + } else { + if (myId != null) { + myParent = new Key(myParent, myId); + } + myId = builder.toString(); + builder.delete(0, builder.length()); + } + } + } catch (IOException e) { + } + } + } + protected NetworkTree(int level) { super(level); } @@ -90,11 +156,28 @@ public abstract class NetworkTree extends FBTree { public abstract NetworkLibraryItem getHoldedItem(); + private Key myKey; /** * Returns unique identifier which can be used in NetworkView methods - * @return unique String instance + * @return unique Key instance */ - public abstract String getUniqueKey(); + public final Key getUniqueKey() { + if (myKey == null) { + //final ZLTree parentTree = getParent(); + final Key parentKey = Parent instanceof NetworkTree ? + ((NetworkTree)Parent).getUniqueKey() : null; + myKey = new Key(parentKey, getStringId()); + } + return myKey; + } + + /** + * Returns id used as a part of unique key above. This string must be + * not null + * and + * be unique for all children of same tree + */ + protected abstract String getStringId(); public void removeItems(Set items) { if (items.isEmpty() || subTrees().isEmpty()) { diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSXMLReader.java b/src/org/geometerplus/fbreader/network/opds/OPDSXMLReader.java index 1631f7aef..631266477 100644 --- a/src/org/geometerplus/fbreader/network/opds/OPDSXMLReader.java +++ b/src/org/geometerplus/fbreader/network/opds/OPDSXMLReader.java @@ -172,7 +172,7 @@ class OPDSXMLReader extends ZLXMLReaderAdapter { private int myState = START; - private final StringBuffer myBuffer = new StringBuffer(); + private final StringBuilder myBuffer = new StringBuilder(); private HtmlToString myHtmlToString = new HtmlToString(); private boolean myFeedMetadataProcessed; diff --git a/src/org/geometerplus/fbreader/network/tree/NetworkAuthorTree.java b/src/org/geometerplus/fbreader/network/tree/NetworkAuthorTree.java index 7a395ab54..e16690223 100644 --- a/src/org/geometerplus/fbreader/network/tree/NetworkAuthorTree.java +++ b/src/org/geometerplus/fbreader/network/tree/NetworkAuthorTree.java @@ -125,7 +125,7 @@ public class NetworkAuthorTree extends NetworkTree { } @Override - public String getUniqueKey() { - return "org.geometerplus.fbreader.network.tree.Authors:" + Author.DisplayName; + protected String getStringId() { + return "@Author:" + Author.DisplayName + ":" + Author.SortKey; } } diff --git a/src/org/geometerplus/fbreader/network/tree/NetworkBookTree.java b/src/org/geometerplus/fbreader/network/tree/NetworkBookTree.java index df737635b..c765fcb4c 100644 --- a/src/org/geometerplus/fbreader/network/tree/NetworkBookTree.java +++ b/src/org/geometerplus/fbreader/network/tree/NetworkBookTree.java @@ -74,7 +74,7 @@ public class NetworkBookTree extends NetworkTree { } @Override - public String getUniqueKey() { - return null; + protected String getStringId() { + return "@Book:" + Book.Id + ":" + Book.Title; } } diff --git a/src/org/geometerplus/fbreader/network/tree/NetworkCatalogTree.java b/src/org/geometerplus/fbreader/network/tree/NetworkCatalogTree.java index 5f77d8bf0..265a9a573 100644 --- a/src/org/geometerplus/fbreader/network/tree/NetworkCatalogTree.java +++ b/src/org/geometerplus/fbreader/network/tree/NetworkCatalogTree.java @@ -172,7 +172,7 @@ public class NetworkCatalogTree extends NetworkTree { } @Override - public String getUniqueKey() { + protected String getStringId() { return Item.getFullRequestString(); } } diff --git a/src/org/geometerplus/fbreader/network/tree/NetworkSeriesTree.java b/src/org/geometerplus/fbreader/network/tree/NetworkSeriesTree.java index 5ae3f7984..8c4bb848f 100644 --- a/src/org/geometerplus/fbreader/network/tree/NetworkSeriesTree.java +++ b/src/org/geometerplus/fbreader/network/tree/NetworkSeriesTree.java @@ -100,15 +100,7 @@ public class NetworkSeriesTree extends NetworkTree { } @Override - public String getUniqueKey() { - final StringBuilder buffer = new StringBuilder(); - - final String parentKey = ((NetworkTree)Parent).getUniqueKey(); - if (parentKey != null) { - buffer.append(parentKey).append("///"); - } - buffer.append("org.geometerplus.fbreader.network.tree.Series:").append(SeriesTitle); - - return buffer.toString(); + protected String getStringId() { + return "@Series:" + SeriesTitle; } } diff --git a/src/org/geometerplus/fbreader/network/tree/RootTree.java b/src/org/geometerplus/fbreader/network/tree/RootTree.java index a954f6c32..b7b93506f 100644 --- a/src/org/geometerplus/fbreader/network/tree/RootTree.java +++ b/src/org/geometerplus/fbreader/network/tree/RootTree.java @@ -34,7 +34,7 @@ public final class RootTree extends NetworkTree { } @Override - public String getUniqueKey() { - return null; + protected String getStringId() { + return "@Root"; } }