/*
* Copyright (C) 2007-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.formats.fb2;
import java.util.*;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.xml.*;
import org.geometerplus.fbreader.library.Book;
import org.geometerplus.fbreader.library.Tag;
public class FB2MetaInfoReader extends ZLXMLReaderAdapter {
private final static int READ_NOTHING = 0;
private final static int READ_SOMETHING = 1;
private final static int READ_TITLE = 2;
private final static int READ_AUTHOR = 3;
private final static int READ_AUTHOR_NAME_0 = 4;
private final static int READ_AUTHOR_NAME_1 = 5;
private final static int READ_AUTHOR_NAME_2 = 6;
private final static int READ_LANGUAGE = 7;
private final static int READ_GENRE = 8;
private final Book myBook;
private int myReadState = READ_NOTHING;
private final String[] myAuthorNames = new String[3];
private final StringBuilder myBuffer = new StringBuilder();
public FB2MetaInfoReader(Book book) {
myBook = book;
myBook.setTitle(null);
myBook.setLanguage(null);
}
public boolean dontCacheAttributeValues() {
return true;
}
public boolean readMetaInfo() {
myReadState = READ_NOTHING;
myAuthorNames[0] = "";
myAuthorNames[1] = "";
myAuthorNames[2] = "";
myBuffer.delete(0, myBuffer.length());
return readDocument(myBook.File);
}
public boolean startElementHandler(String tagName, ZLStringMap attributes) {
switch (FB2Tag.getTagByName(tagName)) {
case FB2Tag.BODY:
return true;
case FB2Tag.TITLE_INFO:
myReadState = READ_SOMETHING;
break;
case FB2Tag.BOOK_TITLE:
if (myReadState == READ_SOMETHING) {
myReadState = READ_TITLE;
}
break;
case FB2Tag.GENRE:
if (myReadState == READ_SOMETHING) {
myReadState = READ_GENRE;
}
break;
case FB2Tag.AUTHOR:
if (myReadState == READ_SOMETHING) {
myReadState = READ_AUTHOR;
}
break;
case FB2Tag.LANG:
if (myReadState == READ_SOMETHING) {
myReadState = READ_LANGUAGE;
}
break;
case FB2Tag.FIRST_NAME:
if (myReadState == READ_AUTHOR) {
myReadState = READ_AUTHOR_NAME_0;
}
break;
case FB2Tag.MIDDLE_NAME:
if (myReadState == READ_AUTHOR) {
myReadState = READ_AUTHOR_NAME_1;
}
break;
case FB2Tag.LAST_NAME:
if (myReadState == READ_AUTHOR) {
myReadState = READ_AUTHOR_NAME_2;
}
break;
case FB2Tag.SEQUENCE:
if (myReadState == READ_SOMETHING) {
String name = attributes.getValue("name");
if (name != null) {
name.trim();
if (name.length() != 0) {
int index = 0;
try {
final String sIndex = attributes.getValue("number");
if (sIndex != null) {
index = Integer.parseInt(sIndex);
}
} catch (NumberFormatException e) {
}
myBook.setSeriesInfo(name, index);
}
}
}
break;
}
return false;
}
public boolean endElementHandler(String tag) {
switch (FB2Tag.getTagByName(tag)) {
case FB2Tag.TITLE_INFO:
myReadState = READ_NOTHING;
break;
case FB2Tag.BOOK_TITLE:
if (myReadState == READ_TITLE) {
myBook.setTitle(myBuffer.toString().trim());
myReadState = READ_SOMETHING;
}
break;
case FB2Tag.GENRE:
if (myReadState == READ_GENRE) {
final String genre = myBuffer.toString().trim();
if (genre.length() > 0) {
final ArrayList<Tag> tags = FB2TagManager.humanReadableTags(genre);
if (tags != null) {
for (Tag t : tags) {
myBook.addTag(t);
}
} else {
myBook.addTag(genre);
}
}
myReadState = READ_SOMETHING;
}
break;
case FB2Tag.AUTHOR:
if (myReadState == READ_AUTHOR) {
myAuthorNames[0] = myAuthorNames[0].trim();
myAuthorNames[1] = myAuthorNames[1].trim();
myAuthorNames[2] = myAuthorNames[2].trim();
String fullName = myAuthorNames[0];
if (fullName.length() != 0 && myAuthorNames[1].length() != 0) {
fullName += ' ';
}
fullName += myAuthorNames[1];
if (fullName.length() != 0 && myAuthorNames[2].length() != 0) {
fullName += ' ';
}
fullName += myAuthorNames[2];
myBook.addAuthor(fullName, myAuthorNames[2]);
myAuthorNames[0] = "";
myAuthorNames[1] = "";
myAuthorNames[2] = "";
myReadState = READ_SOMETHING;
}
break;
case FB2Tag.LANG:
if (myReadState == READ_LANGUAGE) {
myBook.setLanguage(myBuffer.toString().trim());
myReadState = READ_SOMETHING;
}
break;
case FB2Tag.FIRST_NAME:
if (myReadState == READ_AUTHOR_NAME_0) {
myReadState = READ_AUTHOR;
}
break;
case FB2Tag.MIDDLE_NAME:
if (myReadState == READ_AUTHOR_NAME_1) {
myReadState = READ_AUTHOR;
}
break;
case FB2Tag.LAST_NAME:
if (myReadState == READ_AUTHOR_NAME_2) {
myReadState = READ_AUTHOR;
}
break;
default:
break;
}
myBuffer.delete(0, myBuffer.length());
return false;
}
public void characterDataHandler(char[] data, int start, int length) {
switch (myReadState) {
case READ_AUTHOR_NAME_0:
myAuthorNames[0] += new String(data, start, length);
break;
case READ_AUTHOR_NAME_1:
myAuthorNames[1] += new String(data, start, length);
break;
case READ_AUTHOR_NAME_2:
myAuthorNames[2] += new String(data, start, length);
break;
case READ_TITLE:
case READ_LANGUAGE:
case READ_GENRE:
myBuffer.append(data, start, length);
break;
}
}
public boolean readDocument(ZLFile file) {
return ZLXMLProcessor.read(this, file, 512);
}
}