Added Android code
[wl-app.git] / Android / r2-streamer / r2-parser / src / main / java / org / readium / r2_streamer / parser / NCXParser.java
1 package org.readium.r2_streamer.parser;
2
3 import org.readium.r2_streamer.model.container.Container;
4 import org.readium.r2_streamer.model.publication.EpubPublication;
5 import org.readium.r2_streamer.model.tableofcontents.TOCLink;
6
7 import org.w3c.dom.Document;
8 import org.w3c.dom.Element;
9 import org.w3c.dom.Node;
10
11 import java.util.ArrayList;
12 import java.util.List;
13
14 /**
15  * Created by gautam chibde on 31/5/17.
16  */
17
18 public class NCXParser {
19
20     private static final String TAG = NCXParser.class.getSimpleName();
21
22     public static void parseNCXFile(String ncxFile, Container container, EpubPublication publication, String rootPath) throws EpubParserException {
23         String ncxData = container.rawData(ncxFile);
24         if (ncxData == null) {
25             return; // File is missing
26         }
27         Document document = EpubParser.xmlParser(ncxData);
28         if (document == null) {
29             throw new EpubParserException("Error while parsing");
30         }
31
32         Element navMapElement = (Element) document.getElementsByTagName("navMap").item(0);
33         // Parse table of contents (toc) from ncx file
34         if (navMapElement != null) {
35             publication.tableOfContents = nodeArray(navMapElement, "navPoint", rootPath);
36         }
37
38         Element pageList = (Element) document.getElementsByTagName("pageList").item(0);
39         // Parse page list if exists from ncx file
40         if (pageList != null) {
41             publication.pageList = nodeArray(pageList, "pageTarget", rootPath);
42         }
43     }
44
45     /**
46      * Generate an array of {@link TOCLink} elements representation of the XML
47      * structure in the ncx file. Each of them possibly having children.
48      *
49      * @param elements NCX DOM element object
50      * @param type     The sub elements names (e.g. 'navPoint' for 'navMap',
51      *                 'pageTarget' for 'pageList'.
52      * @return The Object representation of the data contained in the given NCX XML element.
53      */
54     private static List<TOCLink> nodeArray(Element elements, String type, String rootPath) {
55         // The "to be returned" node array.
56         List<TOCLink> newNodeArray = new ArrayList<>();
57
58         // Find the elements of `type` in the XML element.
59         for (Node n = elements.getFirstChild(); n != null; n = n.getNextSibling()) {
60             if (n.getNodeType() == Node.ELEMENT_NODE) {
61                 Element e = (Element) n;
62                 if (e.getTagName().equalsIgnoreCase(type)) {
63                     newNodeArray.add(node(e, type, rootPath));
64                 }
65             }
66         }
67         return newNodeArray;
68     }
69
70     /**
71      * [RECURSIVE]
72      * Create a node link from the specified type element.
73      * recur if there are child elements
74      *
75      * @param element the DOM NCX file elemet
76      * @param type    The sub elements names (e.g. 'navPoint' for 'navMap',
77      *                'pageTarget' for 'pageList'.
78      * @return The generated node {@link TOCLink}.
79      */
80     private static TOCLink node(Element element, String type, String rootPath) {
81         TOCLink newNode = new TOCLink();
82
83         Element content = (Element) element.getElementsByTagName("content").item(0);
84         Element navLabel = (Element) element.getElementsByTagName("navLabel").item(0);
85         if (content != null) {
86             newNode.href = rootPath + content.getAttribute("src");
87         }
88         if (navLabel != null) {
89             Element text = (Element) navLabel.getElementsByTagName("text").item(0);
90             if (text != null) {
91                 newNode.bookTitle = text.getTextContent();
92             }
93         }
94
95         for (Node n = element.getFirstChild(); n != null; n = n.getNextSibling()) {
96             if (n.getNodeType() == Node.ELEMENT_NODE) {
97                 Element e = (Element) n;
98                 if (e.getTagName().equalsIgnoreCase(type)) {
99                     newNode.tocLinks.add(node(e, type, rootPath));
100                 }
101             }
102         }
103         return newNode;
104     }
105 }