1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-04 10:19:33 +02:00

Loading catalogs from network

git-svn-id: https://only.mawhrin.net/repos/FBReaderJ/trunk@1674 6a642e6f-84f6-412e-ac94-c4a38d5a04b0
This commit is contained in:
Vasiliy Bout 2010-08-24 14:05:58 +00:00
parent c2bb518019
commit d029660d2e
17 changed files with 183 additions and 957 deletions

View file

@ -14,7 +14,8 @@ NP: оповещение об изменениях в namespace'ах проис
** Загрузка не из xml, а из OPDS-каталога с расширениями
DONE сделать DTD для xml-ей, как в OPDS, вместо существующего
** перенести xml на сервер
DONE перенести xml на сервер
** кэширование каталога
** сделать чтение информации о поиске напрямую из каталога
** Использовать default e-mail при регистрации новых пользователей в AuthenticationDialog (возможно только в Android 2.0+)

View file

@ -1,555 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:dc="http://purl.org/dc/terms/"
xmlns:opds="http://opds-spec.org/2010/catalog"
xmlns:fbreader="http://data.fbreader.org/catalog/metadata/"
>
<id>http://data.fbreader.org/catalogs/generic-1.0.xml</id>
<title>FBReader catalogs list</title>
<updated>2010-07-28T16:34:00Z</updated>
<author>
<name>Geometer Plus</name>
<uri>http://www.fbreader.org</uri>
<email>contact@geometerplus.com</email>
</author>
<link type="application/atom+xml" rel="self" href="http://data.fbreader.org/catalogs/generic-1.0.xml"/>
<entry>
<id>urn:fbreader-org-catalog:feedbooks.com</id>
<updated>2010-07-28T12:00:00Z</updated>
<title>Feedbooks OPDS Catalog</title>
<content>Feedbooks: Food for the mind. A place to discover and publish e-books.</content>
<link type="application/atom+xml" href="http://www.feedbooks.com/catalog.atom"/>
<link rel="search" type="application/atom+xml" href="http://www.feedbooks.com/search.atom?query={searchTerms}" />
<link type="application/atom+xml" rel="http://data.fbreader.org/catalog/sign-in" href="https://www.feedbooks.com/user/profile.atom" />
<link type="text/html" rel="http://data.fbreader.org/catalog/sign-out" href="https://www.feedbooks.com/user/signout" />
<fbreader:advancedSearch style="separateWords" author="author" titleOrSeries="title" tag="type" annotation="description" />
<link type="application/atom+xml" rel="http://data.fbreader.org/condition/never" href="http://www.feedbooks.com/news/catalog.atom" />
<link type="application/atom+xml" rel="http://data.fbreader.org/condition/signed-in" href="https://www.feedbooks.com/user/profile.atom" />
<fbreader:authentication type="basic" />
<fbreader:hasStableIdentifiers/>
<link type="image/png" rel="http://opds-spec.org/thumbnail" href="data:image/png;base64,
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
V3KvaPw/AMARafW5GgkAAAAASUVORK5CYII=" />
</entry>
<entry>
<id>urn:fbreader-org-catalog:litres.ru</id>
<updated>2010-07-28T12:15:00Z</updated>
<title>Каталог LitRes</title>
<content>Продажа электронных книг.</content>
<link type="application/atom+xml" href="http://data.fbreader.org/catalogs/litres/index.php"/>
<link rel="search" type="application/atom+xml" href="http://data.fbreader.org/catalogs/litres/search.php?query={searchTerms}" />
<link type="application/litres+xml" rel="http://data.fbreader.org/catalog/sign-in" href="https://robot.litres.ru/pages/catalit_authorise/?skip_ip=1&amp;lfrom=51" />
<link type="application/litres+xml" rel="http://data.fbreader.org/catalog/sign-up" href="https://robot.litres.ru/pages/catalit_register_user/?lfrom=51" />
<link type="text/html" rel="http://data.fbreader.org/catalog/refill-account" href="https://www.litres.ru/pages/put_money_on_account/?lfrom=51" />
<link type="application/litres+xml" rel="http://data.fbreader.org/catalog/recover-password" href="http://robot.litres.ru/pages/catalit_recover_pass/?lfrom=51" />
<fbreader:advancedSearch style="separateWords" author="author" titleOrSeries="titleOrSeries" tag="tag" annotation="annotation" />
<link type="application/atom+xml" rel="http://data.fbreader.org/condition/signed-in" href="http://data.fbreader.org/catalogs/litres/my.php" />
<fbreader:authentication type="litres" />
<fbreader:urlRewritingRule type="addUrlParameter" apply="external" name="lfrom" value="51" />
<fbreader:hasStableIdentifiers/>
<link type="image/png" rel="http://opds-spec.org/thumbnail" href="data:image/png;base64,
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" />
</entry>
<entry>
<id>urn:fbreader-org-catalog:manybooks.net</id>
<updated>2010-07-28T12:15:00Z</updated>
<title>ManyBooks Catalog</title>
<content>ManyBooks.net: The best ebooks at the best price: free!</content>
<link type="application/atom+xml" href="http://manybooks.net/opds/"/>
<link rel="search" type="application/atom+xml" href="http://manybooks.net/opds/search.php?q={searchTerms}" />
<fbreader:relationAlias alias="http://opds-spec.org/opds-cover-image-thumbnail" name="http://opds-spec.org/thumbnail" />
<link type="image/png" rel="http://opds-spec.org/thumbnail" href="data:image/png;base64,
iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAIAAAD+THXTAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ
bWFnZVJlYWR5ccllPAAAA+pJREFUeNrsmz1sEzEUxx3UrUh0KiNJ56KGCTaCwggFxrAkEjA3c4vU
MABrYC1DJsJGWtYiXTbYgpKZhLFMQSJz+Tvv8s65fJAPx2dHZ52iRnm688/v/57f2W7i8oFYs3ZF
iBgpRoqRYiRLkTavrQsSSLJ5cfRZfOrqvfFGBDAgufNYXmh/u9pvbxDp9iOf5OqWuOiI07L4WpFf
n5ZcQwqRAANX+4f/K/kKLbUnsgVxMyMObtmKRF1Ej68npbq+1SRJqx42207Kzw9taWapl0ZJTmri
+2k4MZDfyEVwXdOTZr2ueOtZg7R9Q5LgosE+r4whgQ0YYLOTll9/NvxwYhHu3vUHBfLDBeOHiQX6
kliqEg/1Ej6hq/cnsEFHySFEC4eQze9fQ/chBg4tuA725pDklFKYRgKD3UyQFaDAljfehhxC9wEG
DMAM41RaihBIZAaD6qvVIGE4X5T9sYRyIBt1vEODzV1UFQhd4VcioXmJaGHG96Ehw4PwCKJFm9lj
cyJBRRg8hEq1FPSA1K8GCTmEg4T0CRuMN5zG8sOnakMGuAndh2ib/YQBvJmRFkoP9wui3ZBOIJ9Q
kFCaZqdhpGlGgg0ZkFdVp8mkkvflRzaU/c76/gmljZVnPAwbDSQYql4QJHj8fnEoPNBF1QAu3T+Q
oRLCqHpD2osyiUu3dPyJn8s2CIYcQiPNlQELj8QJV2vC0IeE/r2s+X+jlx9L/XxV990FBtRvKgZx
AljN8paWrRBPuSA2t3wMymaUBoxgrAAJUfG+EWCo7jLetNZ4kNbSdbRlb7U9Te9ziMM5E7fFyym5
Y/HlUs7mHI1uI8EzOt5wrUFCtXFUc2SFSNYTB3K2nd6KFX/6sn3tAYFBDSXFYSYo28auTzi2jgcP
vPHG+wqSg4t4GnApliZRseTolcSx9DBKxZKDMlFSuSQ8XlVVqfC+xJIDj6Yi0BQSesxxwlSq5ELL
SQ4g9foZT6VCmcvLD5okZzyWoCuVSnWg1vcOs+lhlEqr5CIqiFQq3ZKLrsYjKvhHt+SMFERTqF4/
ceEV0I4WI8VIMdKgXXTkCq5jGW9So83p5ZaULUPSsT6+hrG0YSIw5PZEZ12QniW177VELTzjPHEs
mW+8Re82UmpP7vOG9qTPK64h8SEbdRd00T3pOZFadXFSFLmShvXrsRg6dkHn99LZO/nUYiU4NzJ7
oz1pPpoiVrInvcSxqNxxeDsIPTu893+Mpudfq9nMXe6kF7oLd/HpQELi8047aWMY+pDEYN+B17VR
+IROAEFaZrfWE3r+MyabF8/7R3BaA29M2kpyBommxSjKn1UixS/qMVKMFCPZ3v4JMAC5KATHe24p
XQAAAABJRU5ErkJggg==" />
</entry>
<entry>
<id>urn:fbreader-org-catalog:shucang.com</id>
<updated>2010-07-28T13:40:00Z</updated>
<title>Shucang Catalog</title>
<content>Shucang: a Chinese bookshelf.</content>
<link type="application/atom+xml" href="http://www.shucang.com/s/index.php"/>
<link rel="search" type="application/atom+xml" href="http://www.shucang.com/s/doclist.php?skey={searchTerms}" />
<link type="application/litres+xml" rel="http://data.fbreader.org/catalog/sign-in" href="http://www.shucang.com/s/myshucang.php" />
<link type="text/html" rel="http://data.fbreader.org/catalog/sign-out" href="http://www.shucang.com/logout.php" />
<fbreader:relationAlias alias="x-stanza-cover-image-thumbnail" name="http://opds-spec.org/thumbnail" />
<fbreader:relationAlias alias="x-stanza-cover-image" name="http://opds-spec.org/cover" />
<link type="application/atom+xml" rel="http://data.fbreader.org/condition/signed-in" href="urn:uuid:01182b8b-4719-2369-35e0-107bce646b54" />
<fbreader:authentication type="basic" />
<link type="image/png" rel="http://opds-spec.org/thumbnail" href="data:image/png;base64,
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" />
</entry>
<entry>
<id>urn:fbreader-org-catalog:smashwords.com</id>
<updated>2010-07-28T13:40:00Z</updated>
<title>Smashwords</title>
<content>Ebooks from independent authors and publishers</content>
<link type="application/atom+xml" href="http://www.smashwords.com/atom"/>
<link rel="search" type="application/atom+xml" href="http://www.smashwords.com/atom/search/books/epub/any?query={searchTerms}" />
<fbreader:advancedSearch style="quoted" author="authorFullName" titleOrSeries="title" tag="categories" annotation="description" />
<fbreader:relationAlias alias="x-stanza-cover-image-thumbnail" name="http://opds-spec.org/thumbnail" />
<fbreader:relationAlias alias="x-stanza-cover-image" name="http://opds-spec.org/cover" />
<fbreader:relationAlias alias="bookinfo" name="http://opds-spec.org/acquisition/buy" type="text/html" />
<fbreader:relationAlias alias="" name="http://data.fbreader.org/acquisition/sampleOrFull" type="application/epub+zip" />
<fbreader:urlRewritingRule type="addUrlParameter" apply="external" name="ref" value="geometer" />
<link type="image/png" rel="http://opds-spec.org/thumbnail" href="data:image/png;base64,
iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAL
EwAACxMBAJqcGAAAAAd0SU1FB9gLFAUcBH3DnpQAAAizSURBVFjDzVldbBPZFT73zp3x+Dcex3+Q
xCyQApuyDeW/P1poVRVoQAmiu32oEFKFqqq0TSAPFKlVxUN2KRJqeaOr7q60oKK8tGSbVKVC4oFF
2y40S7qgANU2hIQswY7tzIxnxvNzbx8GjJM4wQ5L1aMr+Xrm+Nzvnr977jFijMH/E+Eq+cpxV78H
RVEopS8EEEIIAO7du+fOn4mJUjowMLBjx45bt27VpiJWNQ0ODvr9/s7OzmqYDcNob28HgNHRUVYL
1QBIVdVIJLJ69erx8fFnMmuatn79+o6ODsdxKKXVr1KDD/n9/hMnTty5c+f8+fOO4yxgNVf0xMTE
1q1bS+b+/E3m7ru1tVWSJFmWF+bM5/OhUGhgYIDVSHgWsoXjSBTFnp6eVatWEUKe6ddtbW0tLS21
Ri4qB4EQ0jTN5/M9Zy5xRc2dz+VhjKXT6VgsVuLB5YF9+fLlnTt3njlzZj4lVZmByhHM50AIoWw2
e+jQoT179kxMTFT2oV27dgEAz/Pnzp1jjNUUHdWTKzaTybgu39XVNW/YDwwMxONxURQB4OzZs6Zp
shdDd+/ebWlpaWxs7O/vdyGWNg+zgD948KC3t3fv3r2EkJMnT74INLIsHzx48MiRI24+m2UHNMvV
XZMXCoXR0VFBEJqbmz/349OyLEVRJEmq6F5oPud1ud23bjiUP1nYkRcXjwsBqshq2/bFixez6UmE
y/M7A0AIIZ4QhBEAMECEEMJx7mue5zHHMcYwwoQQBoAQEI54/YG1a9d6vd5Z65L5YhshJMvK6dO/
tW2b47hwODw0dOO9s38Q482AEEBpG4g6FlCKn6CkjoWAIYQBgDomAoQQMMaYY7s81LE4jvNh++13
321ra3s2IFcxb7zxZv+f379+/bpl28lkMpvNih4+sHTN5p+cc4qFGZUGsBn6YqwMLit9Mva4MGLU
QQj//fT3NFWpoR46+es3P/z47vLVawkhfX19HR17+/70R1847tiWY5vlg9nW0+FYjNqMOk8GfTzY
0zINczxCCBzTW+lImBfQiuUvBVZs/HbH99esWZPNZiUpXDR0m/NiDrtaXBwBACBwLANTq1pArg8t
Wdqg5dNKQVuyJKGqajweV1UFPCH03GGPEHIsQ0COr0pA7j4am5qoJhf0YmNjk23bsVhsOp/n/ZGF
jrPHrxAAKj+U5izAOUWd5zlfTSZramoCS5NVrWFpg67ryWQyl8sLgXpWoWgvZVkAzGn5R4YyBQhj
ImDMoUobtg2V5wWvtwIgMh+gxsYmoLasFJYsaXYcJ5lI3PjnR57gMsacuXrBmHCinyPCnb+c1u9e
0gqFL3y3h/jrBG+IeLyM0hkpDWHLUHmBr6iheQE1NDSAY8tqIRqLFotmLBbL5qfFYIRRZ07+xIY8
+e++s0ZmJGg/+uTGxz8/evTtd34aDXl0ym/48TluJiaEsaVN87zgnuLVmiwej4NjqQU9GAhijOPx
2LSqC74QMDozTQMg9mlfzw+/2fSdTS8JhESjsZdbvphKhMfHx1uaU9S2MMcjhJ/WhAhb+jTP8+Kc
NL0QoPr6esQjTdc5wkmRSKQ+quqWRwwwyma6BaKmKXnZkaO/+NGhnymqqqpqS0tLLJH0iF5C+Nt/
e2v4r79ziupTqyFkFfKiIIgeTw2AJEkK+ERdL1KHSuEwUEcxKCd4ABiU1YMADBHeAj6TTq9bt44Q
ks/nk8lkLpcDANMsbllqvtqgj/3rMiDsahQBMgu5YChACKkBkCiK4VDQtMyCVli+YoWqyIaDuMe1
/QwdYUwsEGQ5Hw6HI5GIoih+v980Tdu2TdN87bXXX/nSK2bRerIBAISK6nQoVFfDVdo96iUpbJtW
NptLJhKyPG2CgDBXSQaiJKDIimvobDZbSmaO46RSqVw2xxG+TDo1tXyoLlwDIFdcIhphjpXJZAFA
UWSHE2G+pEhE3dDdUEin0+6W3DbDsmXLcvkcJ3hKZwBjrKhOh8NSzc2GRDwGzElnpgBAkWVGAgwq
tjIQAOUwdgHJslwsFt0yWRCEeDyezmR5bx1HBI4IHO9BGJuGUheurCGyAKB4Ig7sk6n8NAComg68
15QzdlED5p7h7nluA0J2IesRvQAQCoVUVTVNEyFkGIYoij6f79Hkw4x8sTgx5FgGtU3m2KBmpPpY
bYAQQtFoDKj92cNJABj5z6c2EC37gFoGAsSYwxgghCi1MccjS/eIIgBs2bJFkqRoNHr48GFCSHd3
N8Z4Kq9EX/5WKJYChBDCgPBng/11dXU1aygiSV6feP3WyPJUowKBVa+f8EdTT8Ielcda/h/vhYJB
AGhvb3fLjK6uLozxvn37KKUF3VzWvNVfnwRKMcfLD4YBIJVqqhnQqtVrID8a+HK7RVl9tDF9+4OH
psEYBcdGGGxTZ5Qxx2aOmQpyDY0pAOCelNKliSzL6Yl7uXcOYUKYYwIgM/9w06ZNO3bsrNlkX/nq
135zsmeg//30o4wnfadOCnuCHo7jxsfHP/jwo2+8+vVYMnZj6IauG7986/dhSaqYO65duwaM/urw
D8JSmOMIx3Giz7drV1v5Taaqdkzp/qaq6tTUVD6XKxRUTdMMw8hkMsFgsLu7mzE2MjIyNjY26yfl
8+3bt2/cuHEB+YvvoJULOnXqVDAYHB4erijd/Wqa5oEDBwghg4OD1XcKYNE34m3btm3YsOHmzZuz
LufuhFLa1dVVX19/9erVmvoWsOj2xcTExO7duxOJxIULF+Yuefz48Wg0eunSpVq7KPA8LRXbtjs7
OwkhbuuutPCVK1cA4NixY4uQDM/Z5mGMbd68ef/+/bN6woSQ3t7eRTSZ8PPcZkrdDM/MUmtsbMy2
bUmSFtGEWDwglzRNGxoaSiaT5Q9lWQYAVVVf4H8d89Ht27dFUQwGg+UPVVX1+XzFYnExin/Of4Ns
2x4eHvb5fCtXriw9nJycvH//fmtrqyAI/1NAFdu/1fSEF6D/AmCU/2ALMCZ7AAAAAElFTkSuQmCC" />
</entry>
</feed>

