Source code: com/eireneh/bible/book/RefEle.java
1
2 package com.eireneh.bible.book;
3
4 import java.util.*;
5 import java.io.*;
6
7 import org.w3c.dom.Document;
8 import org.w3c.dom.Element;
9 import org.w3c.dom.Node;
10 import org.w3c.dom.NodeList;
11
12 import org.xml.sax.Parser;
13 import org.xml.sax.HandlerBase;
14 import org.xml.sax.InputSource;
15 import org.xml.sax.SAXException;
16
17 import org.apache.xerces.dom.*;
18 import org.apache.xerces.parsers.SAXParser;
19
20 import com.eireneh.util.*;
21 import com.eireneh.bible.passage.*;
22
23 /**
24 * A VerseElement represents a Verse that exists inside a BibleEle.
25 *
26 * <table border='1' cellPadding='3' cellSpacing='0' width="100%">
27 * <tr><td bgColor='white'class='TableRowColor'><font size='-7'>
28 * Distribution Licence:<br />
29 * Project B is free software; you can redistribute it
30 * and/or modify it under the terms of the GNU General Public License,
31 * version 2 as published by the Free Software Foundation.<br />
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35 * General Public License for more details.<br />
36 * The License is available on the internet
37 * <a href='http://www.gnu.org/copyleft/gpl.html'>here</a>, by writing to
38 * <i>Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
39 * MA 02111-1307, USA</i>, Or locally at the Licence link below.<br />
40 * The copyright to this program is held by it's authors.
41 * </font></td></tr></table>
42 * @see <a href='http://www.eireneh.com/servlets/Web'>Project B Home</a>
43 * @see docs.Licence
44 * @author Joe Walker
45 * @version D5.I5.T0
46 */
47 public class RefEle
48 {
49 /**
50 * Create a RefEle
51 * @param doc The BibleEle that we are a part of
52 * @param title The title of this section
53 * @param para Is this verse at the start of a new paragraph
54 * @param xml The XML text that need to be parse and added in
55 */
56 public RefEle(SectionEle section, Verse verse, boolean para) throws BookException
57 {
58 this.section = section;
59 this.doc = section.getParent();
60 this.verse = verse;
61 this.xml = xml;
62 this.para = para;
63
64 this.ref = doc.getDocument().createElement("ref");
65
66 ref.setAttribute("b", ""+verse.getBook());
67 ref.setAttribute("c", ""+verse.getChapter());
68 ref.setAttribute("v", ""+verse.getVerse());
69
70 if (para) ref.setAttribute("para", ""+para);
71 }
72
73 /**
74 * Accessor for our parent Element
75 * @return The parent SectionElement
76 */
77 public SectionEle getParent()
78 {
79 return section;
80 }
81
82 /**
83 * Accessor for the Element that we are wrapping
84 * @return The Element that we wrap
85 */
86 public Document getDocument()
87 {
88 return doc.getDocument();
89 }
90
91 /**
92 * Accessor for the Element that we are wrapping
93 * @return The Element that we wrap
94 */
95 public Element getElement()
96 {
97 return ref;
98 }
99
100 /**
101 * Get the verse that this element contains
102 * @param The verse
103 */
104 public Verse getVerse()
105 {
106 return verse;
107 }
108
109 /**
110 * Add some plain text to the verse
111 */
112 public void setPlainText(String text)
113 {
114 Element it = doc.getDocument().createElement("it");
115 it.appendChild(doc.getDocument().createTextNode(text));
116 ref.appendChild(it);
117 }
118
119 /**
120 * Add XML markup to the verse
121 * @param xml The markup to add
122 */
123 public void setXMLText(String xml) throws SAXException
124 {
125 // First we remove the old ref node:
126 Node dad = ref.getParentNode();
127 dad.removeChild(ref);
128
129 // We need to ensure that we have a single root node to be the
130 // Document node in the parse
131 String insert =
132 "<ref " +
133 " b='"+verse.getBook()+"'" +
134 " c='"+verse.getChapter()+"'" +
135 " v='"+verse.getVerse()+"'" +
136 (para ? " para='true'" : "") +
137 "><it>" +
138 xml +
139 "</it></ref>";
140
141 try
142 {
143 // The parser support classes
144 StringReader sin = new StringReader(insert);
145 InputSource is = new InputSource(sin);
146 HandlerBase handler = new DOMHandlerBase(section.getElement());
147
148 // Parsing: The official ultra portable version is:
149 // Parser parser = ParserFactory.makeParser(PARSER);
150 // However this is run-time checked. I prefer the compile
151 // time checked version which is:
152 Parser parser = new SAXParser();
153 parser.setDocumentHandler(handler);
154 parser.setErrorHandler(handler);
155 parser.parse(is);
156
157 // Find the root node that we just added
158 ref = (Element) section.getElement().getLastChild();
159 }
160 catch (IOException ex)
161 {
162 throw new SAXException("Rare in-memory IO error. System message: "+ex);
163 }
164 }
165
166 /**
167 * A simplified plain text version of the data in this verse with all
168 * the markup stripped out.
169 * @return The Bible text without markup
170 */
171 public String getPlainText()
172 {
173 StringBuffer buffer = new StringBuffer();
174 getText(buffer);
175 return buffer.toString();
176 }
177
178 /**
179 * A simplified plain text version of the data in this verse with all
180 * the markup stripped out.
181 * @return The Bible text without markup
182 */
183 public String getXMLText()
184 {
185 return xml;
186 }
187
188 /**
189 * A simplified plain text version of the data in this verse with all
190 * the markup stripped out.
191 * @return The Bible text without markup
192 */
193 public void getText(StringBuffer buffer)
194 {
195 recurseNodes(ref, buffer, 0);
196 }
197
198 /**
199 * Recurse down a Doument node tree
200 * @param node The node to dig into
201 * @param text The place to store the text that we find
202 * @param depth How far down have we gone? This is only needed if we
203 * want to uncomment the debug
204 */
205 private static void recurseNodes(Node node, StringBuffer text, int depth)
206 {
207 // String space = StringUtil.chain(depth*2, ' ');
208 // log.fine(space+"name="+node.getNodeName()+" type="+node.getNodeType()+" value="+node.getNodeValue());
209 // log.fine(space+"{");
210
211 /*
212 NamedNodeMap map = node.getAttributes();
213 if (map != null)
214 for (int i=0; i<map.getLength(); i++)
215 recurseNodes(map.item(i), text, depth+1);
216 */
217
218 if (node.getNodeType() == 3)
219 {
220 text.append(node.getNodeValue());
221 text.append(" ");
222 }
223
224 NodeList list = node.getChildNodes();
225 for (int i=0; i<list.getLength(); i++)
226 {
227 Node sub = list.item(i);
228 if (sub != null)
229 {
230 String name = sub.getNodeName();
231 if (name.equals("it") || sub.getNodeType() == 3)
232 {
233 recurseNodes(sub, text, depth+1);
234 }
235 }
236 // else log.fine("ignoring="+sub.getNodeName());
237 }
238
239 // log.fine(space+"}");
240 }
241
242 /** The document that we are a part of */
243 private BibleEle doc;
244
245 /** The Verse that we model */
246 private Verse verse;
247
248 /** Is this verse the start of a new paragraph */
249 private boolean para;
250
251 /** The current verse */
252 private Element ref;
253
254 /** The parent section */
255 private SectionEle section;
256
257 /** The formatted text */
258 private String xml;
259 }