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