View file

@ -139,6 +139,7 @@
<node name="buyAndDownload" value="Kaufen und runterladen" />
<node name="continue" toBeTranslated="true" value="Continue" />
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
<node name="tryAgain" toBeTranslated="true" value="Try again" />
</node>
<node name="BookInfo">
<node name="fileName" value="Datei Name"/>

View file

@ -138,6 +138,7 @@
<node name="buyAndDownload" value="Buy and download" />
<node name="continue" value="Continue" />
<node name="editUrl" value="Edit URL" />
<node name="tryAgain" value="Try again" />
</node>
<node name="BookInfo">
<node name="fileName" value="File name"/>

View file

@ -139,6 +139,7 @@
<node name="buyAndDownload" value="Acheter et télécharger"/>
<node name="continue" toBeTranslated="true" value="Continue" />
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
<node name="tryAgain" toBeTranslated="true" value="Try again" />
</node>
<node name="BookInfo">
<node name="fileName" value="Nom du fichier"/>

View file

@ -139,6 +139,7 @@
<node name="buyAndDownload" value="Vásárlás és letöltés" />
<node name="continue" toBeTranslated="true" value="Continue" />
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
<node name="tryAgain" toBeTranslated="true" value="Try again" />
</node>
<node name="BookInfo">
<node name="fileName" value="Fájlnév"/>

