/* * Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com> * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ package org.geometerplus.fbreader.network.authentication.litres; import java.util.*; import org.geometerplus.zlibrary.core.xml.*; import org.geometerplus.fbreader.network.NetworkItem; import org.geometerplus.fbreader.network.opds.OPDSBookItem; import org.geometerplus.fbreader.network.opds.OPDSNetworkLink; import org.geometerplus.fbreader.network.atom.FormattedBuffer; import org.geometerplus.fbreader.network.urlInfo.*; class LitResXMLReader extends LitResAuthenticationXMLReader { public final OPDSNetworkLink Link; public final List<NetworkItem> Books; private int myIndex; private String myBookId; private String myTitle; //private String myLanguage; //private String myDate; private String mySeriesTitle; private int myIndexInSeries; private CharSequence mySummary; private final UrlInfoCollection<UrlInfo> myUrls = new UrlInfoCollection<UrlInfo>(); private String myAuthorFirstName; private String myAuthorMiddleName; private String myAuthorLastName; private LinkedList<OPDSBookItem.AuthorData> myAuthors = new LinkedList<OPDSBookItem.AuthorData>(); private LinkedList<String> myTags = new LinkedList<String>(); public LitResXMLReader(OPDSNetworkLink link, List<NetworkItem> books) { super(link.getSiteName()); Link = link; Books = books; } private static final int START = 0; private static final int CATALOG = 1; private static final int BOOK = 2; private static final int BOOK_DESCRIPTION = 3; private static final int HIDDEN = 4; private static final int TITLE_INFO = 5; private static final int GENRE = 6; private static final int AUTHOR = 7; private static final int FIRST_NAME = 8; private static final int MIDDLE_NAME = 9; private static final int LAST_NAME = 10; private static final int BOOK_TITLE = 11; private static final int ANNOTATION = 12; private static final int DATE = 13; private static final int LANGUAGE = 14; private static final String TAG_CATALOG = "catalit-fb2-books"; private static final String TAG_BOOK = "fb2-book"; private static final String TAG_TEXT_DESCRIPTION = "text_description"; private static final String TAG_HIDDEN = "hidden"; private static final String TAG_TITLE_INFO = "title-info"; private static final String TAG_GENRE = "genre"; private static final String TAG_AUTHOR = "author"; private static final String TAG_FIRST_NAME = "first-name"; private static final String TAG_MIDDLE_NAME = "middle-name"; private static final String TAG_LAST_NAME = "last-name"; private static final String TAG_BOOK_TITLE = "book-title"; private static final String TAG_ANNOTATION = "annotation"; private static final String TAG_DATE = "date"; private static final String TAG_SEQUENCE = "sequence"; private static final String TAG_LANGUAGE = "lang"; private int myState = START; private final StringBuilder myBuffer = new StringBuilder(); private FormattedBuffer myAnnotationBuffer = new FormattedBuffer(FormattedBuffer.Type.XHtml); @Override public boolean startElementHandler(String tag, ZLStringMap attributes) { tag = tag.intern(); switch (myState) { case START: if (TAG_CATALOG == tag) { myState = CATALOG; } break; case CATALOG: if (TAG_BOOK == tag) { myBookId = attributes.getValue("hub_id"); myUrls.addInfo(new UrlInfo( UrlInfo.Type.Image, attributes.getValue("cover_preview") )); myUrls.addInfo(new BookUrlInfo( UrlInfo.Type.BookConditional, BookUrlInfo.Format.FB2_ZIP, "https://robot.litres.ru/pages/catalit_download_book/?art=" + myBookId )); myState = BOOK; } break; case BOOK: if (TAG_TEXT_DESCRIPTION == tag) { myState = BOOK_DESCRIPTION; } break; case BOOK_DESCRIPTION: if (TAG_HIDDEN == tag) { myState = HIDDEN; } break; case HIDDEN: if (TAG_TITLE_INFO == tag) { myState = TITLE_INFO; } break; case TITLE_INFO: if (TAG_GENRE == tag) { myState = GENRE; } else if (TAG_AUTHOR == tag) { myState = AUTHOR; } else if (TAG_BOOK_TITLE == tag) { myState = BOOK_TITLE; } else if (TAG_ANNOTATION == tag) { myState = ANNOTATION; } else if (TAG_DATE == tag) { myState = DATE; } else if (TAG_LANGUAGE == tag) { myState = LANGUAGE; } else if (TAG_SEQUENCE == tag) { mySeriesTitle = attributes.getValue("name"); if (mySeriesTitle != null) { myIndexInSeries = 0; final String indexInSeries = attributes.getValue("number"); if (indexInSeries != null) { try { myIndexInSeries = Integer.parseInt(indexInSeries); } catch (NumberFormatException e) { } } } //myState = SEQUENCE; // handled through attributes without state } break; case AUTHOR: if (TAG_FIRST_NAME == tag) { myState = FIRST_NAME; } else if (TAG_MIDDLE_NAME == tag) { myState = MIDDLE_NAME; } else if (TAG_LAST_NAME == tag) { myState = LAST_NAME; } break; case ANNOTATION: myAnnotationBuffer.appendText(myBuffer); myAnnotationBuffer.appendStartTag(tag, attributes); break; } myBuffer.delete(0, myBuffer.length()); return false; } @Override public boolean endElementHandler(String tag) { tag = tag.intern(); switch (myState) { case CATALOG: if (TAG_CATALOG == tag) { myState = START; } break; case BOOK: if (TAG_BOOK == tag) { myUrls.addInfo(new UrlInfo( UrlInfo.Type.SingleEntry, "http://data.fbreader.org/catalogs/litres2/full.php5?id=" + myBookId )); Books.add(new OPDSBookItem( Link, myBookId, myIndex++, myTitle, mySummary, //myLanguage, //myDate, myAuthors, myTags, mySeriesTitle, myIndexInSeries, myUrls )); myBookId = myTitle = /*myLanguage = myDate = */mySeriesTitle = null; mySummary = null; myIndexInSeries = 0; myAuthors.clear(); myTags.clear(); myUrls.clear(); myState = CATALOG; } break; case BOOK_DESCRIPTION: if (TAG_TEXT_DESCRIPTION == tag) { myState = BOOK; } break; case HIDDEN: if (TAG_HIDDEN == tag) { myState = BOOK_DESCRIPTION; } break; case TITLE_INFO: if (TAG_TITLE_INFO == tag) { myState = HIDDEN; } break; case AUTHOR: if (TAG_AUTHOR == tag) { StringBuilder displayName = new StringBuilder(); if (myAuthorFirstName != null) { displayName.append(myAuthorFirstName).append(" "); } if (myAuthorMiddleName != null) { displayName.append(myAuthorMiddleName).append(" "); } if (myAuthorLastName != null) { displayName.append(myAuthorLastName).append(" "); } myAuthors.add(new OPDSBookItem.AuthorData(displayName.toString().trim(), myAuthorLastName)); myAuthorFirstName = null; myAuthorMiddleName = null; myAuthorLastName = null; myState = TITLE_INFO; } break; case FIRST_NAME: if (TAG_FIRST_NAME == tag) { myAuthorFirstName = myBuffer.toString(); myState = AUTHOR; } break; case MIDDLE_NAME: if (TAG_MIDDLE_NAME == tag) { myAuthorMiddleName = myBuffer.toString(); myState = AUTHOR; } break; case LAST_NAME: if (TAG_LAST_NAME == tag) { myAuthorLastName = myBuffer.toString(); myState = AUTHOR; } break; case GENRE: if (TAG_GENRE == tag) { /*if (myBuffer.length() != 0) { const std::map<std::string,shared_ptr<LitResGenre> > &genresMap = LitResGenreMap::Instance().genresMap(); const std::map<shared_ptr<LitResGenre>,std::string> &genresTitles = LitResGenreMap::Instance().genresTitles(); std::map<std::string, shared_ptr<LitResGenre> >::const_iterator it = genresMap.find(myBuffer); if (it != genresMap.end()) { std::map<shared_ptr<LitResGenre>, std::string>::const_iterator jt = genresTitles.find(it->second); if (jt != genresTitles.end()) { myTags.push_back(jt->second); } } }*/ myState = TITLE_INFO; } break; case BOOK_TITLE: if (TAG_BOOK_TITLE == tag) { myTitle = myBuffer.toString(); myState = TITLE_INFO; } break; case ANNOTATION: myAnnotationBuffer.appendText(myBuffer); if (TAG_ANNOTATION == tag) { mySummary = myAnnotationBuffer.getText(); myAnnotationBuffer.reset(); myState = TITLE_INFO; } else { myAnnotationBuffer.appendEndTag(tag); } break; case DATE: if (TAG_DATE == tag) { //myDate = myBuffer.toString(); myState = TITLE_INFO; } break; case LANGUAGE: if (TAG_LANGUAGE == tag) { //myLanguage = myBuffer.toString(); myState = TITLE_INFO; } break; } myBuffer.delete(0, myBuffer.length()); return false; } @Override public void characterDataHandler(char[] data, int start, int length) { myBuffer.append(data, start, length); } }