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: Book.java 2221 2012-01-25 21:32:57Z dmsmith $
21   */
22  package org.crosswire.jsword.book;
23  
24  import java.util.Iterator;
25  import java.util.Map;
26  
27  import org.crosswire.common.activate.Activatable;
28  import org.crosswire.common.util.Language;
29  import org.crosswire.jsword.index.IndexStatus;
30  import org.crosswire.jsword.index.IndexStatusListener;
31  import org.crosswire.jsword.index.search.SearchRequest;
32  import org.crosswire.jsword.passage.Key;
33  import org.crosswire.jsword.passage.NoSuchKeyException;
34  import org.jdom.Content;
35  import org.jdom.Document;
36  
37  /**
38   * Book is the most basic store of textual data - It can retrieve data either as
39   * an XML document or as plain text - It uses Keys to refer to parts of itself,
40   * and can search for words (returning Keys).
41   * 
42   * @see gnu.lgpl.License for license details.<br>
43   *      The copyright to this program is held by it's authors.
44   * @author Joe Walker [joe at eireneh dot com]
45   */
46  public interface Book extends Activatable, Comparable<Book> {
47      /**
48       * Get a complete list of index entries. Create a Key that encompasses all
49       * of the known valid keys for the given context. For a dictionary this will
50       * include all of the entries in the dictionary, for a Bible this will
51       * probably include all the verses in the Bible, but a commentary may well
52       * miss some out.
53       * 
54       * @return A Key that includes all of the known Keys
55       */
56      Key getGlobalKeyList();
57  
58      /**
59       * Get a Key for the name, if possible. Otherwise return an empty Key.
60       * 
61       * @param name
62       * @return a valid key.
63       */
64      Key getValidKey(String name);
65  
66      /**
67       * Someone has typed in a reference to find, but we need a Key to actually
68       * look it up. So we create a Key from the string if such a translation is
69       * possible. The returned Key may be a BranchKey if the string represents
70       * more than one Key.
71       * 
72       * @param name
73       *            The string to translate into a Key
74       * @return The Key corresponding to the input text
75       * @throws NoSuchKeyException
76       *             If the name can not be parsed.
77       */
78      Key getKey(String name) throws NoSuchKeyException;
79  
80      /**
81       * Fetch an empty Key to which we can add Keys. Not all implementations of
82       * Key are able to hold any type of Key, It isn't reasonable to expect a Key
83       * of Bible verses (=Passage) to hold a dictionary Key. So each KeyFactory
84       * must be able to create you an empty Key to which you can safely add other
85       * Keys it generates.
86       * 
87       * @return An empty Key that can hold other Keys from this factory.
88       */
89      Key createEmptyKeyList();
90  
91      /**
92       * Meta-Information: What version of the Bible is this?
93       * 
94       * @return A Version for this Bible
95       */
96      BookMetaData getBookMetaData();
97  
98      /**
99       * Set the meta-information for this book.
100      */
101     void setBookMetaData(BookMetaData bmd);
102 
103     /**
104      * Return an iterator that returns each key's OSIS in turn.
105      * 
106      * @param key
107      *            the Items to locate
108      * @param allowEmpty
109      *            indicates whether empty keys should be present.
110      */
111     Iterator<Content> getOsisIterator(Key key, boolean allowEmpty) throws BookException;
112 
113     /**
114      * Returns <tt>true</tt> if this book contains the specified element.
115      * 
116      * @param key
117      *            element whose presence in this book is to be tested.
118      * @return <tt>true</tt> if this book contains the specified element.
119      */
120     boolean contains(Key key);
121 
122     /**
123      * Returns the raw text that getData(Key key) builds into OSIS.
124      * 
125      * @param key
126      *            The item to locate
127      * @return The found Book data
128      * @throws BookException
129      *             If anything goes wrong with this method
130      */
131     String getRawText(Key key) throws BookException;
132 
133     /**
134      * A Book is writable if the file system allows the underlying files to be
135      * opened for writing and if the driver for the book allows writing.
136      * Ultimately, all drivers should allow writing. At this time writing is not
137      * supported by drivers, so abstract implementations should return false and
138      * let specific implementations return true otherwise.
139      * 
140      * @return true if the book is writable
141      */
142     boolean isWritable();
143 
144     /**
145      * Store the raw text for the given key. This will replace/hide any raw text
146      * that already is present. Note: it is the responsibility of the calling
147      * program to ensure that the raw text matches the character set encoding
148      * and markup of the module.
149      * 
150      * @param key
151      *            The item to locate
152      * @param rawData
153      *            The text to store
154      * @throws BookException
155      *             If anything goes wrong with this method
156      */
157     void setRawText(Key key, String rawData) throws BookException;
158 
159     /**
160      * Store an alias of one key to another. Some Bibles do not have a verse by
161      * verse numbering system but rather meld several verses into one. Thus, any
162      * verse in the range refers to the same verse. Also it may apply to
163      * biblical commentaries that are indexed by Book, Chapter, Verse and that
164      * discuss the Bible at a verse range level. For a dictionary, it may be
165      * used for synonyms.
166      * <p>
167      * It should be an exception to set an alias when that alias already has raw
168      * text. Also, it should be an exception to set an alias to an alias.
169      * However, getRawText(Key) must be able to handle alias chains.
170      * </p>
171      * 
172      * @param alias
173      *            the key that aliases another
174      * @param source
175      *            the key that holds the text
176      * @throws BookException
177      *             If anything goes wrong with this method
178      */
179     void setAliasKey(Key alias, Key source) throws BookException;
180 
181     /**
182      * Retrieval: For a given search spec find a list of references to it. If
183      * there are no matches then null should be returned, otherwise a valid Key.
184      * 
185      * @param request
186      *            The search spec.
187      * @throws BookException
188      *             If anything goes wrong with this method
189      */
190     Key find(SearchRequest request) throws BookException;
191 
192     /**
193      * Retrieval: For a given search spec find a list of references to it. If
194      * there are no matches then null should be returned, otherwise a valid Key.
195      * 
196      * @param request
197      *            The search spec.
198      * @throws BookException
199      *             If anything goes wrong with this method
200      */
201     Key find(String request) throws BookException;
202 
203     /**
204      * The name of the book, for example "King James Version" or
205      * "Bible in Basic English" or "Greek". In general it should be possible to
206      * deduce the initials from the name by removing all the non-capital
207      * letters. Although this is only a generalization. This method should not
208      * return null or a blank string.
209      * 
210      * @return The name of this book
211      */
212     String getName();
213 
214     /**
215      * What category of content is this, a Bible or a reference work like a
216      * Dictionary or Commentary.
217      * 
218      * @return The category of book
219      */
220     BookCategory getBookCategory();
221 
222     /**
223      * Accessor for the driver that runs this Book. Note this method should only
224      * be used to delete() Books. Everything else you should want to do to a
225      * Book should be available in other ways.
226      */
227     BookDriver getDriver();
228 
229     /**
230      * The language of the book.
231      * 
232      * @return the common name for the language
233      */
234     Language getLanguage();
235 
236     /**
237      * The initials of this book - how people familiar with this book will know
238      * it, for example "NIV", "KJV".
239      * 
240      * @return The book's initials
241      */
242     String getInitials();
243 
244     /**
245      * Calculated field: Get an OSIS identifier for the OsisText.setOsisIDWork()
246      * and the Work.setOsisWork() methods. The response will generally be of the
247      * form [Bible][Dict..].getInitials
248      * 
249      * @return The osis id of this book
250      */
251     String getOsisID();
252 
253     /**
254      * Return the likelihood that we have a match. This allows for calling the
255      * book different things and still be found.
256      * 
257      * @param name
258      * @return true if we have a match.
259      */
260     boolean match(String name);
261 
262     /**
263      * Indicate whether this book is supported by JSword. Since the expectation
264      * is that all books are supported, abstract implementations should return
265      * true and let specific implementations return false if they cannot support
266      * the book.
267      * 
268      * @return true if the book is supported
269      */
270     boolean isSupported();
271 
272     /**
273      * Indicate whether this book is enciphered. Since the expectation is that
274      * most books are unenciphered, abstract implementations should return false
275      * and let specific implementations return true otherwise.
276      * 
277      * @return true if the book is enciphered
278      */
279     boolean isEnciphered();
280 
281     /**
282      * Indicate whether this book is enciphered and without a key. Since the
283      * expectation is that most books are unenciphered, abstract implementations
284      * should return false and let specific implementations return true
285      * otherwise.
286      * 
287      * @return true if the book is locked
288      */
289     boolean isLocked();
290 
291     /**
292      * Unlocks a book with the given key.
293      * 
294      * @param unlockKey
295      *            the key to try
296      * @return true if the unlock key worked.
297      */
298     boolean unlock(String unlockKey);
299 
300     /**
301      * Gets the unlock key for the module.
302      * 
303      * @return the unlock key, if any, null otherwise.
304      */
305     String getUnlockKey();
306 
307     /**
308      * Indicate whether this book is questionable. A book may be deemed
309      * questionable if it's quality or content has not been confirmed. Since the
310      * expectation is that all books are not questionable, abstract
311      * implementations should return false and let specific implementations
312      * return true if the book is questionable.
313      * 
314      * @return true if the book is questionable
315      */
316     boolean isQuestionable();
317 
318     /**
319      * Calculated field: The name of the name, which could be helpful to
320      * distinguish similar Books available through 2 BookDrivers.
321      * 
322      * @return The driver name
323      */
324     String getDriverName();
325 
326     /**
327      * Return the orientation of the script of the Book. If a book contains more
328      * than one script, it refers to the dominate script of the book. This will
329      * be used to present Arabic and Hebrew in their proper orientation. Note:
330      * some languages have multiple scripts which don't have the same
331      * directionality.
332      * 
333      * @return true if the orientation for the dominate script is LeftToRight.
334      */
335     boolean isLeftToRight();
336 
337     /**
338      * Return whether the feature is supported by the book.
339      */
340     boolean hasFeature(FeatureType feature);
341 
342     /**
343      * Get a list of all the properties available to do with this Book. The
344      * returned Properties will be read-only so any attempts to alter it will
345      * fail.
346      */
347     Map<String, Object> getProperties();
348 
349     /**
350      * @param key
351      *            the key of the property.
352      * @return the value of the property
353      */
354     Object getProperty(String key);
355 
356     /**
357      * @param key
358      *            the key of the property.
359      * @param value
360      *            the value of the property
361      */
362     void putProperty(String key, Object value);
363 
364     /**
365      * Has anyone generated a search index for this Book?
366      * 
367      * @see org.crosswire.jsword.index.IndexManager
368      */
369     IndexStatus getIndexStatus();
370 
371     /**
372      * This method does not alter the index status, however it is for Indexers
373      * that are responsible for indexing and have changed the status themselves.
374      * 
375      * @see org.crosswire.jsword.index.IndexManager
376      */
377     void setIndexStatus(IndexStatus status);
378 
379     /**
380      * Get an OSIS representation of information concerning this Book.
381      */
382     Document toOSIS();
383 
384     /**
385      * Adds a <code>IndexStatusListener</code> to the listener list.
386      * <p>
387      * A <code>IndexStatusEvent</code> will get fired in response to
388      * <code>setIndexStatus</code>.
389      * 
390      * @param li
391      *            the <code>IndexStatusListener</code> to be added
392      */
393     void addIndexStatusListener(IndexStatusListener li);
394 
395     /**
396      * Removes a <code>IndexStatusListener</code> from the listener list.
397      * 
398      * @param li
399      *            the <code>IndexStatusListener</code> to be removed
400      */
401     void removeIndexStatusListener(IndexStatusListener li);
402 }
403