/*
* (c) Copyright 2009 Tim Jenkins
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* ITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package com.screenrunner.data;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class Scripture extends XmlDoc {
public static Scripture fromXml(InputStream data) throws IOException, ParserConfigurationException, SAXException {
Scripture s = new Scripture();
s._doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(data);
return s;
}
private NodeList _books = null;
private String _name;
public String getBibleName() { return _name; }
public void setBibleName(String name) { _name = name; }
private Node getBookNode(int book) {
if(_books == null) {
_books = _doc.getElementsByTagName("b");
}
return ((book >= 0 && book < _books.getLength()) ? _books.item(book) : null);
}
private Node getChapterNode(int book, int chapter) {
Node n = getBookNode(book);
if(n == null) return null;
Node[] ch = getNamedChildrenWithAttributeValue(n, "c", "n", Integer.toString(chapter));
if(ch == null || ch.length == 0) return null;
return ch[0];
}
/**
* getVerseNode(int, int, int)
* Might need this in the future... but I don't know.
* Until I do need it, it's commented out.
*/
// private Node getVerseNode(int book, int chapter, int verse) {
// Node c = getChapterNode(book, chapter);
// if(c == null) return null;
// Node[] vs = getNamedChildrenWithAttributeValue(c, "v", "n", Integer.toString(verse));
// if(vs == null || vs.length == 0) return null;
// return vs[0];
// }
public String[] getBookNames() {
getBookNode(0);
String[] names = new String[_books.getLength()];
for(int i = 0; i < _books.getLength(); i++) {
Node book = _books.item(i);
Node name = book.getAttributes().getNamedItem("n");
names[i] = (name == null ? null : name.getTextContent().trim());
}
return names;
}
public String getBookName(int book) {
Node b = getBookNode(book);
if(b != null) {
Node name = b.getAttributes().getNamedItem("n");
return (name != null ? name.getTextContent().trim() : null);
}
return null;
}
public int[] getChapters(int book) {
Node b = getBookNode(book);
if(b == null) return null;
Node[] chapters = getNamedChildren(b, "c");
int[] rv = new int[chapters.length];
for(int i = 0; i < chapters.length; i++) {
Node attr = chapters[i].getAttributes().getNamedItem("n");
rv[i] = -1;
try {
rv[i] = Integer.parseInt(attr.getTextContent().toString());
} catch (NumberFormatException e) {}
}
return rv;
}
public int[] getVerses(int book, int chapter) {
Node ch = getChapterNode(book, chapter);
if(ch == null) return null;
Node[] verses = this.getNamedChildren(ch, "v");
int[] rv = new int[verses.length];
for(int i = 0; i < verses.length; i++) {
Node attr = verses[i].getAttributes().getNamedItem("n");
rv[i] = -1;
try {
rv[i] = Integer.parseInt(attr.getTextContent().toString());
} catch (NumberFormatException e) {}
}
return rv;
}
public int getIndexFromBookName(String name) {
name = name.replaceAll("\\s+", "").toLowerCase();
String[] names = getBookNames();
Vector<Integer> results = new Vector<Integer>();
for(int i = 0; i < names.length; i++) {
names[i] = names[i].replaceAll("\\s+", "").toLowerCase();
if(names[i].startsWith(name))
results.add(i);
}
if(results.size() != 1) return -1;
return results.get(0);
}
public ScriptureVerse[] getVerseText(int book, int chapter, int startVerse, int endVerse) {
Node ch = getChapterNode(book, chapter);
if(ch == null) return null;
if(startVerse > endVerse) {
// swap values
startVerse = startVerse ^ endVerse;
endVerse = startVerse ^ endVerse;
startVerse = startVerse ^ endVerse;
}
Vector<ScriptureVerse> verses = new Vector<ScriptureVerse>();
Node[] vs = getNamedChildren(ch, "v");
for(int i = 0; i < vs.length; i++) {
Node attr = vs[i].getAttributes().getNamedItem("n");
int num = -1;
if(attr != null) {
try {
num = Integer.parseInt(attr.getTextContent().trim());
} catch (NumberFormatException e) {}
}
if(num >= startVerse && num <= endVerse) {
verses.add(new ScriptureVerse(this, book, chapter, num, vs[i].getTextContent().trim()));
}
}
return verses.toArray(new ScriptureVerse[verses.size()]);
}
public ScriptureVerse[] getVerseText(String reference) {
reference = reference.toLowerCase().replaceAll("\\s+", "").trim();
Pattern pbook = Pattern.compile("^[1-3]?[a-z ]+");
Matcher m = pbook.matcher(reference);
String book = null;
int chapter = -1;
int verse = -1;
int everse = -1;
if(m.find(0)) {
book = m.group();
//System.out.println("Book: '" + book + "'");
m.usePattern(Pattern.compile("\\d+"));
if(m.find()) {
//System.out.println("Chapter: " + m.group());
chapter = Integer.parseInt(m.group());
m.usePattern(Pattern.compile(":"));
if(m.find()) {
m.usePattern(Pattern.compile("\\d+"));
if(m.find()) {
//System.out.println("Start Verse: " + m.group());
verse = Integer.parseInt(m.group());
m.usePattern(Pattern.compile("-"));
if(m.find()) {
m.usePattern(Pattern.compile("\\d+"));
if(m.find()) {
//System.out.println("To Verse: " + m.group());
everse = Integer.parseInt(m.group());
} else {
//System.out.println("To End of Chapter");
everse = -2;
}
}
}
}
}
}
if(book == null || chapter == -1) return null;
int bookid = getIndexFromBookName(book);
if(bookid == -1) return null;
if(verse == -1) {
verse = 1;
int[] vs = getVerses(bookid, chapter);
everse = vs[vs.length - 1];
}
else if(everse == -2) {
int[] vs = getVerses(bookid, chapter);
everse = vs[vs.length - 1];
}
else if(everse == -1) {
everse = verse;
}
return getVerseText(bookid, chapter, verse, everse);
}
}