1
21 package org.crosswire.jsword.book;
22
23 import java.util.ArrayList;
24 import java.util.Iterator;
25 import java.util.List;
26
27 import org.crosswire.common.diff.Diff;
28 import org.crosswire.common.diff.DiffCleanup;
29 import org.crosswire.common.diff.Difference;
30 import org.crosswire.common.util.Language;
31 import org.crosswire.common.xml.JDOMSAXEventProvider;
32 import org.crosswire.common.xml.SAXEventProvider;
33 import org.crosswire.jsword.passage.Key;
34 import org.jdom2.Content;
35 import org.jdom2.Document;
36 import org.jdom2.Element;
37 import org.jdom2.Namespace;
38 import org.jdom2.Text;
39
40
53 public class BookData implements BookProvider {
54
57 public BookData(Book book, Key key) {
58 assert book != null;
59 assert key != null;
60
61 this.key = key;
62
63 books = new Book[1];
64 books[0] = book;
65 }
66
67
70 public BookData(Book[] books, Key key, boolean compare) {
71 assert books != null && books.length > 0;
72 assert key != null;
73
74 this.books = books.clone();
75 this.key = key;
76 this.comparingBooks = compare;
77 }
78
79
82 public Element getOsis() throws BookException {
83 if (osis == null) {
84 osis = OSISUtil.createOsisFramework(getFirstBook().getBookMetaData());
87 Element text = osis.getChild(OSISUtil.OSIS_ELEMENT_OSISTEXT);
88 Element div = getOsisFragment();
89 text.addContent(div);
90 }
91
92 return osis;
93 }
94
95
98 public Element getOsisFragment() throws BookException {
99 if (fragment == null) {
100 fragment = getOsisContent();
101 }
102
103 return fragment;
104 }
105
106
111 public SAXEventProvider getSAXEventProvider() throws BookException {
112 Element frag = getOsisFragment();
114 Document doc = frag.getDocument();
115 if (doc == null) {
116 doc = new Document(frag);
117 }
118 return new JDOMSAXEventProvider(doc);
119 }
120
121
126 public Book[] getBooks() {
127 return books == null ? null : (Book[]) books.clone();
128 }
129
130
133 public Book getFirstBook() {
134 return books != null && books.length > 0 ? books[0] : null;
135 }
136
137
142 public Key getKey() {
143 return key;
144 }
145
146
149 public boolean isComparingBooks() {
150 return comparingBooks;
151 }
152
153 private Element getOsisContent() throws BookException {
154 Element div = OSISUtil.factory().createDiv();
155
156 if (books.length == 1) {
157 Iterator<Content> iter = books[0].getOsisIterator(key, false);
158 while (iter.hasNext()) {
159 Content content = iter.next();
160 div.addContent(content);
161 }
162 } else {
163 Element table = OSISUtil.factory().createTable();
164 Element row = OSISUtil.factory().createRow();
165 Element cell = null;
166
167 table.addContent(row);
168
169 Iterator<Content>[] iters = new Iterator[books.length];
170 boolean[] showDiffs = new boolean[books.length - 1];
171 boolean doDiffs = false;
172
173 for (int i = 0; i < books.length; i++) {
174 Book book = books[i];
175
176 cell = OSISUtil.factory().createHeaderCell();
177
178 if (i > 0) {
179 Book firstBook = books[0];
180 BookCategory category = book.getBookCategory();
181
182 BookCategory prevCategory = firstBook.getBookCategory();
183 String prevName = firstBook.getInitials();
184 showDiffs[i - 1] = comparingBooks && BookCategory.BIBLE.equals(category) && category.equals(prevCategory)
185 && book.getLanguage().equals(firstBook.getLanguage()) && !book.getInitials().equals(prevName);
186
187 if (showDiffs[i - 1]) {
188 doDiffs = true;
189 StringBuilder buf = new StringBuilder(firstBook.getInitials());
190 buf.append(" ==> ");
191 buf.append(book.getInitials());
192
193 cell.addContent(OSISUtil.factory().createText(buf.toString()));
194 row.addContent(cell);
195 cell = OSISUtil.factory().createHeaderCell();
196 }
197 }
198
199 cell.addContent(OSISUtil.factory().createText(book.getInitials()));
200 row.addContent(cell);
201
202 iters[i] = book.getOsisIterator(key, true);
203 }
204
205 Content content = null;
206
207 int cellCount = 0;
208 int rowCount = 0;
209 while (true) {
210 cellCount = 0;
211
212 row = OSISUtil.factory().createRow();
213
214 String firstText = "";
215
216 for (int i = 0; i < iters.length; i++) {
217 Book book = books[i];
218 cell = OSISUtil.factory().createCell();
219 Language lang = (Language) book.getProperty(BookMetaData.KEY_XML_LANG);
220 if (lang != null) {
221 cell.setAttribute(OSISUtil.OSIS_ATTR_LANG, lang.getCode(), Namespace.XML_NAMESPACE);
222 }
223
224 row.addContent(cell);
225
226 StringBuilder newText = new StringBuilder(doDiffs ? 32 : 0);
227
228 if (iters[i].hasNext()) {
229 List<Content> contents = new ArrayList<Content>(1);
230
231 do {
232 content = iters[i].next();
233 contents.add(content);
234 addText(doDiffs, newText, content);
235 } while (!isNextVerse(content));
236
237 if (doDiffs) {
238 String thisText = newText.toString();
239 if (unaccenter != null) {
240 thisText = unaccenter.unaccent(thisText);
241 }
242
243 if (i > 0 && showDiffs[i - 1]) {
244 List<Difference> diffs = new Diff(firstText, thisText, false).compare();
245 DiffCleanup.cleanupSemantic(diffs);
246 cell.addContent(OSISUtil.diffToOsis(diffs));
247
248 cell = OSISUtil.factory().createCell();
250 lang = (Language) book.getProperty(BookMetaData.KEY_XML_LANG);
251 cell.setAttribute(OSISUtil.OSIS_ATTR_LANG, lang.getCode(), Namespace.XML_NAMESPACE);
252 row.addContent(cell);
253 }
254 if (i == 0) {
255 firstText = thisText;
256 }
257 }
258 cell.addContent(contents);
259 cellCount++;
260 }
261 }
262
263 if (cellCount == 0) {
264 break;
265 }
266
267 table.addContent(row);
268 rowCount++;
269 }
270 if (rowCount > 0) {
271 div.addContent(table);
272 }
273 }
274
275 return div;
276 }
277
278 private boolean isNextVerse(Content content) {
279 if (content instanceof Element) {
280 return OSISUtil.OSIS_ELEMENT_VERSE.equals(((Element) content).getName());
281 }
282
283 return false;
284 }
285
286 private void addText(boolean doDiffs, StringBuilder newText, Content content) {
287 if (doDiffs) {
288 if (newText.length() != 0) {
290 newText.append(' ');
291 }
292
293 if (content instanceof Element) {
294 newText.append(OSISUtil.getCanonicalText((Element) content));
295 } else if (content instanceof Text) {
296 newText.append(((Text) content).getText());
297 }
298 }
299 }
300
301
304 public void setUnaccenter(UnAccenter unaccenter) {
305 this.unaccenter = unaccenter;
306 }
307
308
311 private Key key;
312
313
316 private Book[] books;
317
318
321 private boolean comparingBooks;
322
323
326 private Element osis;
327
328
331 private Element fragment;
332
333 private UnAccenter unaccenter;
334 }
335