/*
* 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.oeb;
import java.util.*;
import org.geometerplus.zlibrary.core.constants.XMLNamespaces;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.xml.*;
import org.geometerplus.fbreader.library.Book;
class OEBMetaInfoReader extends ZLXMLReaderAdapter implements XMLNamespaces {
private final Book myBook;
private String myDCMetadataTag = "dc-metadata";
private String myMetadataTag = "metadata";
private String myOpfMetadataTag = "metadata";
private String myMetadataTagRealName;
private String myTitleTag;
private String myAuthorTag;
private String mySubjectTag;
private String myLanguageTag;
private String myMetaTag = "meta";
private String mySeriesTitle = "";
private int mySeriesIndex = 0;
private final ArrayList<String> myAuthorList = new ArrayList<String>();
private final ArrayList<String> myAuthorList2 = new ArrayList<String>();
OEBMetaInfoReader(Book book) {
myBook = book;
myBook.setTitle(null);
myBook.setLanguage(null);
}
boolean readMetaInfo(ZLFile file) {
myReadMetaData = false;
myReadState = READ_NONE;
if (!ZLXMLProcessor.read(this, file, 512)) {
return false;
}
final ArrayList<String> authors = myAuthorList.isEmpty() ? myAuthorList2 : myAuthorList;
for (String a : authors) {
final int index = a.indexOf(',');
if (index >= 0) {
a = a.substring(index + 1).trim() + ' ' + a.substring(0, index).trim();
} else {
a = a.trim();
}
myBook.addAuthor(a);
}
return true;
}
private static final int READ_NONE = 0;
private static final int READ_AUTHOR = 1;
private static final int READ_AUTHOR2 = 2;
private static final int READ_TITLE = 3;
private static final int READ_SUBJECT = 4;
private static final int READ_LANGUAGE = 5;
private int myReadState;
private boolean myReadMetaData;
private final StringBuilder myBuffer = new StringBuilder();
@Override
public boolean processNamespaces() {
return true;
}
@Override
public void namespaceMapChangedHandler(Map<String,String> namespaceMap) {
myTitleTag = null;
myAuthorTag = null;
mySubjectTag = null;
myLanguageTag = null;
myOpfMetadataTag = "metadata";
for (Map.Entry<String,String> entry : namespaceMap.entrySet()) {
final String id = entry.getValue();
if (id.startsWith(DublinCorePrefix) || id.startsWith(DublinCoreLegacyPrefix)) {
final String name = entry.getKey();
myTitleTag = (name + ":title").intern();
myAuthorTag = (name + ":creator").intern();
mySubjectTag = (name + ":subject").intern();
myLanguageTag = (name + ":language").intern();
} else if (id.equals(OpenPackagingFormat)) {
final String name = entry.getKey();
myOpfMetadataTag = (name + ":metadata").intern();
}
}
}
@Override
public boolean startElementHandler(String tag, ZLStringMap attributes) {
tag = tag.toLowerCase().intern();
if (tag == myMetadataTag || tag == myDCMetadataTag || tag == myOpfMetadataTag) {
myMetadataTagRealName = tag;
myReadMetaData = true;
} else if (myReadMetaData) {
if (tag == myTitleTag) {
myReadState = READ_TITLE;
} else if (tag == myAuthorTag) {
final String role = attributes.getValue("role");
if (role == null) {
myReadState = READ_AUTHOR2;
} else if (role.equals("aut")) {
myReadState = READ_AUTHOR;
}
} else if (tag == mySubjectTag) {
myReadState = READ_SUBJECT;
} else if (tag == myLanguageTag) {
myReadState = READ_LANGUAGE;
} else if (tag == myMetaTag) {
if (attributes.getValue("name").equals("calibre:series")) {
mySeriesTitle = attributes.getValue("content");
} else if (attributes.getValue("name").equals("calibre:series_index")) {
final String strIndex = attributes.getValue("content");
try {
mySeriesIndex = Integer.parseInt(strIndex);
} catch (NumberFormatException e) {
}
}
}
}
return false;
}
@Override
public void characterDataHandler(char[] data, int start, int len) {
switch (myReadState) {
case READ_NONE:
break;
case READ_AUTHOR:
case READ_AUTHOR2:
case READ_TITLE:
case READ_SUBJECT:
case READ_LANGUAGE:
myBuffer.append(data, start, len);
break;
}
}
@Override
public boolean endElementHandler(String tag) {
tag = tag.toLowerCase();
if (tag.equals(myMetadataTagRealName)) {
return true;
}
String bufferContent = myBuffer.toString().trim();
if (bufferContent.length() != 0) {
switch (myReadState) {
case READ_TITLE:
myBook.setTitle(bufferContent);
break;
case READ_AUTHOR:
myAuthorList.add(bufferContent);
break;
case READ_AUTHOR2:
myAuthorList2.add(bufferContent);
break;
case READ_SUBJECT:
myBook.addTag(bufferContent);
break;
case READ_LANGUAGE:
{
int index = bufferContent.indexOf('_');
if (index >= 0) {
bufferContent = bufferContent.substring(0, index);
}
index = bufferContent.indexOf('-');
if (index >= 0) {
bufferContent = bufferContent.substring(0, index);
}
myBook.setLanguage("cz".equals(bufferContent) ? "cs" : bufferContent);
}
break;
}
} else {
if (tag.equals(myMetaTag)) {
if (!mySeriesTitle.equals("") && mySeriesIndex > 0) {
myBook.setSeriesInfo(mySeriesTitle, mySeriesIndex);
}
}
}
myBuffer.delete(0, myBuffer.length());
myReadState = READ_NONE;
return false;
}
}