/* * 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.constants.MimeTypes; import org.geometerplus.zlibrary.core.xml.*; import org.geometerplus.fbreader.network.*; import org.geometerplus.fbreader.network.opds.HtmlToString; class LitResXMLReader extends LitResAuthenticationXMLReader { public final INetworkLink 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 String mySummary; private String myCover; private String myAuthorFirstName; private String myAuthorMiddleName; private String myAuthorLastName; private LinkedList<NetworkBookItem.AuthorData> myAuthors = new LinkedList<NetworkBookItem.AuthorData>(); private LinkedList<String> myTags = new LinkedList<String>(); private LinkedList<BookReference> myReferences = new LinkedList<BookReference>(); public LitResXMLReader(INetworkLink 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 HtmlToString myHtmlToString = new HtmlToString(); @Override public boolean startElementHandler(String tag, ZLStringMap attributes) { tag = tag.intern(); final char[] bufferContentArray = myBuffer.toString().trim().toCharArray(); final String bufferContent; if (bufferContentArray.length == 0) { bufferContent = null; } else { bufferContent = new String(bufferContentArray); } myBuffer.delete(0, myBuffer.length()); switch(myState) { case START: if (TAG_CATALOG == tag) { myState = CATALOG; } break; case CATALOG: if (TAG_BOOK == tag) { myBookId = attributes.getValue("hub_id"); myCover = attributes.getValue("cover_preview"); myReferences.add(new BookReference( "https://robot.litres.ru/pages/catalit_download_book/?art=" + myBookId, BookReference.Format.FB2_ZIP, BookReference.Type.DOWNLOAD_FULL_CONDITIONAL )); 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) { myHtmlToString.setupTextContent(MimeTypes.MIME_TEXT_XHTML); 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: myHtmlToString.processTextContent(false, tag, attributes, bufferContent); break; } return false; } @Override public boolean endElementHandler(String tag) { tag = tag.intern(); final char[] bufferContentArray = myBuffer.toString().trim().toCharArray(); final String bufferContent; if (bufferContentArray.length == 0) { bufferContent = null; } else { bufferContent = new String(bufferContentArray); } myBuffer.delete(0, myBuffer.length()); switch (myState) { case CATALOG: if (TAG_CATALOG == tag) { myState = START; } break; case BOOK: if (TAG_BOOK == tag) { Books.add(new NetworkBookItem( Link, myBookId, myIndex++, myTitle, mySummary, //myLanguage, //myDate, myAuthors, myTags, mySeriesTitle, myIndexInSeries, myCover, myReferences )); myBookId = myTitle = /*myLanguage = myDate = */mySeriesTitle = mySummary = myCover = null; myIndexInSeries = 0; myAuthors.clear(); myTags.clear(); myReferences.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 NetworkBookItem.AuthorData(displayName.toString().trim(), myAuthorLastName)); myAuthorFirstName = null; myAuthorMiddleName = null; myAuthorLastName = null; myState = TITLE_INFO; } break; case FIRST_NAME: if (TAG_FIRST_NAME == tag) { myAuthorFirstName = bufferContent; myState = AUTHOR; } break; case MIDDLE_NAME: if (TAG_MIDDLE_NAME == tag) { myAuthorMiddleName = bufferContent; myState = AUTHOR; } break; case LAST_NAME: if (TAG_LAST_NAME == tag) { myAuthorLastName = bufferContent; myState = AUTHOR; } break; case GENRE: if (TAG_GENRE == tag) { /*if (bufferContent != null) { 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(bufferContent); 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 = bufferContent; myState = TITLE_INFO; } break; case ANNOTATION: if (TAG_ANNOTATION == tag) { mySummary = myHtmlToString.finishTextContent(bufferContent); myState = TITLE_INFO; } else { myHtmlToString.processTextContent(true, tag, null, bufferContent); } break; case DATE: if (TAG_DATE == tag) { //myDate = bufferContent; myState = TITLE_INFO; } break; case LANGUAGE: if (TAG_LANGUAGE == tag) { //myLanguage = bufferContent; myState = TITLE_INFO; } break; } return false; } @Override public void characterDataHandler(char[] data, int start, int length) { myBuffer.append(data, start, length); } }