1
22 package org.crosswire.jsword.book;
23
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.jdom.Content;
35 import org.jdom.Document;
36 import org.jdom.Element;
37 import org.jdom.Namespace;
38 import org.jdom.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 prevBook = books[i - 1];
180 BookCategory category = book.getBookCategory();
181
182 BookCategory prevCategory = prevBook.getBookCategory();
183 String prevName = prevBook.getInitials();
184 showDiffs[i - 1] = comparingBooks && BookCategory.BIBLE.equals(category) && category.equals(prevCategory)
185 && book.getLanguage().equals(prevBook.getLanguage()) && !book.getInitials().equals(prevName);
186
187 if (showDiffs[i - 1]) {
188 doDiffs = true;
189 StringBuilder buf = new StringBuilder(prevBook.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 lastText = "";
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 cell.setAttribute(OSISUtil.OSIS_ATTR_LANG, lang.getCode(), Namespace.XML_NAMESPACE);
221 row.addContent(cell);
222 if (iters[i].hasNext()) {
223 content = iters[i].next();
224
225 if (doDiffs) {
226 String thisText = "";
227 if (content instanceof Element) {
228 thisText = OSISUtil.getCanonicalText((Element) content);
229 } else if (content instanceof Text) {
230 thisText = ((Text) content).getText();
231 }
232
233 if (i > 0 && showDiffs[i - 1]) {
234 List<Difference> diffs = new Diff(lastText, thisText, false).compare();
235 DiffCleanup.cleanupSemantic(diffs);
236 cell.addContent(OSISUtil.diffToOsis(diffs));
237
238 cell = OSISUtil.factory().createCell();
240 lang = (Language) book.getProperty(BookMetaData.KEY_XML_LANG);
241 cell.setAttribute(OSISUtil.OSIS_ATTR_LANG, lang.getCode(), Namespace.XML_NAMESPACE);
242 row.addContent(cell);
243 }
244 lastText = thisText;
245 }
246 cell.addContent(content);
247 cellCount++;
248 }
249 }
250
251 if (cellCount == 0) {
252 break;
253 }
254
255 table.addContent(row);
256 rowCount++;
257 }
258 if (rowCount > 0) {
259 div.addContent(table);
260 }
261 }
262
263 return div;
264 }
265
266
269 private Key key;
270
271
274 private Book[] books;
275
276
279 private boolean comparingBooks;
280
281
284 private Element osis;
285
286
289 private Element fragment;
290 }
291