View file

@ -139,6 +139,7 @@
<node name="buyAndDownload" value="Compra e scarica" />
<node name="continue" toBeTranslated="true" value="Continue" />
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
<node name="tryAgain" toBeTranslated="true" value="Try again" />
</node>
<node name="BookInfo">
<node name="fileName" value="Nome file"/>

View file

@ -138,6 +138,7 @@
<node name="buyAndDownload" value="Купить и скачать" />
<node name="continue" value="Продолжить" />
<node name="editUrl" value="Изменить URL" />
<node name="tryAgain" value="Повторить" />
</node>
<node name="BookInfo">
<node name="fileName" value="Файл"/>

View file

@ -139,6 +139,7 @@
<node name="buyAndDownload" value="Mua và Tải về" />
<node name="continue" toBeTranslated="true" value="Continue" />
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
<node name="tryAgain" toBeTranslated="true" value="Try again" />
</node>
<node name="BookInfo">
<node name="fileName" value="Tên tập tin"/>

View file

@ -139,6 +139,7 @@
<node name="buyAndDownload" value="购买 下载" />
<node name="continue" toBeTranslated="true" value="Continue" />
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
<node name="tryAgain" toBeTranslated="true" value="Try again" />
</node>
<node name="BookInfo">
<node name="fileName" value="文件" />

