| APIExamples.java |
1 /**
2 * Distribution License:
3 * JSword is free software; you can redistribute it and/or modify it under
4 * the terms of the GNU Lesser General Public License, version 2.1 as published by
5 * the Free Software Foundation. This program is distributed in the hope
6 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
7 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8 * See the GNU Lesser General Public License for more details.
9 *
10 * The License is available on the internet at:
11 * http://www.gnu.org/copyleft/lgpl.html
12 * or by writing to:
13 * Free Software Foundation, Inc.
14 * 59 Temple Place - Suite 330
15 * Boston, MA 02111-1307, USA
16 *
17 * Copyright: 2005
18 * The copyright to this program is held by it's authors.
19 *
20 * ID: $Id: APIExamples.java 1890 2008-07-09 12:15:15Z dmsmith $
21 */
22 package org.crosswire.jsword.examples;
23
24 import java.net.URL;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28
29 import javax.xml.transform.TransformerException;
30
31 import org.crosswire.common.util.NetUtil;
32 import org.crosswire.common.util.ResourceUtil;
33 import org.crosswire.common.xml.Converter;
34 import org.crosswire.common.xml.SAXEventProvider;
35 import org.crosswire.common.xml.TransformingSAXEventProvider;
36 import org.crosswire.common.xml.XMLUtil;
37 import org.crosswire.jsword.book.Book;
38 import org.crosswire.jsword.book.BookCategory;
39 import org.crosswire.jsword.book.BookData;
40 import org.crosswire.jsword.book.BookException;
41 import org.crosswire.jsword.book.BookFilter;
42 import org.crosswire.jsword.book.BookFilters;
43 import org.crosswire.jsword.book.BookMetaData;
44 import org.crosswire.jsword.book.Books;
45 import org.crosswire.jsword.book.BooksEvent;
46 import org.crosswire.jsword.book.BooksListener;
47 import org.crosswire.jsword.book.OSISUtil;
48 import org.crosswire.jsword.book.install.InstallException;
49 import org.crosswire.jsword.book.install.InstallManager;
50 import org.crosswire.jsword.book.install.Installer;
51 import org.crosswire.jsword.index.search.DefaultSearchModifier;
52 import org.crosswire.jsword.index.search.DefaultSearchRequest;
53 import org.crosswire.jsword.passage.Key;
54 import org.crosswire.jsword.passage.NoSuchKeyException;
55 import org.crosswire.jsword.passage.Passage;
56 import org.crosswire.jsword.passage.PassageTally;
57 import org.crosswire.jsword.passage.RestrictionType;
58 import org.crosswire.jsword.util.ConverterFactory;
59 import org.xml.sax.SAXException;
60
61 /**
62 * All the methods in this class highlight some are of the API and how to use it.
63 *
64 * @see gnu.lgpl.License for license details.
65 * The copyright to this program is held by it's authors.
66 * @author Joe Walker [joe at eireneh dot com]
67 */
68 public class APIExamples
69 {
70 /**
71 * The name of a Bible to find
72 */
73 private static final String BIBLE_NAME = "KJV"; //$NON-NLS-1$
74
75 /**
76 * Get a particular installed book by initials.
77 *
78 * @param bookInitials The book name to search for
79 * @return The found book. Null otherwise.
80 */
81 public Book getBook(String bookInitials)
82 {
83 return Books.installed().getBook(bookInitials);
84 }
85
86 /**
87 * Get just the canonical text of one or more book entries without any markup.
88 *
89 * @param bookInitials the book to use
90 * @param reference a reference, appropriate for the book, of one or more entries
91 */
92 public String getPlainText(String bookInitials, String reference) throws BookException, NoSuchKeyException
93 {
94 Book book = getBook(bookInitials);
95 if (book == null)
96 {
97 return ""; //$NON-NLS-1$
98 }
99
100 Key key = book.getKey(reference);
101 BookData data = new BookData(book, key);
102 return OSISUtil.getCanonicalText(data.getOsisFragment());
103 }
104
105 /**
106 * Obtain a SAX event provider for the OSIS document representation of one or more book entries.
107 *
108 * @param bookInitials the book to use
109 * @param reference a reference, appropriate for the book, of one or more entries
110 */
111 public SAXEventProvider getOSIS(String bookInitials, String reference, int maxKeyCount) throws BookException, NoSuchKeyException
112 {
113 if (bookInitials == null || reference == null)
114 {
115 return null;
116 }
117
118 Book book = getBook(bookInitials);
119
120 Key key = null;
121 if (BookCategory.BIBLE.equals(book.getBookCategory()))
122 {
123 key = book.getKey(reference);
124 ((Passage) key).trimVerses(maxKeyCount);
125 }
126 else
127 {
128 key = book.createEmptyKeyList();
129
130 Iterator iter = book.getKey(reference).iterator();
131 int count = 0;
132 while (iter.hasNext())
133 {
134 if (++count >= maxKeyCount)
135 {
136 break;
137 }
138 key.addAll((Key) iter.next());
139 }
140 }
141
142 BookData data = new BookData(book, key);
143
144 return data.getSAXEventProvider();
145 }
146
147 /**
148 * Obtain styled text (in this case HTML) for a book reference.
149 *
150 * @param bookInitials the book to use
151 * @param reference a reference, appropriate for the book, of one or more entries
152 * @return the styled text
153 * @see Book
154 * @see SAXEventProvider
155 */
156 public String readStyledText(String bookInitials, String reference, int maxKeyCount) throws NoSuchKeyException, BookException, TransformerException, SAXException
157 {
158 Book book = getBook(bookInitials);
159 SAXEventProvider osissep = getOSIS(bookInitials, reference, maxKeyCount);
160 if (osissep == null)
161 {
162 return ""; //$NON-NLS-1$
163 }
164
165 Converter styler = ConverterFactory.getConverter();
166
167 TransformingSAXEventProvider htmlsep = (TransformingSAXEventProvider) styler.convert(osissep);
168
169 // You can also pass parameters to the XSLT. What you pass depends upon what the XSLT can use.
170 BookMetaData bmd = book.getBookMetaData();
171 boolean direction = bmd.isLeftToRight();
172 htmlsep.setParameter("direction", direction ? "ltr" : "rtl"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
173
174 // Finally you can get the styled text.
175 return XMLUtil.writeToString(htmlsep);
176 }
177
178 /**
179 * While Bible and Commentary are very similar, a Dictionary is read in a
180 * slightly different way. It is also worth looking at the JavaDoc for
181 * Book that has a way of treating Bible, Commentary and Dictionary the same.
182 * @see Book
183 */
184 public void readDictionary() throws BookException
185 {
186 // This just gets a list of all the known dictionaries and picks the
187 // first. In a real world app you will probably have a better way
188 // of doing this.
189 List dicts = Books.installed().getBooks(BookFilters.getDictionaries());
190 Book dict = (Book) dicts.get(0);
191
192 // If I want every key in the Dictionary then I do this (or something
193 // like it - in the real world you want to call hasNext() on an iterator
194 // before next() but the point is the same:
195 Key keys = dict.getGlobalKeyList();
196 Key first = (Key) keys.iterator().next();
197
198 System.out.println("The first Key in the default dictionary is " + first); //$NON-NLS-1$
199
200 BookData data = new BookData(dict, first);
201 System.out.println("And the text against that key is " + OSISUtil.getPlainText(data.getOsisFragment())); //$NON-NLS-1$
202 }
203
204 /**
205 * An example of how to search for various bits of data.
206 */
207 public void search() throws BookException
208 {
209 Book bible = Books.installed().getBook(BIBLE_NAME);
210
211 // This does a standard operator search. See the search documentation
212 // for more examples of how to search
213 Key key = bible.find("+moses +aaron"); //$NON-NLS-1$
214
215 System.out.println("The following verses contain both moses and aaron: " + key.getName()); //$NON-NLS-1$
216
217 // You can also trim the result to a more manageable quantity.
218 // The test here is not necessary since we are working with a bible. It is necessary if we don't know what it is.
219 if (key instanceof Passage)
220 {
221 Passage remaining = ((Passage) key).trimVerses(5);
222 System.out.println("The first 5 verses containing both moses and aaron: " + key.getName()); //$NON-NLS-1$
223 System.out.println("The rest of the verses are: " + remaining.getName()); //$NON-NLS-1$
224 }
225 }
226
227 /**
228 * An example of how to perform a ranked search.
229 * @throws BookException
230 */
231 void rankedSearch() throws BookException
232 {
233 Book bible = Books.installed().getBook(BIBLE_NAME);
234
235 // For a more complex example:
236 // Rank the verses and show the first 20
237 boolean rank = true;
238
239 DefaultSearchModifier modifier = new DefaultSearchModifier();
240 modifier.setRanked(rank);
241
242 Key results = bible.find(new DefaultSearchRequest("for god so loved the world", modifier)); //$NON-NLS-1$
243 int total = results.getCardinality();
244 int partial = total;
245
246 // we get PassageTallys for rank searches
247 if (results instanceof PassageTally || rank)
248 {
249 PassageTally tally = (PassageTally) results;
250 tally.setOrdering(PassageTally.ORDER_TALLY);
251 int rankCount = 20;
252 if (rankCount > 0 && rankCount < total)
253 {
254 // Here we are trimming by ranges, where a range is a set of continuous verses.
255 tally.trimRanges(rankCount, RestrictionType.NONE);
256 partial = rankCount;
257 }
258 }
259 System.out.println("Showing the first " + partial + " of " + total + " verses."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
260 System.out.println(results);
261 }
262
263 /**
264 * An example of how to do a search and then get text for each range of verses.
265 * @throws BookException
266 * @throws SAXException
267 */
268 void searchAndShow() throws BookException, SAXException
269 {
270 Book bible = Books.installed().getBook(BIBLE_NAME);
271
272 // Search for words like Melchezedik
273 Key key = bible.find("melchesidec~"); //$NON-NLS-1$
274
275 // Here is an example of how to iterate over the ranges and get the text for each
276 // The key's iterator would have iterated over verses.
277
278 // The following shows how to use a stylesheet of your own choosing
279 String path = "xsl/cswing/simple.xsl"; //$NON-NLS-1$
280 URL xslurl = ResourceUtil.getResource(path);
281
282 Iterator rangeIter = ((Passage) key).rangeIterator(RestrictionType.CHAPTER); // Make ranges break on chapter boundaries.
283 while (rangeIter.hasNext())
284 {
285 Key range = (Key) rangeIter.next();
286 BookData data = new BookData(bible, range);
287 SAXEventProvider osissep = data.getSAXEventProvider();
288 SAXEventProvider htmlsep = new TransformingSAXEventProvider(NetUtil.toURI(xslurl), osissep);
289 String text = XMLUtil.writeToString(htmlsep);
290 System.out.println("The html text of " + range.getName() + " is " + text); //$NON-NLS-1$ //$NON-NLS-2$
291 }
292 }
293
294 /**
295 * This is an example of the different ways to select a Book from the
296 * selection available.
297 * @see org.crosswire.common.config.Config
298 * @see Books
299 */
300 public void pickBible()
301 {
302 // The Default Bible - JSword does everything it can to make this work
303 Book book = Books.installed().getBook(BIBLE_NAME);
304
305 // And you can find out more too:
306 System.out.println(book.getLanguage());
307
308 // If you want a greater selection of Books:
309 List books = Books.installed().getBooks();
310 book = (Book) books.get(0);
311
312 // Or you can narrow the range a bit
313 books = Books.installed().getBooks(BookFilters.getOnlyBibles());
314 book = (Book) books.get(0);
315
316 // There are implementations of BookFilter for all sorts of things in
317 // the BookFilters class
318
319 // If you are wanting to get really fancy you can implement your own
320 // BookFilter easily
321 List test = Books.installed().getBooks(new MyBookFilter("ESV")); //$NON-NLS-1$
322 book = (Book) test.get(0);
323
324 if (book != null)
325 {
326 System.out.println(book.getInitials());
327 }
328
329
330 // If you want to know about new books as they arrive:
331 Books.installed().addBooksListener(new MyBooksListener());
332 }
333
334 public void installBook()
335 {
336 // An installer knows how to install books
337 Installer installer = null;
338
339 InstallManager imanager = new InstallManager();
340
341 // Ask the Install Manager for a map of all known module sites
342 Map installers = imanager.getInstallers();
343
344 // Get all the installers one after the other
345 Iterator iter = installers.entrySet().iterator();
346 String name = null;
347 while (iter.hasNext())
348 {
349 Map.Entry mapEntry = (Map.Entry) iter.next();
350 name = (String) mapEntry.getKey();
351 installer = (Installer) mapEntry.getValue();
352 }
353
354 name = "CrossWire"; //$NON-NLS-1$
355 // If we know the name of the installer we can get it directly
356 installer = imanager.getInstaller(name);
357
358 // Now we can get the list of books
359 try
360 {
361 installer.reloadBookList();
362 }
363 catch (InstallException e)
364 {
365 e.printStackTrace();
366 }
367
368 // Get a list of all the available books
369 List availableBooks = installer.getBooks();
370
371 // get some available books. In this case, just one book.
372 availableBooks = installer.getBooks(new MyBookFilter("ESV")); //$NON-NLS-1$
373
374 Book book = (Book) availableBooks.get(0);
375
376 if (book != null)
377 {
378 System.out.println("Book " + book.getInitials() + " is available"); //$NON-NLS-1$ //$NON-NLS-2$
379
380 // Delete the book, if present
381 // At the moment, JSword will not re-install. Later it will, if the remote version is greater.
382 try
383 {
384 if (Books.installed().getBook("ESV") != null) //$NON-NLS-1$
385 {
386 // Make the book unavailable.
387 // This is normally done via listeners.
388 Books.installed().removeBook(book);
389
390 // Actually do the delete
391 // This should be a call on installer.
392 book.getDriver().delete(book);
393 }
394 }
395 catch (BookException e1)
396 {
397 e1.printStackTrace();
398 }
399
400 try
401 {
402 // Now install it. Note this is a background task.
403 installer.install(book);
404 }
405 catch (InstallException e)
406 {
407 e.printStackTrace();
408 }
409 }
410 }
411
412 /**
413 * A simple BookFilter that looks for a Bible by name.
414 */
415 static class MyBookFilter implements BookFilter
416 {
417 public MyBookFilter(String bookName)
418 {
419 name = bookName;
420 }
421
422 public boolean test(Book bk)
423 {
424 return bk.getInitials().equals(name);
425 }
426
427 private String name;
428 }
429
430 /**
431 * A simple BooksListener that actually does nothing.
432 */
433 static class MyBooksListener implements BooksListener
434 {
435 /* (non-Javadoc)
436 * @see org.crosswire.jsword.book.BooksListener#bookAdded(org.crosswire.jsword.book.BooksEvent)
437 */
438 public void bookAdded(BooksEvent ev)
439 {
440 }
441
442 /* (non-Javadoc)
443 * @see org.crosswire.jsword.book.BooksListener#bookRemoved(org.crosswire.jsword.book.BooksEvent)
444 */
445 public void bookRemoved(BooksEvent ev)
446 {
447 }
448 }
449
450 /**
451 * Quick Demo
452 * @throws NoSuchKeyException
453 * @throws BookException
454 * @throws SAXException
455 * @throws TransformerException
456 */
457 public static void main(String[] args) throws BookException, NoSuchKeyException, TransformerException, SAXException
458 {
459 APIExamples examples = new APIExamples();
460
461 examples.installBook();
462 System.out.println("The plain text of Gen 1:1 is " + examples.getPlainText(BIBLE_NAME, "Gen 1:1")); //$NON-NLS-1$ //$NON-NLS-2$
463 System.out.println("The html text of Gen 1:1 is " + examples.readStyledText(BIBLE_NAME, "Gen 1:1", 100)); //$NON-NLS-1$ //$NON-NLS-2$
464 examples.readDictionary();
465 examples.search();
466 examples.rankedSearch();
467 examples.searchAndShow();
468 }
469 }
470