From f56603710a640fdd07caef628f85444e78414376 Mon Sep 17 00:00:00 2001 From: naofumi Date: Fri, 3 Oct 2014 00:53:17 +0900 Subject: [PATCH] Added shinjuku library --- WorldOpac/AndroidManifest.xml | 6 +- WorldOpac/assets/bibs/Japan_Hachioji.json | 2 +- WorldOpac/assets/bibs/Japan_Shinjukuku.json | 19 + WorldOpac/res/values-ja/strings.xml | 6 +- .../src/de/geeksfactory/opacclient/OpacClient.java | 5 +- .../de/geeksfactory/opacclient/apis/BaseApi.java | 4 +- .../geeksfactory/opacclient/apis/JapanLicsre.java | 1045 ++++++++++++++++++++ .../opacclient/frontend/MainActivity.java | 10 +- .../frontend/SearchResultDetailActivity.java | 11 +- .../frontend/SearchResultListActivity.java | 12 +- 10 files changed, 1107 insertions(+), 13 deletions(-) create mode 100644 WorldOpac/assets/bibs/Japan_Shinjukuku.json create mode 100644 WorldOpac/src/de/geeksfactory/opacclient/apis/JapanLicsre.java diff --git a/WorldOpac/AndroidManifest.xml b/WorldOpac/AndroidManifest.xml index 2b54bea..e6a7bec 100644 --- a/WorldOpac/AndroidManifest.xml +++ b/WorldOpac/AndroidManifest.xml @@ -1,11 +1,11 @@ + android:versionCode="2" + android:versionName="0.2"> diff --git a/WorldOpac/assets/bibs/Japan_Hachioji.json b/WorldOpac/assets/bibs/Japan_Hachioji.json index 4c7503d..7d8de56 100644 --- a/WorldOpac/assets/bibs/Japan_Hachioji.json +++ b/WorldOpac/assets/bibs/Japan_Hachioji.json @@ -13,5 +13,5 @@ ], "state": "東京都", "support": "目録検索", - "title": "八王子市立図書館" + "title": "八王子市図書館" } diff --git a/WorldOpac/assets/bibs/Japan_Shinjukuku.json b/WorldOpac/assets/bibs/Japan_Shinjukuku.json new file mode 100644 index 0000000..c2342e9 --- /dev/null +++ b/WorldOpac/assets/bibs/Japan_Shinjukuku.json @@ -0,0 +1,19 @@ +{ + "api": "japanlicsre", + "city": "新宿区", + "country": "日本", + "data": { + "accountSupported": true, + "charset": "euc-jp", + "db": "1", + "baseurl": "https://www.library.shinjuku.tokyo.jp/opac/cgi-bin", + "information": "http://www.city.shinjuku.lg.jp/library/index04.html" + }, + "geo": [ + 35.7052389, + 139.7071623 + ], + "state": "東京都", + "support": "目録検索およびアカウント", + "title": "新宿区立図書館" +} diff --git a/WorldOpac/res/values-ja/strings.xml b/WorldOpac/res/values-ja/strings.xml index 9e26765..acf44e6 100644 --- a/WorldOpac/res/values-ja/strings.xml +++ b/WorldOpac/res/values-ja/strings.xml @@ -151,7 +151,7 @@ 詳細がロードされるまでしばらくお待ちください この図書館ではサポートされていません この機能はサポートされていません - この機能は、この図書館でサポートされていません. これに対応するには, この図書館の読者の助けが必要です. あなたが手助けをしたい場合は info@opacapp.de にサインアップしてください + この機能は、この図書館でサポートされていません. これに対応するには, この図書館の読者の助けが必要です. あなたが支援したい場合は aosj@users.sourceforeg.jp にメールしてください この機能は、この図書館でサポートされていません. これに対応するには, この図書館の読者の助けを必要とします: あなたがボタン「レポートを送信」を押すと, 私たちは次のアップデートでそれに対応することができるようになります. 次にあなたのカード番号であなたが本を借りて, その情報を評価させてください (パスワードや、名前などの個人情報は必要ありませn!) 責任を持ってデータは削除します. 情報 メールを作成 @@ -190,9 +190,9 @@ 次へ 前へ エラーが発生しました. しばらくお待ちください. - Web Opac アプリ: エラーが発生しました. + World Opac アプリ: エラーが発生しました. エラーレポートを送信するにはこちらをクリックしてください. - Web Opac アプリがクラッシュしました + World Opac アプリがクラッシュしました Opac アプリでエラーが発生しました! 私たちがそれを修正することができるように, メールでバグレポートを送ってください. 更新 すべて延長 diff --git a/WorldOpac/src/de/geeksfactory/opacclient/OpacClient.java b/WorldOpac/src/de/geeksfactory/opacclient/OpacClient.java index 00a96ce..157639b 100644 --- a/WorldOpac/src/de/geeksfactory/opacclient/OpacClient.java +++ b/WorldOpac/src/de/geeksfactory/opacclient/OpacClient.java @@ -59,6 +59,7 @@ import de.geeksfactory.opacclient.apis.Bibliotheca; import de.geeksfactory.opacclient.apis.IOpac; import de.geeksfactory.opacclient.apis.JapanElcielo; import de.geeksfactory.opacclient.apis.JapanClis; +import de.geeksfactory.opacclient.apis.JapanLicsre; import de.geeksfactory.opacclient.apis.OpacApi; import de.geeksfactory.opacclient.apis.OpenLibrary; import de.geeksfactory.opacclient.apis.Pica; @@ -77,7 +78,7 @@ import de.geeksfactory.opacclient.storage.AccountDataSource; import de.geeksfactory.opacclient.storage.SQLMetaDataSource; import de.geeksfactory.opacclient.storage.StarContentProvider; -@ReportsCrashes(formKey = "", mailTo = "aosj@sourceforge.jp", mode = org.acra.ReportingInteractionMode.NOTIFICATION) +@ReportsCrashes(formKey = "", mailTo = "aosj@users.sourceforge.jp", mode = org.acra.ReportingInteractionMode.NOTIFICATION) public class OpacClient extends Application { public Exception last_exception; @@ -168,6 +169,8 @@ public class OpacClient extends Application { newApiInstance = new JapanElcielo(); else if (lib.getApi().equals("japanclis")) newApiInstance = new JapanClis(); + else if (lib.getApi().equals("japanlicsre")) + newApiInstance = new JapanLicsre(); else if (lib.getApi().equals("openlibrary")) newApiInstance = new OpenLibrary(); else diff --git a/WorldOpac/src/de/geeksfactory/opacclient/apis/BaseApi.java b/WorldOpac/src/de/geeksfactory/opacclient/apis/BaseApi.java index 31c56b6..6c45d1a 100644 --- a/WorldOpac/src/de/geeksfactory/opacclient/apis/BaseApi.java +++ b/WorldOpac/src/de/geeksfactory/opacclient/apis/BaseApi.java @@ -98,7 +98,9 @@ public abstract class BaseApi implements OpacApi { CookieStore cookieStore) throws ClientProtocolException, IOException { - HttpGet httpget = new HttpGet(cleanUrl(url)); +// HttpGet httpget = new HttpGet(cleanUrl(url)); + HttpGet httpget = new HttpGet(url); + httpget.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.0; rv:32.0) Gecko/20100101 Firefox/32.0"); HttpResponse response; try { diff --git a/WorldOpac/src/de/geeksfactory/opacclient/apis/JapanLicsre.java b/WorldOpac/src/de/geeksfactory/opacclient/apis/JapanLicsre.java new file mode 100644 index 0000000..f78c8fb --- /dev/null +++ b/WorldOpac/src/de/geeksfactory/opacclient/apis/JapanLicsre.java @@ -0,0 +1,1045 @@ +/* + * Copyright (C) 2014 Naofumi Fukue + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.geeksfactory.opacclient.apis; + +import java.io.IOException; +import java.net.URI; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.apache.http.NameValuePair; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.CookieStore; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.message.BasicNameValuePair; +import org.json.JSONException; +import org.json.JSONObject; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import de.geeksfactory.opacclient.ISBNTools; +import de.geeksfactory.opacclient.NotReachableException; +import de.geeksfactory.opacclient.objects.Account; +import de.geeksfactory.opacclient.objects.AccountData; +import de.geeksfactory.opacclient.objects.Detail; +import de.geeksfactory.opacclient.objects.DetailledItem; +import de.geeksfactory.opacclient.objects.Filter; +import de.geeksfactory.opacclient.objects.Filter.Option; +import de.geeksfactory.opacclient.objects.Library; +import de.geeksfactory.opacclient.objects.SearchRequestResult; +import de.geeksfactory.opacclient.objects.SearchResult; +import de.geeksfactory.opacclient.objects.SearchResult.MediaType; +import de.geeksfactory.opacclient.objects.SearchResult.Status; +import de.geeksfactory.opacclient.storage.MetaDataSource; + +public class JapanLicsre extends BaseApi implements OpacApi { + + protected String opac_url = ""; + protected String https_url = ""; + protected JSONObject data; + protected MetaDataSource metadata; + protected boolean initialised = false; + protected Library library; + protected int resultcount = 10; + protected String reusehtml; + protected Integer searchSet; + protected String db; + protected String unEncoded; + protected String pwEncoded; + CookieStore cookieStore = new BasicCookieStore(); + + protected List sellist_params; + + protected Document res_doc; + protected String contact; + // protected String num; + // protected String ctg; + protected String dtype; + protected String type; + protected String sid; + // protected String tm; + // protected String aut; + + protected String lor_reservations; + + protected static HashMap defaulttypes = new HashMap(); + + static { + defaulttypes.put("一般", MediaType.BOOK); + defaulttypes.put("新書", MediaType.BOOK); + defaulttypes.put("本", MediaType.BOOK); + defaulttypes.put("図書", MediaType.BOOK); + defaulttypes.put("図書資料", MediaType.BOOK); + defaulttypes.put("図書その他", MediaType.BOOK); + defaulttypes.put("文庫", MediaType.BOOK); + defaulttypes.put("文庫本", MediaType.BOOK); + defaulttypes.put("旅行案内", MediaType.BOOK); + defaulttypes.put("参考資料", MediaType.BOOK); + defaulttypes.put("例規集", MediaType.BOOK); + defaulttypes.put("和綴資料", MediaType.BOOK); + defaulttypes.put("大活字", MediaType.BOOK); + defaulttypes.put("大活字本", MediaType.BOOK); + defaulttypes.put("拡大写本", MediaType.BOOK); + defaulttypes.put("外国語", MediaType.BOOK); + defaulttypes.put("まんが", MediaType.BOOK); + defaulttypes.put("点字資料", MediaType.BOOK); + defaulttypes.put("点字付資料", MediaType.BOOK); + defaulttypes.put("新聞", MediaType.NEWSPAPER); + defaulttypes.put("新聞縮刷版", MediaType.NEWSPAPER); + defaulttypes.put("雑誌", MediaType.MAGAZINE); + defaulttypes.put("雑誌(点字)", MediaType.MAGAZINE); + defaulttypes.put("絵本", MediaType.ART); + defaulttypes.put("特大絵本", MediaType.ART); + defaulttypes.put("しかけ絵本", MediaType.ART); + defaulttypes.put("布の絵本", MediaType.ART); + defaulttypes.put("紙芝居", MediaType.ART); + defaulttypes.put("ポスター", MediaType.ART); + defaulttypes.put("絵画", MediaType.ART); + defaulttypes.put("写真", MediaType.ART); + defaulttypes.put("パンフレット", MediaType.ART); + defaulttypes.put("図譜・図案等", MediaType.ART); + defaulttypes.put("地図", MediaType.MAP); + defaulttypes.put("地図(1枚もの)", MediaType.MAP); + defaulttypes.put("楽譜", MediaType.SCORE_MUSIC); + defaulttypes.put("CD-ROM", MediaType.CD_SOFTWARE); + defaulttypes.put("マイクロフィルム", MediaType.UNKNOWN); + defaulttypes.put("区分なし", MediaType.UNKNOWN); + defaulttypes.put("その他作成物", MediaType.UNKNOWN); + defaulttypes.put("CD", MediaType.CD); + defaulttypes.put("朗読CD", MediaType.CD); + defaulttypes.put("コンパクトディスク", MediaType.CD); + defaulttypes.put("DVD", MediaType.DVD); + defaulttypes.put("映像", MediaType.MOVIE); + defaulttypes.put("ビデオテープ", MediaType.MOVIE); + defaulttypes.put("ビデオテープ(VHS)", MediaType.MOVIE); + defaulttypes.put("カセットテープ", MediaType.AUDIO_CASSETTE); + defaulttypes.put("カセット", MediaType.AUDIO_CASSETTE); + defaulttypes.put("音響", MediaType.CD); + } + + @Override + public void start() throws IOException, NotReachableException { + // String html = httpGet(opac_url + // + "/DB=" + db + "/SET=1/TTL=1/ADVANCED_SEARCHFILTER", + // getDefaultEncoding(), false, cookieStore); + + // Document doc = Jsoup.parse(html); + + // updateSearchSetValue(doc); + + try { + metadata.open(); + } catch (Exception e) { + throw new RuntimeException(e); + } + if (!metadata.hasMeta(library.getIdent())) { + metadata.close(); + // extract_meta(doc); + } else { + metadata.close(); + } + } + + @Override + public void init(MetaDataSource metadata, Library lib) { + super.init(metadata, lib); + + this.metadata = metadata; + this.library = lib; + this.data = lib.getData(); + + try { + this.opac_url = data.getString("baseurl"); + this.db = data.getString("db"); + if (!library.getData().isNull("accountSupported")) { + if (data.has("httpsbaseurl")) { + this.https_url = data.getString("httpsbaseurl"); + } else { + this.https_url = this.opac_url; + } + } + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + + protected int addParameters(Map query, String key, + String searchkey, List params, int index) { + if (!query.containsKey(key) || query.get(key).equals("")) + return index; + try { + if (data.has("searchindex") + && data.getJSONObject("searchindex").has(key)) { + searchkey = data.getJSONObject("searchindex").getString(key); + } + } catch (JSONException e) { + e.printStackTrace(); + } + + params.add(new BasicNameValuePair("KEY" + index, query.get(key))); + params.add(new BasicNameValuePair("ITEM" + index, searchkey)); + params.add(new BasicNameValuePair("COMP" + index, "3")); + return index + 1; + + } + + @Override + public SearchRequestResult search(Map query) + throws IOException, NotReachableException, OpacErrorException { + List params = new ArrayList(); + + // int index = 0; + start(); + + params.add(new BasicNameValuePair("type", "0")); + params.add(new BasicNameValuePair("allc", "")); + params.add(new BasicNameValuePair("page", "1")); + + // if (query.containsKey(KEY_SEARCH_QUERY_FREE) + // && !query.get(KEY_SEARCH_QUERY_FREE).equals("")) { + params.add(new BasicNameValuePair("keyword", query + .get(KEY_SEARCH_QUERY_FREE))); + // } + params.add(new BasicNameValuePair("sentaku", "and")); + // if (query.containsKey(KEY_SEARCH_QUERY_TITLE) + // && !query.get(KEY_SEARCH_QUERY_TITLE).equals("")) { + params.add(new BasicNameValuePair("title", query + .get(KEY_SEARCH_QUERY_TITLE))); + // } + params.add(new BasicNameValuePair("sentaku", "and")); + // if (query.containsKey(KEY_SEARCH_QUERY_AUTHOR) + // && !query.get(KEY_SEARCH_QUERY_AUTHOR).equals("")) { + params.add(new BasicNameValuePair("author", query + .get(KEY_SEARCH_QUERY_AUTHOR))); + // } + params.add(new BasicNameValuePair("sentaku", "or")); + if (query.containsKey(KEY_SEARCH_QUERY_PUBLISHER) + && !query.get(KEY_SEARCH_QUERY_PUBLISHER).equals("")) { + params.add(new BasicNameValuePair("publish", query + .get(KEY_SEARCH_QUERY_PUBLISHER))); + } else { + params.add(new BasicNameValuePair("publish", "")); + } + params.add(new BasicNameValuePair("sentaku", "or")); + // if (query.containsKey(KEY_SEARCH_QUERY_ISBN) + // && !query.get(KEY_SEARCH_QUERY_ISBN).equals("")) { + params.add(new BasicNameValuePair("isbn", query + .get(KEY_SEARCH_QUERY_ISBN))); + // } + // if (query.containsKey(KEY_SEARCH_QUERY_YEAR) + // && !query.get(KEY_SEARCH_QUERY_YEAR).equals("")) { + params.add(new BasicNameValuePair("pubydate1", query + .get(KEY_SEARCH_QUERY_YEAR))); + // } + params.add(new BasicNameValuePair("pubydate3", "")); + params.add(new BasicNameValuePair("bunrui", "")); + params.add(new BasicNameValuePair("syubetu", "all")); + params.add(new BasicNameValuePair("kan", "all")); + params.add(new BasicNameValuePair("media", "all")); + params.add(new BasicNameValuePair("count", "10")); + params.add(new BasicNameValuePair("order", "publish")); + + params.add(new BasicNameValuePair("before", "select")); + params.add(new BasicNameValuePair("authorid", "")); + params.add(new BasicNameValuePair("opacfile", "")); + params.add(new BasicNameValuePair("titleid", "")); + params.add(new BasicNameValuePair("tophp", "select")); + params.add(new BasicNameValuePair("sid", "")); + sellist_params = params; + + String html = httpGet( + opac_url + "/sellist?" + + URLEncodedUtils.format(params, getDefaultEncoding()), + getDefaultEncoding(), false, cookieStore); + + return parse_search(html, 1); + } + + protected SearchRequestResult parse_search(String html, int page) + throws OpacErrorException { + Document doc = Jsoup.parse(html); + + // updateSearchSetValue(doc); + + if (doc.select("div.page_content center").size() > 0) { + if (doc.select("div.page_content center").text().trim() + .contains("検索結果はありません")) { + // nothing found + return new SearchRequestResult(new ArrayList(), + 0, 1, 1); + } else { + // error + throw new OpacErrorException(doc + .select("div.page_content center").first().text() + .trim()); + } + } + + reusehtml = html; + + int results_total = -1; + + String resultnumstr = ""; + if (doc.select("div.search_report input[name=allc]").size() > 0) { + resultnumstr = doc.select("div.search_report input[name=allc]") + .val(); + results_total = Integer.valueOf(resultnumstr); + } + + List params = new ArrayList(); + params.add(new BasicNameValuePair("type", "0")); + params.add(new BasicNameValuePair("allc", String.valueOf(results_total))); + for (int i = 2; i < sellist_params.size(); i++) { + params.add(sellist_params.get(i)); + } + sellist_params = params; + + // end of page + if ((results_total - 1) / 10 + 1 < page) { + return new SearchRequestResult(new ArrayList(), 0, 1, + 1); + } + List results = new ArrayList(); + + Elements table = doc.select("table.list tr"); + // identifier = null; + + Elements links = doc.select("table.list a"); + boolean haslink = false; + for (int i = 0; i < links.size(); i++) { + Element node = links.get(i); + if (node.hasAttr("href") & node.attr("href").contains("detail?") + && !haslink) { + haslink = true; + try { + List anyurl = URLEncodedUtils.parse(new URI( + node.attr("href")), getDefaultEncoding()); + for (NameValuePair nv : anyurl) { + if (nv.getName().equals("identifier")) { + // identifier = nv.getValue(); + break; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + } + + for (int i = 1; i < table.size(); i++) { + Element tr = table.get(i); + SearchResult sr = new SearchResult(); + if (tr.select("td").size() > 6) { + String fname = tr.select("td").get(6).text(); + if (data.has("mediatypes")) { + try { + sr.setType(MediaType.valueOf(data.getJSONObject( + "mediatypes").getString(fname))); + } catch (JSONException e) { + sr.setType(defaulttypes.get(fname)); + } catch (IllegalArgumentException e) { + sr.setType(defaulttypes.get(fname)); + } + } else { + sr.setType(defaulttypes.get(fname)); + } + } + // Element middlething = tr.child(2); + + // List children = middlething.childNodes(); + // int childrennum = children.size(); + + StringBuilder description = new StringBuilder(); + + if (tr.select("td").size() > 4) { + description.append("" + tr.select("td").get(1).text() + + ""); + description.append("
" + tr.select("td").get(2).text()); + description.append(" - " + tr.select("td").get(3).text()); + description.append(" - " + tr.select("td").get(4).text()); + sr.setInnerhtml(description.toString()); + } + + sr.setNr(10 * (page - 1) + i); + sr.setId(null); + if (tr.select("a").size() > 0) { + sr.setId(tr.select("a").first().attr("href")); + } + if (tr.select("td").size() > 5) { + if (tr.select("td").get(5).text().contains("貸出中")) { + sr.setStatus(Status.RED); + } + } + results.add(sr); + } + resultcount = results.size(); + return new SearchRequestResult(results, results_total, page); + } + + @Override + public SearchRequestResult searchGetPage(int page) throws IOException, + NotReachableException, OpacErrorException { + if (!initialised) + start(); + + List params = new ArrayList(); + for (int i = 0; i < sellist_params.size(); i++) { + if (i == 2) { + params.add(new BasicNameValuePair("page", String.valueOf(page))); + } else { + params.add(sellist_params.get(i)); + } + } + + String html = httpGet( + opac_url + "/sellist?" + + URLEncodedUtils.format(params, getDefaultEncoding()), + getDefaultEncoding(), false, cookieStore); + return parse_search(html, page); + } + + @Override + public SearchRequestResult filterResults(Filter filter, Option option) + throws IOException, NotReachableException { + return null; + } + + @Override + public DetailledItem getResultById(String id, String homebranch) + throws IOException, NotReachableException { + + String html = httpGet(opac_url + "/" + id, getDefaultEncoding(), false); + + return parse_result(html); + } + + @Override + public DetailledItem getResult(int position) throws IOException { + // Should not be called because every media has an ID + + return null; + } + + protected DetailledItem parse_result(String html) throws IOException { + Document doc = Jsoup.parse(html); + doc.setBaseUri(opac_url); + + DetailledItem result = new DetailledItem(); + + // GET TITLE AND SUBTITLE + Element part = doc.select("table.list").first(); + for (Element element : part.select("tr")) { + String title = element.select("th").text().trim(); + String detail = element.select("td").text().trim(); + + if (title.contains("書名") || title.contains("タイトル")) { + result.setTitle(detail); + // result.addDetail(new Detail("Titelzusatz", subtitle)); + } else if (title.contains("ISBN")) { + // GET COVER + if (detail.replaceAll("[^\\dX]", "").length() == 13) { + result.setCover(ISBNTools.getAmazonCoverURL(detail, true)); + } else { + result.setCover(ISBNTools.getAmazonCoverURL("000" + detail, + true)); + } + result.addDetail(new Detail(title, detail)); + } else if (title.contains("外部サイトで調べる")) { + // skip + } else { + result.addDetail(new Detail(title, detail)); + } + } + + Element form; + if (doc.select("form[name=PutFORM]").size() > 0) { + form = doc.select("form[name=PutFORM]").get(1); + result.setId(doc.select("input[name=bid]").first().val()); + Elements inputs = form.parent().select("input"); + StringBuilder str = new StringBuilder(); + for (Element input : inputs) { + if (str.length() > 0) { + str.append("&"); + } + str.append(input.attr("name") + "=" + input.val()); + } + result.setReservation_info(form.attr("action") + "?" + + str.toString()); + } + + // GET OTHER INFORMATION + Map e = new HashMap(); + + if (!library.getData().isNull("accountSupported")) { + try { + result.setReservable(library.getData().getBoolean( + "accountSupported")); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + if (doc.select("table.list").size() > 1) { + part = doc.select("table.list").get(1); + } else { + part = doc.select("table.list").get(0); + } + for (Element element : part.select("tr")) { + if (element.select("td").size() > 5) { + e.put(DetailledItem.KEY_COPY_BRANCH, element.select("td") + .get(1).text().trim()); + e.put(DetailledItem.KEY_COPY_STATUS, element.select("td") + .get(4).text().trim()); + result.addCopy(e); + e = new HashMap(); + } + } + + return result; + } + + @Override + public ReservationResult reservation(DetailledItem item, Account account, + int useraction, String selection) throws IOException { + String reservation_info = item.getReservation_info(); + + // Document doc = null; + + if (useraction == MultiStepResult.ACTION_CONFIRMATION) { + Elements inputs = res_doc.select("form[name=PutFORM]").parents() + .select("input"); + List nameValuePairs = new ArrayList(); + if (inputs.size() > 0) { + for (int i = 0; i < inputs.size(); i++) { + nameValuePairs.add(new BasicNameValuePair(inputs.get(i) + .attr("name"), inputs.get(i).val())); + } + } + httpPost(opac_url + "/rsvend", new UrlEncodedFormEntity( + nameValuePairs), getDefaultEncoding()); + return new ReservationResult(MultiStepResult.Status.OK); + } else if (selection == null || useraction == 0) { + // login + String html = httpGet(opac_url + "/" + reservation_info, + getDefaultEncoding()); + res_doc = Jsoup.parse(html); + + if (res_doc.select("form[name=theFORM]").size() > 0) { + Elements inputs = res_doc.select("form[name=theFORM]") + .parents().select("input"); + List nameValuePairs = new ArrayList(); + for (int i = 0; i < inputs.size(); i++) { + if (i == 0) { + nameValuePairs.add(new BasicNameValuePair("type", "0")); + } else if (i == 2) { + nameValuePairs.add(new BasicNameValuePair("n1", account + .getName())); + } else if (i == 3) { + nameValuePairs.add(new BasicNameValuePair("n2", account + .getPassword())); + } else { + nameValuePairs.add(new BasicNameValuePair(inputs.get(i) + .attr("name"), inputs.get(i).val())); + } + } + html = httpPost(opac_url + "/rsvinput", + new UrlEncodedFormEntity(nameValuePairs), + getDefaultEncoding()); + res_doc = Jsoup.parse(html); + } + + // select contact method + if (res_doc.select("select[name=selectsyudan]").size() > 0) { + Map branches = new HashMap(); + for (Element option : res_doc + .select("select[name=selectsyudan]").first().children()) { + String value = option.text().trim(); + String key; + if (option.hasAttr("value")) { + key = option.attr("value"); + } else { + key = value; + } + branches.put(key, value); + } + ReservationResult result = new ReservationResult( + MultiStepResult.Status.SELECTION_NEEDED); + result.setActionIdentifier(ReservationResult.ACTION_USER); + result.setSelection(branches); + return result; + } else if (res_doc.select("select[name=selectplace]").size() > 0) { + // select branch + Map branches = new HashMap(); + for (Element option : res_doc + .select("select[name=selectplace]").first().children()) { + String value = option.text().trim(); + String key; + if (option.hasAttr("value")) { + key = option.attr("value"); + } else { + key = value; + } + branches.put(key, value); + } + ReservationResult result = new ReservationResult( + MultiStepResult.Status.SELECTION_NEEDED); + result.setActionIdentifier(ReservationResult.ACTION_BRANCH); + result.setSelection(branches); + return result; + } + } else if (useraction == ReservationResult.ACTION_USER) { + // select branch + contact = selection; + // String html = httpGet(reservation_info, getDefaultEncoding()); + // doc = Jsoup.parse(html); + + if (res_doc.select("select[name=selectplace]").size() > 0) { + Map branches = new HashMap(); + for (Element option : res_doc + .select("select[name=selectplace]").first().children()) { + String value = option.text().trim(); + String key; + if (option.hasAttr("value")) { + key = option.attr("value"); + } else { + key = value; + } + branches.put(key, value); + } + ReservationResult result = new ReservationResult( + MultiStepResult.Status.SELECTION_NEEDED); + result.setActionIdentifier(ReservationResult.ACTION_BRANCH); + result.setSelection(branches); + return result; + } + } else if (useraction == ReservationResult.ACTION_BRANCH) { + // String html = httpGet(reservation_info, getDefaultEncoding()); + // doc = Jsoup.parse(html); + + Elements inputs = res_doc.select("form[name=PutFORM]").parents() + .select("input"); + List nameValuePairs = new ArrayList(); + if (inputs.size() > 5) { + for (int i = 0; i < 6; i++) { + nameValuePairs.add(new BasicNameValuePair(inputs.get(i) + .attr("name"), inputs.get(i).val())); + } + } + nameValuePairs + .add(new BasicNameValuePair("selectplace", selection)); + if (contact != null) { + nameValuePairs.add(new BasicNameValuePair("selectsyudan", + contact)); + } + if (inputs.size() > 6) { + for (int i = 6; i < inputs.size(); i++) { + nameValuePairs.add(new BasicNameValuePair(inputs.get(i) + .attr("name"), inputs.get(i).val())); + } + } + String html = httpPost(opac_url + "/rsvinfo", + new UrlEncodedFormEntity(nameValuePairs), + getDefaultEncoding()); + res_doc = Jsoup.parse(html); + } + + if (res_doc == null) + return new ReservationResult(MultiStepResult.Status.ERROR); + + if (res_doc.select("table.ulist").size() > 1) { + List details = new ArrayList(); + + for (Element row : res_doc.select("table.ulist").get(1) + .select("tr")) { + if (row.select("th").size() == 1 + && row.select("td").size() == 1) { + details.add(new String[] { row.select("th").text().trim(), + row.select("td").text().trim() }); + } + } + ReservationResult result = new ReservationResult( + MultiStepResult.Status.CONFIRMATION_NEEDED); + result.setDetails(details); + return result; + } + + if (res_doc.getElementsByClass("MSGBOLDL").size() == 1) { + return new ReservationResult(MultiStepResult.Status.ERROR, res_doc + .getElementsByClass("MSGBOLDL").get(0).text()); + } + + return new ReservationResult(MultiStepResult.Status.ERROR, + "Unbekannter Fehler"); + } + + @Override + public ProlongResult prolong(String media, Account account, int useraction, + String Selection) throws IOException { + if (pwEncoded == null) + try { + account(account); + } catch (JSONException e1) { + return new ProlongResult(MultiStepResult.Status.ERROR); + } catch (OpacErrorException e1) { + return new ProlongResult(MultiStepResult.Status.ERROR, + e1.getMessage()); + } + + String html = httpGet(opac_url + "/" + media, getDefaultEncoding()); + Document doc = Jsoup.parse(html); + + if (doc.select("div.page_content_frame").text().contains("完了しました")) { + return new ProlongResult(MultiStepResult.Status.OK); + } else if (doc.select("div.page_content_frame").text() + .contains("ログインしてください") + || doc.select("div.page_content_frame").text() + .contains("有効時間が経過しています")) { + try { + account(account); + return prolong(media, account, useraction, Selection); + } catch (JSONException e) { + return new ProlongResult(MultiStepResult.Status.ERROR); + } catch (OpacErrorException e) { + return new ProlongResult(MultiStepResult.Status.ERROR, + e.getMessage()); + } + } else { + ProlongResult res = new ProlongResult(MultiStepResult.Status.ERROR); + res.setMessage(doc.select("div.page_content_frame").text()); + return res; + } + } + + @Override + public ProlongAllResult prolongAll(Account account, int useraction, + String selection) throws IOException { + return null; + } + + @Override + public CancelResult cancel(String media, Account account, int useraction, + String selection) throws IOException, OpacErrorException { + String html = httpGet(opac_url + "/" + media, getDefaultEncoding()); + Document doc = Jsoup.parse(html); + + if (doc.select("div.page_content_frame").text().contains("完了しました")) { + return new CancelResult(MultiStepResult.Status.OK); + } else if (doc.select("div.page_content_frame").text() + .contains("ログインしてください") + || doc.select("div.page_content_frame").text() + .contains("有効時間が経過しています")) { + try { + account(account); + return cancel(media, account, useraction, selection); + } catch (JSONException e) { + throw new OpacErrorException("内部エラー"); + } + } else { + CancelResult res = new CancelResult(MultiStepResult.Status.ERROR); + res.setMessage(doc.select("div.page_content_frame").text()); + return res; + } + } + + @Override + public AccountData account(Account account) throws IOException, + JSONException, OpacErrorException { + List params = new ArrayList(); + params.add(new BasicNameValuePair("type", "0")); + params.add(new BasicNameValuePair("n1", account.getName())); + params.add(new BasicNameValuePair("n2", account.getPassword())); + params.add(new BasicNameValuePair("ptype", "")); + params.add(new BasicNameValuePair("befHP", "userlogin")); + + String html = httpPost(opac_url + "/userinfo", + new UrlEncodedFormEntity(params, getDefaultEncoding()), + getDefaultEncoding()); + Document doc = Jsoup.parse(html); + + // if (doc.select("div.MSGBOLDL").size() > 0) { + // throw new OpacErrorException(doc.select("div.MSGBOLDL").text()); + // } + unEncoded = doc.select("input[name=.u1]").val(); + pwEncoded = doc.select("input[name=.u2]").val(); + dtype = doc.select("input[name=dtype]").val(); + type = doc.select("input[name=type]").val(); + sid = doc.select("input[name=sid]").val(); + + params = new ArrayList(); + params.add(new BasicNameValuePair("dtype", "0")); + params.add(new BasicNameValuePair(".u1", unEncoded)); + params.add(new BasicNameValuePair(".u2", pwEncoded)); + params.add(new BasicNameValuePair("type", "2")); + params.add(new BasicNameValuePair(sid, sid)); + + html = httpPost(opac_url + "/userlendlist", new UrlEncodedFormEntity( + params, getDefaultEncoding()), getDefaultEncoding()); + doc = Jsoup.parse(html); + + params = new ArrayList(); + params.add(new BasicNameValuePair("dtype", "0")); + params.add(new BasicNameValuePair(".u1", unEncoded)); + params.add(new BasicNameValuePair(".u2", pwEncoded)); + params.add(new BasicNameValuePair("type", "3")); + params.add(new BasicNameValuePair(sid, sid)); + + html = httpPost(opac_url + "/userlendlist", new UrlEncodedFormEntity( + params, getDefaultEncoding()), getDefaultEncoding()); + Document doc2 = Jsoup.parse(html); + + AccountData res = new AccountData(account.getId()); + + List> medien = new ArrayList>(); + List> reserved = new ArrayList>(); + if (doc.select("div.page_content_frame table tr").size() > 0) { + parse_medialist(medien, doc, 1, account.getName()); + } + if (doc2.select("div.page_content_frame table tr").size() > 0) { + parse_reslist(reserved, doc2, 1); + } + + res.setLent(medien); + res.setReservations(reserved); + + if (medien == null || reserved == null) { + throw new OpacErrorException("不明なエラー. アカウントが正しいことを確認してください."); + // Log.d("OPACCLIENT", html); + } + return res; + + } + + protected void parse_medialist(List> medien, + Document doc, int offset, String accountName) + throws ClientProtocolException, IOException { + + Elements copytrs = doc.select("div.page_content_frame table tr"); + Elements table = doc.select("div.page_content_frame table tr th"); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.JAPAN); + + int trs = copytrs.size(); + if (trs < 1) { + medien = null; + return; + } + assert (trs > 1); + for (int i = 1; i < trs; i++) { + // Document doc1 = null; + // try { + // String html = httpGet(copytrs.get(i).select("a").attr("href"), + // getDefaultEncoding()); + // doc1 = Jsoup.parse(html); + // } catch (IOException e) { + // + // } + Element tr = copytrs.get(i); + Map e = new HashMap(); + for (int j = 0; j < table.size(); j++) { + if (table.get(j).text().trim().equals("書名") + || table.get(j).text().trim().equals("タイトル")) { + e.put(AccountData.KEY_LENT_TITLE, tr.select("td").get(j) + .text().trim()); + } else if (table.get(j).text().trim().equals("返却期限") + || table.get(j).text().trim().equals("返却日")) { + e.put(AccountData.KEY_LENT_DEADLINE, tr.select("td").get(j) + .text().trim()); + } + } + // e.put(AccountData.KEY_LENT_STATUS, status); + try { + e.put(AccountData.KEY_LENT_DEADLINE_TIMESTAMP, String + .valueOf(sdf + .parse(e.get(AccountData.KEY_LENT_DEADLINE)) + .getTime())); + } catch (ParseException e1) { + e1.printStackTrace(); + } + if (tr.select("form[name=PutFORM]").size() > 0) { + Elements inputs = doc.select("form[name=PutFORM]") + .parents().select("input"); + List nameValuePairs = new ArrayList(); + if (inputs.size() > 0) { + for (int j = 0; j < inputs.size(); j++) { + nameValuePairs.add(new BasicNameValuePair(inputs.get(j) + .attr("name"), inputs.get(j).val())); + } + } + e.put(AccountData.KEY_LENT_LINK, "userencho?" + URLEncodedUtils.format(nameValuePairs, getDefaultEncoding())); + } else { + e.put(AccountData.KEY_LENT_RENEWABLE, "N"); + } + + medien.add(e); + } + assert (medien.size() == trs - 1); + } + + protected void parse_reslist(List> medien, + Document doc, int offset) throws ClientProtocolException, + IOException { + + // if(doc.select("input[name=LOR_RESERVATIONS]").size()>0) { + // lor_reservations = + // doc.select("input[name=LOR_RESERVATIONS]").attr("value"); + // } + + Elements copytrs = doc.select("div.page_content_frame table tr"); + Elements table = doc.select("div.page_content_frame table tr th"); + if (doc.select("div.page_content_frame").size() > 0) { + copytrs = doc.select("div.page_content_frame").get(0).select("table tr"); + table = doc.select("div.page_content_frame").get(0).select("table tr th"); + } + + int trs1 = copytrs.size(); + if (trs1 >= 1) { + for (int i = 1; i < trs1; i++) { + Element tr = copytrs.get(i); + Map e = new HashMap(); + + for (int j = 0; j < table.size(); j++) { + if (table.get(j).text().trim().equals("書名") + || table.get(j).text().trim().equals("タイトル")) { + e.put(AccountData.KEY_RESERVATION_TITLE, tr.select("td") + .get(j).text().trim()); + e.put(AccountData.KEY_RESERVATION_READY, "ご用意できました"); + } else if (table.get(j).text().trim().equals("受取館")) { + e.put(AccountData.KEY_RESERVATION_BRANCH, tr.select("td") + .get(j).text().trim()); + } else if (table.get(j).text().trim().equals("引取期限日")) { + e.put(AccountData.KEY_RESERVATION_EXPIRE, tr.select("td") + .get(j).text().trim()); + } + } + + medien.add(e); + } + } +// assert (medien.size() == trs1 - 1); + + if (doc.select("div.page_content_frame").size() > 1) { + copytrs = doc.select("div.page_content_frame").get(1).select("table tr"); + table = doc.select("div.page_content_frame").get(1).select("table tr th"); + } + + int trs = copytrs.size(); + if (trs >= 1) { + for (int i = 1; i < trs; i++) { + Element tr = copytrs.get(i); + Map e = new HashMap(); + + for (int j = 0; j < table.size(); j++) { + if (table.get(j).text().trim().equals("書名") + || table.get(j).text().trim().equals("タイトル")) { + e.put(AccountData.KEY_RESERVATION_TITLE, tr.select("td") + .get(j).text().trim()); + } else if (table.get(j).text().trim().equals("予約状況") + || table.get(j).text().trim().equals("予約順位")) { + e.put(AccountData.KEY_RESERVATION_READY, tr.select("td") + .get(j).text().trim()); + } else if (table.get(j).text().trim().equals("受取館")) { + e.put(AccountData.KEY_RESERVATION_BRANCH, tr.select("td") + .get(j).text().trim()); + } + } + // e.put(AccountData.KEY_RESERVATION_TITLE, + // tr.select("td").get(1).text().trim()); + // e.put(AccountData.KEY_RESERVATION_READY, + // tr.select("td").get(4).text().trim()); + if (tr.select("form[name=PutFORM]").size() > 0) { + Elements inputs = doc.select("form[name=PutFORM]") + .parents().select("input"); + List nameValuePairs = new ArrayList(); + if (inputs.size() > 0) { + for (int j = 0; j < inputs.size(); j++) { + nameValuePairs.add(new BasicNameValuePair(inputs.get(j) + .attr("name"), inputs.get(j).val())); + } + } + e.put(AccountData.KEY_RESERVATION_CANCEL, "userrsvdel?" + + URLEncodedUtils.format(nameValuePairs, getDefaultEncoding())); + } + + medien.add(e); + } + } +// assert (medien.size() == trs - 1 + trs1 - 1); + } + + @Override + public String[] getSearchFields() { + return new String[] { KEY_SEARCH_QUERY_FREE, KEY_SEARCH_QUERY_AUTHOR, + KEY_SEARCH_QUERY_KEYWORDA, KEY_SEARCH_QUERY_YEAR, + KEY_SEARCH_QUERY_SYSTEM, KEY_SEARCH_QUERY_PUBLISHER, + KEY_SEARCH_QUERY_ISBN }; + } + + @Override + public boolean isAccountSupported(Library library) { + if (!library.getData().isNull("accountSupported")) { + try { + return library.getData().getBoolean("accountSupported"); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return false; + } + + @Override + public boolean isAccountExtendable() { + return false; + } + + @Override + public String getAccountExtendableInfo(Account account) throws IOException, + NotReachableException { + return null; + } + + @Override + public String getShareUrl(String id, String title) { + return id; + } + + @Override + public int getSupportFlags() { + return SUPPORT_FLAG_ENDLESS_SCROLLING | SUPPORT_FLAG_CHANGE_ACCOUNT; + } + + @Override + protected String getDefaultEncoding() { + try { + if (data.has("charset")) + return data.getString("charset"); + } catch (JSONException e) { + e.printStackTrace(); + } + return "UTF-8"; + } + +} \ No newline at end of file diff --git a/WorldOpac/src/de/geeksfactory/opacclient/frontend/MainActivity.java b/WorldOpac/src/de/geeksfactory/opacclient/frontend/MainActivity.java index 7a150bc..7a4a0f5 100644 --- a/WorldOpac/src/de/geeksfactory/opacclient/frontend/MainActivity.java +++ b/WorldOpac/src/de/geeksfactory/opacclient/frontend/MainActivity.java @@ -116,7 +116,15 @@ public class MainActivity extends OpacActivity implements adView.setAdSize(AdSize.BANNER); View root = getWindow().getDecorView(); View firstChild = ((ViewGroup) root).getChildAt(0); - ((LinearLayout) firstChild).addView(adView); + //This is for Jelly, ICS, Honeycomb + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + ((LinearLayout) firstChild).addView(adView); + //This is for KitKat and Jelly 4.3 + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + ((ViewGroup) firstChild).addView(adView); + } else { + ((LinearLayout) firstChild).addView(adView); + } AdRequest adRequest = new AdRequest.Builder().build(); adView.loadAd(adRequest); } diff --git a/WorldOpac/src/de/geeksfactory/opacclient/frontend/SearchResultDetailActivity.java b/WorldOpac/src/de/geeksfactory/opacclient/frontend/SearchResultDetailActivity.java index 9a8ace6..66d5bc5 100644 --- a/WorldOpac/src/de/geeksfactory/opacclient/frontend/SearchResultDetailActivity.java +++ b/WorldOpac/src/de/geeksfactory/opacclient/frontend/SearchResultDetailActivity.java @@ -4,6 +4,7 @@ import com.google.android.gms.ads.AdRequest; import com.google.android.gms.ads.AdSize; import com.google.android.gms.ads.AdView; +import android.os.Build; import android.os.Bundle; import android.view.MenuItem; import android.view.View; @@ -72,7 +73,15 @@ public class SearchResultDetailActivity extends OpacActivity implements SearchRe adView.setAdSize(AdSize.BANNER); View root = getWindow().getDecorView(); View firstChild = ((ViewGroup) root).getChildAt(0); - ((LinearLayout) firstChild).addView(adView); + //This is for Jelly, ICS, Honeycomb + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + ((LinearLayout) firstChild).addView(adView); + //This is for KitKat and Jelly 4.3 + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + ((ViewGroup) firstChild).addView(adView); + } else { + ((LinearLayout) firstChild).addView(adView); + } AdRequest adRequest = new AdRequest.Builder().build(); adView.loadAd(adRequest); } diff --git a/WorldOpac/src/de/geeksfactory/opacclient/frontend/SearchResultListActivity.java b/WorldOpac/src/de/geeksfactory/opacclient/frontend/SearchResultListActivity.java index 29c593e..f981c77 100644 --- a/WorldOpac/src/de/geeksfactory/opacclient/frontend/SearchResultListActivity.java +++ b/WorldOpac/src/de/geeksfactory/opacclient/frontend/SearchResultListActivity.java @@ -9,13 +9,13 @@ import com.google.android.gms.ads.AdSize; import com.google.android.gms.ads.AdView; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.view.Window; import android.widget.LinearLayout; import de.geeksfactory.opacclient.NotReachableException; import de.geeksfactory.opacclient.OpacClient; @@ -81,7 +81,15 @@ public class SearchResultListActivity extends OpacActivity implements adView.setAdSize(AdSize.BANNER); View root = getWindow().getDecorView(); View firstChild = ((ViewGroup) root).getChildAt(0); - ((LinearLayout) firstChild).addView(adView); + //This is for Jelly, ICS, Honeycomb + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + ((LinearLayout) firstChild).addView(adView); + //This is for KitKat and Jelly 4.3 + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + ((ViewGroup) firstChild).addView(adView); + } else { + ((LinearLayout) firstChild).addView(adView); + } AdRequest adRequest = new AdRequest.Builder().build(); adView.loadAd(adRequest); } -- 2.11.0