View file

@ -19,12 +19,15 @@
package org.geometerplus.android.fbreader.network;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.*;
import android.widget.BaseAdapter;
import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.ui.android.R;
import org.geometerplus.zlibrary.ui.android.dialogs.ZLAndroidDialogManager;
@ -35,8 +38,6 @@ import org.geometerplus.fbreader.network.NetworkLibrary;
public class NetworkLibraryActivity extends NetworkBaseActivity {
private boolean myInitialized;
private NetworkTree myTree;
@Override
@ -48,8 +49,7 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
}
private void prepareView() {
if (!myInitialized) {
myInitialized = true;
if (myTree == null) {
myTree = NetworkLibrary.Instance().getTree();
setListAdapter(new LibraryAdapter());
getListView().invalidateViews();
@ -59,28 +59,83 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
@Override
public void onResume() {
super.onResume();
final NetworkView networkView = NetworkView.Instance();
if (!networkView.isInitialized()) {
final Handler handler = new Handler() {
public void handleMessage(Message message) {
prepareView();
}
};
((ZLAndroidDialogManager)ZLAndroidDialogManager.Instance()).wait("loadingNetworkLibrary", new Runnable() {
public void run() {
networkView.initialize();
handler.sendEmptyMessage(0);
}
}, this);
tryResume();
}
private void tryResume() {
if (!NetworkView.Instance().isInitialized()) {
new Initializator().start();
} else {
prepareView();
}
}
private class Initializator extends Handler {
final DialogInterface.OnClickListener myListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
Initializator.this.start();
} else {
NetworkLibraryActivity.this.finish();
}
}
};
private void runInitialization() {
((ZLAndroidDialogManager)ZLAndroidDialogManager.Instance()).wait("loadingNetworkLibrary", new Runnable() {
public void run() {
final String error = NetworkView.Instance().initialize();
Initializator.this.end(error);
}
}, NetworkLibraryActivity.this);
}
private void processResults(String error) {
final ZLResource dialogResource = ZLResource.resource("dialog");
final ZLResource boxResource = dialogResource.getResource("networkError");
final ZLResource buttonResource = dialogResource.getResource("button");
new AlertDialog.Builder(NetworkLibraryActivity.this)
.setTitle(boxResource.getResource("title").getValue())
.setMessage(error)
.setIcon(0)
.setPositiveButton(buttonResource.getResource("tryAgain").getValue(), myListener)
.setNegativeButton(buttonResource.getResource("cancel").getValue(), myListener)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
myListener.onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
}
})
.create().show();
}
@Override
public void handleMessage(Message message) {
if (message.what == 0) {
runInitialization(); // run initialization process
} else if (message.obj == null) {
prepareView(); // initialization is complete successfully
} else {
processResults((String) message.obj); // handle initialization error
}
}
public void start() {
sendEmptyMessage(0);
}
private void end(String error) {
sendMessage(obtainMessage(1, error));
}
}
private final class LibraryAdapter extends BaseAdapter {
public final int getCount() {
if (!NetworkView.Instance().isInitialized()) {
return 0;
}
return myTree.subTrees().size() + 2; // subtrees + <search item>
}

View file

@ -57,10 +57,16 @@ class NetworkView {
return myInitialized;
}
public void initialize() {
public String initialize() {
new SQLiteNetworkDatabase();
NetworkLibrary.Instance().synchronize();
final NetworkLibrary library = NetworkLibrary.Instance();
final String error = library.initialize();
if (error != null) {
return error;
}
library.synchronize();
myActions.add(new NetworkBookActions());
myActions.add(new NetworkCatalogActions());
@ -70,6 +76,7 @@ class NetworkView {
myActions.trimToSize();
myInitialized = true;
return null;
}

View file

@ -20,7 +20,6 @@
package org.geometerplus.android.fbreader.network;
import java.util.HashMap;
import java.util.List;
import android.content.Context;
import android.database.Cursor;
@ -77,7 +76,7 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
}
@Override
protected void loadCustomLinks(List<ICustomNetworkLink> links, ICustomLinksFactory factory) {
protected void loadCustomLinks(ICustomLinksHandler handler) {
final Cursor cursor = myDatabase.rawQuery("SELECT link_id,title,site_name,summary,icon FROM CustomLinks", null);
final HashMap<String,String> linksMap = new HashMap<String,String>();
while (cursor.moveToNext()) {
@ -94,10 +93,7 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
}
linksCursor.close();
final ICustomNetworkLink newLink = factory.createCustomLink(id, siteName, title, summary, icon, linksMap);
if (newLink != null) {
links.add(newLink);
}
handler.handleCustomLinkData(id, siteName, title, summary, icon, linksMap);
}
cursor.close();
}

View file

@ -19,7 +19,6 @@
package org.geometerplus.fbreader.network;
import java.util.List;
import java.util.Map;
public abstract class NetworkDatabase {
@ -35,11 +34,11 @@ public abstract class NetworkDatabase {
protected abstract void executeAsATransaction(Runnable actions);
public interface ICustomLinksFactory {
ICustomNetworkLink createCustomLink(int id, String siteName, String title, String summary, String icon, Map<String, String> links);
public interface ICustomLinksHandler {
void handleCustomLinkData(int id, String siteName, String title, String summary, String icon, Map<String, String> links);
}
protected abstract void loadCustomLinks(List<ICustomNetworkLink> links, ICustomLinksFactory factory);
protected abstract void loadCustomLinks(ICustomLinksHandler handler);
protected abstract void saveCustomLink(ICustomNetworkLink link);
protected abstract void deleteCustomLink(ICustomNetworkLink link);
}

View file

@ -21,7 +21,6 @@ package org.geometerplus.fbreader.network;
import java.util.*;
import org.geometerplus.zlibrary.core.filesystem.*;
import org.geometerplus.zlibrary.core.util.ZLNetworkUtil;
import org.geometerplus.zlibrary.core.options.ZLStringOption;
import org.geometerplus.zlibrary.core.network.ZLNetworkRequest;
@ -30,7 +29,7 @@ import org.geometerplus.zlibrary.core.network.ZLNetworkManager;
import org.geometerplus.fbreader.tree.FBTree;
import org.geometerplus.fbreader.network.tree.*;
import org.geometerplus.fbreader.network.opds.OPDSLinkReader;
import org.geometerplus.fbreader.network.opds.OPDSLinkXMLReader;
public class NetworkLibrary {
private static NetworkLibrary ourInstance;
@ -206,6 +205,11 @@ public class NetworkLibrary {
}
}
public interface OnNewLinkListener {
void onNewLink(INetworkLink link);
}
public final ZLStringOption NetworkSearchPatternOption = new ZLStringOption("NetworkSearch", "Pattern", "");
@ -219,50 +223,48 @@ public class NetworkLibrary {
private boolean myUpdateVisibility;
private NetworkLibrary() {
final OPDSLinkXMLReader reader = new OPDSLinkXMLReader(myLoadedLinks);
reader.read(ZLResourceFile.createResourceFile("data/network/catalogs.xml"));
ArrayList<ArrayList<? extends INetworkLink>> linksList = new ArrayList<ArrayList<? extends INetworkLink>>();
linksList.add(myLoadedLinks);
linksList.add(myCustomLinks);
myLinks = new CompositeList(linksList, new LinksComparator());
}
NetworkDatabase.Instance().loadCustomLinks(myCustomLinks,
new NetworkDatabase.ICustomLinksFactory() {
public ICustomNetworkLink createCustomLink(int id, String siteName,
public String initialize() {
final LinksComparator comparator = new LinksComparator();
final String url = "http://data.fbreader.org/catalogs/generic-1.0.xml";
final String error = ZLNetworkManager.Instance().perform(
OPDSLinkReader.loadOPDSLinksRequest(url, new OnNewLinkListener() {
public void onNewLink(INetworkLink link) {
addLinkInternal(myLoadedLinks, link, comparator);
}
})
);
if (error != null) {
synchronized (myLinks) {
myLoadedLinks.clear();
}
return error;
}
NetworkDatabase.Instance().loadCustomLinks(
new NetworkDatabase.ICustomLinksHandler() {
public void handleCustomLinkData(int id, String siteName,
String title, String summary, String icon, Map<String, String> links) {
final ICustomNetworkLink link = OPDSLinkReader.createCustomLink(id, siteName, title, summary, icon, links);
link.setSaveLinkListener(myChangesListener);
return link;
if (link != null) {
addLinkInternal(myCustomLinks, link, comparator);
link.setSaveLinkListener(myChangesListener);
}
}
}
);
LinksComparator comparator = new LinksComparator();
Collections.sort(myLoadedLinks, comparator);
Collections.sort(myCustomLinks, comparator);
ArrayList<ArrayList<? extends INetworkLink>> linksList = new ArrayList<ArrayList<? extends INetworkLink>>();
linksList.add(myLoadedLinks);
linksList.add(myCustomLinks);
myLinks = new CompositeList(linksList, comparator);
return null;
}
/*private final LinkedList<String> readCatalogFileNames() {
final LinkedList<String> catalogs = new LinkedList<String>();
final ZLResourceFile catalogsFile = ZLResourceFile.createResourceFile("data/network/catalogs.txt");
try {
InputStream stream = catalogsFile.getInputStream();
if (stream != null) {
Scanner scanner = new Scanner(stream);
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (line.length() > 0) {
catalogs.add(line);
}
}
scanner.close();
}
} catch (IOException ex) {
}
return catalogs;
}*/
public String rewriteUrl(String url, boolean externalUrl) {
final String host = ZLNetworkUtil.hostFromUrl(url).toLowerCase();
synchronized (myLinks) {
@ -377,7 +379,6 @@ public class NetworkLibrary {
}
public NetworkTree getTree() {
synchronize();
return myRootTree;
}
@ -441,48 +442,52 @@ public class NetworkLibrary {
}
};
public void addCustomLink(ICustomNetworkLink link) {
final int index = Collections.binarySearch(myCustomLinks, link, new LinksComparator());
if (index >= 0) {
throw new RuntimeException("Unable to add link with duplicated title to the library");
private <T extends INetworkLink> void addLinkInternal(ArrayList<T> list, T link, LinksComparator comparator) {
synchronized (myLinks) {
final int index = Collections.binarySearch(list, link, comparator);
if (index >= 0) {
throw new RuntimeException("Unable to add link with duplicated title to the library");
}
final int insertAt = -index - 1;
list.add(insertAt, link);
}
final int insertAt = -index - 1;
myCustomLinks.add(insertAt, link);
}
public void addCustomLink(ICustomNetworkLink link) {
addLinkInternal(myCustomLinks, link, new LinksComparator());
link.setSaveLinkListener(myChangesListener);
link.saveLink();
}
/*public int getCustomLinksNumber() {
return myCustomLinks.size();
}
public ICustomNetworkLink getCustomLink(int index) {
return myCustomLinks.get(index);
}*/
public void removeCustomLink(ICustomNetworkLink link) {
final int index = Collections.binarySearch(myCustomLinks, link, new LinksComparator());
if (index < 0) {
return;
synchronized (myLinks) {
final int index = Collections.binarySearch(myCustomLinks, link, new LinksComparator());
if (index < 0) {
return;
}
myCustomLinks.remove(index);
}
myCustomLinks.remove(index);
NetworkDatabase.Instance().deleteCustomLink(link);
link.setSaveLinkListener(null);
}
public boolean hasCustomLinkTitle(String title, ICustomNetworkLink exeptFor) {
for (INetworkLink link: myLinks) {
if (link != exeptFor && link.getTitle().equals(title)) {
return true;
synchronized (myLinks) {
for (INetworkLink link: myLinks) {
if (link != exeptFor && link.getTitle().equals(title)) {
return true;
}
}
}
return false;
}
public boolean hasCustomLinkSite(String siteName, ICustomNetworkLink exeptFor) {
for (INetworkLink link: myLinks) {
if (link != exeptFor && link.getSiteName().equals(siteName)) {
return true;
synchronized (myLinks) {
for (INetworkLink link: myLinks) {
if (link != exeptFor && link.getSiteName().equals(siteName)) {
return true;
}
}
}
return false;

View file

@ -19,87 +19,23 @@
package org.geometerplus.fbreader.network.opds;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import java.util.*;
//import org.geometerplus.zlibrary.core.xml.*;
//import org.geometerplus.zlibrary.core.filesystem.ZLFile;
//import org.geometerplus.zlibrary.core.filesystem.ZLResourceFile;
import org.geometerplus.zlibrary.core.network.ZLNetworkRequest;
import org.geometerplus.fbreader.network.*;
//import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
//import org.geometerplus.fbreader.network.authentication.litres.LitResAuthenticationManager;
public class OPDSLinkReader /*extends ZLXMLReaderAdapter*/ {
/*private String mySiteName;
private String myTitle;
private String mySummary;
private String myIcon;
private boolean myHasStableIdentifiers;
private final HashMap<String, String> myLinks = new HashMap<String, String>();
private HashMap<RelationAlias, String> myRelationAliases = new HashMap<RelationAlias, String>();
//private String mySearchType;
private final HashMap<String, String> mySearchFields = new HashMap<String, String>();
private final HashMap<String, Integer> myUrlConditions = new HashMap<String, Integer>();
private String myAuthenticationType;
private final LinkedList<URLRewritingRule> myUrlRewritingRules = new LinkedList<URLRewritingRule>();
private String mySSLCertificate;
private INetworkLink link() {
if (mySiteName == null || myTitle == null || myLinks.get(INetworkLink.URL_MAIN) == null) {
return null;
}
OPDSLink opdsLink = new OPDSLink(
mySiteName,
myTitle,
mySummary,
myIcon,
myLinks,
myHasStableIdentifiers
);
// if (!mySearchType.empty()) {
// opdsLink.setupAdvancedSearch(
// mySearchType,
// mySearchFields["titleOrSeries"],
// mySearchFields["author"],
// mySearchFields["tag"],
// mySearchFields["annotation"]
// );
// }
opdsLink.setRelationAliases(myRelationAliases);
opdsLink.setUrlConditions(myUrlConditions);
opdsLink.setUrlRewritingRules(myUrlRewritingRules);
NetworkAuthenticationManager authManager = null;
if (myAuthenticationType == "basic") {
//authManager = new BasicAuthenticationManager(opdsLink, mySSLCertificate);
} else if (myAuthenticationType == "litres") {
authManager = new LitResAuthenticationManager(opdsLink, mySSLCertificate);
}
opdsLink.setAuthenticationManager(authManager);
return opdsLink;
}*/
public class OPDSLinkReader {
public static ICustomNetworkLink createCustomLink(int id, String siteName, String title, String summary, String icon, Map<String, String> links) {
if (siteName == null || title == null || links.get(INetworkLink.URL_MAIN) == null) {
return null;
}
OPDSCustomLink link = new OPDSCustomLink(id, siteName, title, summary, icon, links);
// TODO: read common OPDSLink attributes from special custom.xml file
// Does this additional info have to override duplicated settings, received from user???
return link;
return new OPDSCustomLink(id, siteName, title, summary, icon, links);
}
public static ICustomNetworkLink createCustomLinkWithoutInfo(String siteName, String url) {
@ -108,233 +44,13 @@ public class OPDSLinkReader /*extends ZLXMLReaderAdapter*/ {
return new OPDSCustomLink(ICustomNetworkLink.INVALID_ID, siteName, null, null, null, links);
}
/*public INetworkLink readDocument(ZLFile file) {
mySiteName = myTitle = mySummary = myIcon = myAuthenticationType = mySSLCertificate = null;
//mySearchType = null;
myHasStableIdentifiers = false;
myLinks.clear();
mySearchFields.clear();
myUrlConditions.clear();
myUrlRewritingRules.clear();
myRelationAliases.clear();
String path = file.getPath();
if (path.endsWith(".xml")) {
path = path.substring(0, path.length() - 4) + ".crt";
if (ZLResourceFile.createResourceFile(path).exists()) {
mySSLCertificate = path;
public static ZLNetworkRequest loadOPDSLinksRequest(String url, final NetworkLibrary.OnNewLinkListener listener) {
return new ZLNetworkRequest(url) {
@Override
public String handleStream(URLConnection connection, InputStream inputStream) throws IOException {
new OPDSLinkXMLReader(listener).read(inputStream);
return null;
}
}
myState = READ_NOTHING;
if (!ZLXMLProcessor.read(this, file)) {
return null;
}
return link();
};
}
private static final String TAG_CATALOG = "catalog";
private static final String TAG_SITE = "site";
private static final String TAG_LINK = "link";
private static final String TAG_TITLE = "title";
private static final String TAG_SUMMARY = "summary";
private static final String TAG_ICON = "icon";
private static final String TAG_RELATION_ALIASES = "relationAliases";
private static final String TAG_ALIAS = "alias";
private static final String TAG_SEARCH_DESCRIPTION = "advancedSearch";
private static final String TAG_FEEDS = "feeds";
private static final String TAG_AUTHENTICATION = "authentication";
private static final String TAG_URL_REWRITING_RULES = "urlRewritingRules";
private static final String TAG_FIELD = "field";
private static final String TAG_CONDITION = "condition";
private static final String TAG_RULE = "rule";
private static final int READ_NOTHING = 0;
private static final int READ_SITENAME = 1;
private static final int READ_TITLE = 2;
private static final int READ_SUMMARY = 3;
private static final int READ_ICON_NAME = 4;
private static final int READ_LINK = 5;
private static final int READ_SEARCH_DESCRIPTION = 6;
private static final int READ_SEARCH_FIELD = 7;
private static final int READ_FEEDS = 8;
private static final int READ_FEEDS_CONDITION = 9;
private static final int READ_URL_REWRITING_RULES = 10;
private static final int READ_RELATION_ALIASES = 11;
private int myState;
private String myAttrBuffer;
private final StringBuffer myBuffer = new StringBuffer();
@Override
public boolean startElementHandler(String tag, ZLStringMap attributes) {
tag = tag.intern();
if (TAG_CATALOG == tag) {
final String value = attributes.getValue("hasStableIdentifiers");
myHasStableIdentifiers = value != null && value.equals("true");
} else if (TAG_SITE == tag) {
myState = READ_SITENAME;
} else if (TAG_TITLE == tag) {
myState = READ_TITLE;
} else if (TAG_SUMMARY == tag) {
myState = READ_SUMMARY;
} else if (TAG_ICON == tag) {
myState = READ_ICON_NAME;
} else if (TAG_LINK == tag) {
String linkType = attributes.getValue("rel");
if (linkType != null) {
myAttrBuffer = linkType;
myLinks.remove(myAttrBuffer);
myState = READ_LINK;
}
} else if (TAG_SEARCH_DESCRIPTION == tag) {
String searchType = attributes.getValue("style");
if (searchType != null) {
//mySearchType = searchType;
myState = READ_SEARCH_DESCRIPTION;
}
} else if (myState == READ_SEARCH_DESCRIPTION && TAG_FIELD == tag) {
String name = attributes.getValue("name");
if (name != null) {
myAttrBuffer = name;
mySearchFields.remove(myAttrBuffer);
myState = READ_SEARCH_FIELD;
}
} else if (TAG_FEEDS == tag) {
myState = READ_FEEDS;
} else if (myState == READ_FEEDS && TAG_CONDITION == tag) {
String show = attributes.getValue("show");
if (show != null) {
myAttrBuffer = show;
myState = READ_FEEDS_CONDITION;
}
} else if (TAG_AUTHENTICATION == tag) {
String authenticationType = attributes.getValue("type");
if (authenticationType != null) {
myAuthenticationType = authenticationType;
}
} else if (TAG_URL_REWRITING_RULES == tag) {
myState = READ_URL_REWRITING_RULES;
} else if (myState == READ_URL_REWRITING_RULES && TAG_RULE == tag) {
String type = attributes.getValue("type");
String apply = attributes.getValue("apply");
String name = attributes.getValue("name");
String value = attributes.getValue("value");
int ruleApply = URLRewritingRule.APPLY_ALWAYS;
if (apply != null) {
apply = apply.intern();
if (apply == "external") {
ruleApply = URLRewritingRule.APPLY_EXTERNAL;
} else if (apply == "internal") {
ruleApply = URLRewritingRule.APPLY_INTERNAL;
} else if (apply != "always") {
type = null;
}
}
if (type != null && name != null && value != null) {
if (type == "addUrlParameter") {
myUrlRewritingRules.add(new URLRewritingRule(URLRewritingRule.ADD_URL_PARAMETER, ruleApply, name, value));
}
}
} else if (TAG_RELATION_ALIASES == tag) {
myState = READ_RELATION_ALIASES;
} else if (myState == READ_RELATION_ALIASES && TAG_ALIAS == tag) {
String alias = attributes.getValue("alias");
String name = attributes.getValue("name");
String type = attributes.getValue("type");
if (alias != null && name != null) {
if (alias.length() == 0) {
alias = null;
}
myRelationAliases.put(new RelationAlias(alias, type), name);
}
}
return false;
}
@Override
public boolean endElementHandler(String tag) {
tag = tag.intern();
String bufferContent = myBuffer.toString().trim();
myBuffer.delete(0, myBuffer.length());
if (bufferContent.length() != 0) {
switch (myState) {
case READ_NOTHING:
case READ_SEARCH_DESCRIPTION:
case READ_FEEDS:
case READ_URL_REWRITING_RULES:
case READ_RELATION_ALIASES:
break;
case READ_SITENAME:
mySiteName = bufferContent;
break;
case READ_TITLE:
myTitle = bufferContent;
break;
case READ_SUMMARY:
mySummary = bufferContent;
break;
case READ_ICON_NAME:
myIcon = bufferContent;
break;
case READ_LINK:
myLinks.put(myAttrBuffer, bufferContent);
break;
case READ_SEARCH_FIELD:
mySearchFields.put(myAttrBuffer, bufferContent);
break;
case READ_FEEDS_CONDITION:
myUrlConditions.put(
bufferContent,
myAttrBuffer.equals("signedIn") ?
OPDSLink.FeedCondition.SIGNED_IN :
OPDSLink.FeedCondition.NEVER
);
break;
}
}
if (myState == READ_SEARCH_FIELD) {
myState = READ_SEARCH_DESCRIPTION;
} else if (myState == READ_FEEDS_CONDITION) {
myState = READ_FEEDS;
} else if (myState == READ_URL_REWRITING_RULES && TAG_RULE == tag) {
//myState = myState;
} else if (myState == READ_RELATION_ALIASES && TAG_ALIAS == tag) {
//myState = myState;
} else {
myState = READ_NOTHING;
}
return false;
}
@Override
public void characterDataHandler(char[] data, int start, int length) {
switch (myState) {
case READ_NOTHING:
case READ_SEARCH_DESCRIPTION:
case READ_FEEDS:
case READ_URL_REWRITING_RULES:
case READ_RELATION_ALIASES:
break;
case READ_SITENAME:
case READ_TITLE:
case READ_SUMMARY:
case READ_ICON_NAME:
case READ_LINK:
case READ_SEARCH_FIELD:
case READ_FEEDS_CONDITION:
myBuffer.append(data, start, length);
break;
}
}*/
}

View file

@ -21,7 +21,6 @@ package org.geometerplus.fbreader.network.opds;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.geometerplus.zlibrary.core.filesystem.ZLResourceFile;
@ -30,6 +29,7 @@ import org.geometerplus.zlibrary.core.xml.ZLStringMap;
import org.geometerplus.fbreader.constants.XMLNamespace;
import org.geometerplus.fbreader.network.INetworkLink;
import org.geometerplus.fbreader.network.NetworkImage;
import org.geometerplus.fbreader.network.NetworkLibrary;
import org.geometerplus.fbreader.network.atom.ATOMLink;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
import org.geometerplus.fbreader.network.authentication.litres.LitResAuthenticationManager;
@ -38,15 +38,15 @@ public class OPDSLinkXMLReader extends OPDSXMLReader {
private static class LinkReader implements OPDSFeedReader {
private List<INetworkLink> myLinksBuffer;
private NetworkLibrary.OnNewLinkListener myListener;
private String myAuthenticationType;
private boolean myHasStableIdentifiers;
private final LinkedList<URLRewritingRule> myUrlRewritingRules = new LinkedList<URLRewritingRule>();
private HashMap<RelationAlias, String> myRelationAliases = new HashMap<RelationAlias, String>();
public LinkReader(List<INetworkLink> links) {
myLinksBuffer = links;
public LinkReader(NetworkLibrary.OnNewLinkListener listener) {
myListener = listener;
}
public void setAuthenticationType(String type) {
@ -141,7 +141,7 @@ public class OPDSLinkXMLReader extends OPDSXMLReader {
INetworkLink result = link(siteName, title, summary, icon, links, urlConditions, sslCertificate);
if (result != null) {
myLinksBuffer.add(result);
myListener.onNewLink(result);
}
return false;
}
@ -190,8 +190,8 @@ public class OPDSLinkXMLReader extends OPDSXMLReader {
public void processFeedEnd() {}
}
public OPDSLinkXMLReader(List<INetworkLink> links) {
super(new LinkReader(links));
public OPDSLinkXMLReader(NetworkLibrary.OnNewLinkListener listener) {
super(new LinkReader(listener));
}
private String myFBReaderNamespaceId;
@ -275,10 +275,4 @@ public class OPDSLinkXMLReader extends OPDSXMLReader {
}
return super.startElementHandler(tagPrefix, tag, attributes, bufferContent);
}
@Override
public boolean endElementHandler(final String tagPrefix, final String tag,
final String bufferContent) {
return super.endElementHandler(tagPrefix, tag, bufferContent);
}
}