package com.dteviot.epubviewer.epub;
import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import com.dteviot.epubviewer.HrefResolver;
import android.content.Intent;
import android.sax.Element;
import android.sax.EndElementListener;
import android.sax.EndTextElementListener;
import android.sax.RootElement;
import android.sax.StartElementListener;
/*
* The TableOfContents part of the epub
*/
public class TableOfContents {
private static final String XML_NAMESPACE_TABLE_OF_CONTENTS = "http://www.daisy.org/z3986/2005/ncx/";
private static final String XML_ELEMENT_NCX = "ncx";
private static final String XML_ELEMENT_NAVMAP = "navMap";
private static final String XML_ELEMENT_NAVPOINT = "navPoint";
private static final String XML_ELEMENT_NAVLABEL = "navLabel";
private static final String XML_ELEMENT_TEXT = "text";
private static final String XML_ELEMENT_CONTENT = "content";
private static final String XML_ATTRIBUTE_PLAYORDER = "playOrder";
private static final String XML_ATTRIBUTE_SCR = "src";
private ArrayList<NavPoint> mNavPoints;
private int mCurrentDepth = 0;
private int mSupportedDepth = 1;
private HrefResolver mHrefResolver = null;
public TableOfContents() {
mNavPoints = new ArrayList<NavPoint>();
}
/*
* Unpacks contents from a bundle
*/
public TableOfContents(Intent intent, String key) {
mNavPoints = intent.getParcelableArrayListExtra(key);
}
public void add(NavPoint navPoint) {
mNavPoints.add(navPoint);
}
public void clear() {
mNavPoints.clear();
}
public NavPoint get(int index) {
return mNavPoints.get(index);
}
/*
* Used to fetch the last item we're building
*/
public NavPoint getLatestPoint() {
return mNavPoints.get(mNavPoints.size() - 1);
}
public int size() {
return mNavPoints.size();
}
/*
* Packs this into an intent
*/
public void pack(Intent intent, String key) {
intent.putExtra(key, mNavPoints);
}
/*
* build parser to parse the "Table of Contents" file,
* @return parser
*/
public ContentHandler constructTocFileParser(HrefResolver resolver) {
RootElement root = new RootElement(XML_NAMESPACE_TABLE_OF_CONTENTS, XML_ELEMENT_NCX);
Element navMap = root.getChild(XML_NAMESPACE_TABLE_OF_CONTENTS, XML_ELEMENT_NAVMAP);
Element navPoint = navMap.getChild(XML_NAMESPACE_TABLE_OF_CONTENTS, XML_ELEMENT_NAVPOINT);
mHrefResolver = resolver;
AddNavPointToParser(navPoint);
return root.getContentHandler();
}
// Build up code to parse a ToC NavPoint
private void AddNavPointToParser(final Element navPoint) {
Element navLabel = navPoint.getChild(XML_NAMESPACE_TABLE_OF_CONTENTS, XML_ELEMENT_NAVLABEL);
Element text = navLabel.getChild(XML_NAMESPACE_TABLE_OF_CONTENTS, XML_ELEMENT_TEXT);
Element content = navPoint.getChild(XML_NAMESPACE_TABLE_OF_CONTENTS, XML_ELEMENT_CONTENT);
navPoint.setStartElementListener(new StartElementListener(){
public void start(Attributes attributes) {
add(new NavPoint(attributes.getValue(XML_ATTRIBUTE_PLAYORDER)));
// extend parser to handle another level of nesting if required
if (mSupportedDepth == ++mCurrentDepth) {
Element child = navPoint.getChild(XML_NAMESPACE_TABLE_OF_CONTENTS, XML_ELEMENT_NAVPOINT);
AddNavPointToParser(child);
++mSupportedDepth;
}
}
});
text.setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
getLatestPoint().setNavLabel(body);
}
});
content.setStartElementListener(new StartElementListener(){
public void start(Attributes attributes) {
getLatestPoint().setContent(mHrefResolver.ToAbsolute(attributes.getValue(XML_ATTRIBUTE_SCR)));
}
});
navPoint.setEndElementListener(new EndElementListener(){
public void end() {
--mCurrentDepth;
}
});
}
}