1
20 package org.crosswire.jsword.book.basic;
21
22 import java.util.HashSet;
23 import java.util.Iterator;
24 import java.util.LinkedHashSet;
25 import java.util.List;
26 import java.util.Set;
27
28 import org.crosswire.common.util.StringUtil;
29 import org.crosswire.jsword.book.BookData;
30 import org.crosswire.jsword.book.BookException;
31 import org.crosswire.jsword.book.BookMetaData;
32 import org.crosswire.jsword.book.OSISUtil;
33 import org.crosswire.jsword.book.filter.SourceFilter;
34 import org.crosswire.jsword.book.sword.Backend;
35 import org.crosswire.jsword.book.sword.processing.RawTextToXmlProcessor;
36 import org.crosswire.jsword.passage.Key;
37 import org.crosswire.jsword.passage.KeyUtil;
38 import org.crosswire.jsword.passage.NoSuchKeyException;
39 import org.crosswire.jsword.passage.Passage;
40 import org.crosswire.jsword.passage.PassageKeyFactory;
41 import org.crosswire.jsword.passage.RestrictionType;
42 import org.crosswire.jsword.passage.Verse;
43 import org.crosswire.jsword.passage.VerseKey;
44 import org.crosswire.jsword.passage.VerseRange;
45 import org.crosswire.jsword.versification.BibleBook;
46 import org.crosswire.jsword.versification.Versification;
47 import org.crosswire.jsword.versification.VersificationsMapper;
48 import org.crosswire.jsword.versification.system.Versifications;
49 import org.jdom2.Content;
50 import org.jdom2.Element;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54
62 public abstract class AbstractPassageBook extends AbstractBook {
63
64
70 public AbstractPassageBook(BookMetaData bmd, Backend backend) {
71 super(bmd, backend);
72 keyf = PassageKeyFactory.instance();
73 this.versification = bmd.getProperty(BookMetaData.KEY_VERSIFICATION);
74 }
75
76
79 public Iterator<Content> getOsisIterator(final Key key, final boolean allowEmpty, final boolean allowGenTitles) throws BookException {
80 final SourceFilter filter = getFilter();
83
84 Passage ref = VersificationsMapper.instance().map(KeyUtil.getPassage(key), this.getVersification());
89
90 final boolean showTitles = ref.hasRanges(RestrictionType.CHAPTER) || (!allowEmpty && allowGenTitles);
94
95 RawTextToXmlProcessor processor = new RawTextToXmlProcessor() {
96 private String previousVerseText = "";
98
99 public void preRange(VerseRange range, List<Content> partialDom) {
100 if (showTitles) {
101 Element title = OSISUtil.factory().createGeneratedTitle();
102 title.addContent(range.getName());
103 partialDom.add(title);
104 }
105 }
106
107 public void postVerse(Key verse, List<Content> partialDom, String rawText) {
108 if ((allowEmpty || rawText.length() > 0) && !previousVerseText.equals(rawText)) {
110 List<Content> osisContent = filter.toOSIS(AbstractPassageBook.this, verse, rawText);
111 addOSIS(verse, partialDom, osisContent);
112 }
113 previousVerseText = rawText;
114 }
115
116 public void init(List<Content> partialDom) {
117 }
119 };
120
121 return getOsis(ref, processor).iterator();
122 }
123
124
133 public void addOSIS(Key key, Element div, List<Content> osisContent) {
134 assert key != null;
135 div.addContent(osisContent);
136 }
137
138
146 public void addOSIS(Key key, List<Content> content, List<Content> osisContent) {
147 assert key != null;
148 content.addAll(osisContent);
149 }
150
151
158 protected abstract SourceFilter getFilter();
159
160
167 public void setDocument(Key key, BookData bdata) throws BookException {
168 for (Content nextElem : OSISUtil.getFragment(bdata.getOsisFragment())) {
170 if (nextElem instanceof Element) {
171 Element div = (Element) nextElem;
172
173 for (Content data : div.getContent()) {
175 if (data instanceof Element) {
176 Element overse = (Element) data;
177 String text = OSISUtil.getPlainText(overse);
178
179 setRawText(key, text);
180 } else {
181 log.error("Ignoring non OSIS/Verse content of DIV.");
182 }
183 }
184 } else {
185 log.error("Ignoring non OSIS/Verse content of DIV.");
186 }
187 }
188 }
189
190
193 public boolean isWritable() {
194 return false;
195 }
196
197
200 public final Key createEmptyKeyList() {
201 return keyf.createEmptyKeyList(Versifications.instance().getVersification(versification));
202 }
203
204
205
208 public Key getValidKey(String name) {
209 try {
210 return getKey(name);
211 } catch (NoSuchKeyException e) {
212 return createEmptyKeyList();
213 }
214 }
215
216
219 public final Key getKey(String text) throws NoSuchKeyException {
220 return PassageKeyFactory.instance().getKey(Versifications.instance().getVersification(versification), text);
221 }
222
223 public Versification getVersification() {
224 if (this.versificationSystem == null) {
225 this.versificationSystem = Versifications.instance().getVersification(getBookMetaData().getProperty(BookMetaData.KEY_VERSIFICATION));
226 }
227 return versificationSystem;
228 }
229
230
235 public Set<BibleBook> getBibleBooks() {
236 if (bibleBooks == null) {
237 synchronized (this) {
238 if (bibleBooks == null) {
239 bibleBooks = getBibleBooksInternal();
240 }
241 }
242 }
243
244 return bibleBooks;
245 }
246
247
251 private Set<BibleBook> getBibleBooksInternal() {
252 String list = this.getBookMetaData().getProperty(BookMetaData.KEY_BOOKLIST);
253 Set<BibleBook> books;
254 if (list == null) {
255 books = calculateBibleBookList();
257 String listOfBooks = toString(books);
258 this.putProperty(BookMetaData.KEY_BOOKLIST, listOfBooks);
259 } else {
260 books = fromString(list);
262 }
263
264 return books;
265 }
266
267 private Set<BibleBook> fromString(String list) {
268 Set<BibleBook> books = new LinkedHashSet<BibleBook>(list.length() / 2);
269 final String[] bookOsis = StringUtil.split(list, ' ');
270 for (String s : bookOsis) {
271 books.add(BibleBook.fromExactOSIS(s));
272 }
273 return books;
274 }
275
276 private String toString(Set<BibleBook> books) {
277 StringBuilder sb = new StringBuilder(books.size() * 8);
278 for (Iterator<BibleBook> iterator = books.iterator(); iterator.hasNext(); ) {
279 BibleBook b = iterator.next();
280 sb.append(b.getOSIS());
281 if (iterator.hasNext()) {
282 sb.append(' ');
283 }
284
285 }
286 return sb.toString();
287 }
288
289
292 private Set<BibleBook> calculateBibleBookList() {
293 final BookMetaData bookMetaData = this.getBookMetaData();
294 final VerseKey scope = (VerseKey) getScope();
295 if (scope == null) {
296 return new HashSet<BibleBook>();
297 }
298
299 final Set<BibleBook> bookList = new LinkedHashSet<BibleBook>();
300
301 final Versification v11n = Versifications.instance().getVersification(bookMetaData.getProperty(BookMetaData.KEY_VERSIFICATION));
303 final Iterator<BibleBook> v11nBookIterator = v11n.getBookIterator();
304
305 while (v11nBookIterator.hasNext()) {
306 BibleBook bibleBook = v11nBookIterator.next();
307 if (scope.contains(new Verse(v11n, bibleBook, 1, 1))
309 || scope.contains(new Verse(v11n, bibleBook, 1, 2)))
310 {
311 bookList.add(bibleBook);
312 }
313 }
314
315 return bookList;
316 }
317
318
321 private String versification;
322
323
326 private Versification versificationSystem;
327
328
331 private PassageKeyFactory keyf;
332
333
336 private volatile Set<BibleBook> bibleBooks;
337
338
341 private static final Logger log = LoggerFactory.getLogger(AbstractPassageBook.class);
342
343 }
344