| AbstractBook.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: AbstractBook.java 2099 2011-03-07 17:13:00Z dmsmith $
21 */
22 package org.crosswire.jsword.book.basic;
23
24 import java.util.Map;
25
26 import org.crosswire.common.activate.Lock;
27 import org.crosswire.common.util.EventListenerList;
28 import org.crosswire.common.util.Language;
29 import org.crosswire.jsword.JSOtherMsg;
30 import org.crosswire.jsword.book.Book;
31 import org.crosswire.jsword.book.BookCategory;
32 import org.crosswire.jsword.book.BookDriver;
33 import org.crosswire.jsword.book.BookException;
34 import org.crosswire.jsword.book.BookMetaData;
35 import org.crosswire.jsword.book.FeatureType;
36 import org.crosswire.jsword.index.IndexStatus;
37 import org.crosswire.jsword.index.IndexStatusEvent;
38 import org.crosswire.jsword.index.IndexStatusListener;
39 import org.crosswire.jsword.index.search.DefaultSearchRequest;
40 import org.crosswire.jsword.index.search.SearchRequest;
41 import org.crosswire.jsword.index.search.Searcher;
42 import org.crosswire.jsword.index.search.SearcherFactory;
43 import org.crosswire.jsword.passage.Key;
44 import org.jdom.Document;
45
46 /**
47 * AbstractBook implements a few of the more generic methods of Book. This class
48 * does a lot of work in helping make search easier, and implementing some basic
49 * write methods.
50 *
51 * @see gnu.lgpl.License for license details.<br>
52 * The copyright to this program is held by it's authors.
53 * @author Joe Walker [joe at eireneh dot com]
54 */
55 public abstract class AbstractBook implements Book {
56 public AbstractBook(BookMetaData bmd) {
57 setBookMetaData(bmd);
58 }
59
60 /*
61 * (non-Javadoc)
62 *
63 * @see org.crosswire.jsword.book.Book#getBookMetaData()
64 */
65 public final BookMetaData getBookMetaData() {
66 return bmd;
67 }
68
69 /*
70 * (non-Javadoc)
71 *
72 * @see
73 * org.crosswire.jsword.book.Book#setBookMetaData(org.crosswire.jsword.book
74 * .BookMetaData)
75 */
76 public final void setBookMetaData(BookMetaData bmd) {
77 this.bmd = bmd;
78 }
79
80 /*
81 * (non-Javadoc)
82 *
83 * @see
84 * org.crosswire.common.activate.Activatable#activate(org.crosswire.common
85 * .activate.Lock)
86 */
87 public void activate(Lock lock) {
88 }
89
90 /*
91 * (non-Javadoc)
92 *
93 * @see
94 * org.crosswire.common.activate.Activatable#deactivate(org.crosswire.common
95 * .activate.Lock)
96 */
97 public void deactivate(Lock lock) {
98 }
99
100 /*
101 * (non-Javadoc)
102 *
103 * @see org.crosswire.jsword.book.Book#find(java.lang.String)
104 */
105 public Key find(String request) throws BookException {
106 return find(new DefaultSearchRequest(request));
107 }
108
109 /*
110 * (non-Javadoc)
111 *
112 * @see
113 * org.crosswire.jsword.book.Book#find(org.crosswire.jsword.index.search
114 * .SearchRequest)
115 */
116 public Key find(SearchRequest request) throws BookException {
117 if (searcher == null) {
118 try {
119 searcher = SearcherFactory.createSearcher(this);
120 } catch (InstantiationException ex) {
121 throw new BookException(JSOtherMsg.lookupText("Failed to initialize the search index"), ex);
122 }
123 }
124
125 return searcher.search(request);
126 }
127
128 /*
129 * (non-Javadoc)
130 *
131 * @see org.crosswire.jsword.book.BookMetaData#getBook()
132 */
133 public Book getBook() {
134 return this;
135 }
136
137 /*
138 * (non-Javadoc)
139 *
140 * @see org.crosswire.jsword.book.BookMetaData#getDriver()
141 */
142 public BookDriver getDriver() {
143 return bmd == null ? null : bmd.getDriver();
144 }
145
146 /*
147 * (non-Javadoc)
148 *
149 * @see org.crosswire.jsword.book.BookMetaData#getDriverName()
150 */
151 public String getDriverName() {
152 return bmd == null ? null : bmd.getDriverName();
153 }
154
155 /*
156 * (non-Javadoc)
157 *
158 * @see org.crosswire.jsword.book.Book#match(java.lang.String)
159 */
160 public boolean match(String name) {
161 if (name == null) {
162 return false;
163 }
164 if (name.equals(getInitials())) {
165 return true;
166 }
167 if (name.equals(getName())) {
168 return true;
169 }
170 if (name.equalsIgnoreCase(getInitials())) {
171 return true;
172 }
173 if (name.equalsIgnoreCase(getName())) {
174 return true;
175 }
176 if (name.startsWith(getInitials())) {
177 return true;
178 }
179 if (name.startsWith(getName())) {
180 return true;
181 }
182 return false;
183 }
184
185 /*
186 * (non-Javadoc)
187 *
188 * @see org.crosswire.jsword.book.BookMetaData#getIndexStatus()
189 */
190 public IndexStatus getIndexStatus() {
191 return bmd.getIndexStatus();
192 }
193
194 /*
195 * (non-Javadoc)
196 *
197 * @see
198 * org.crosswire.jsword.book.BookMetaData#setIndexStatus(org.crosswire.jsword
199 * .book.IndexStatus)
200 */
201 public void setIndexStatus(IndexStatus newStatus) {
202 IndexStatus oldStatus = bmd.getIndexStatus();
203 bmd.setIndexStatus(newStatus);
204 firePropertyChange(oldStatus, newStatus);
205 }
206
207 /*
208 * (non-Javadoc)
209 *
210 * @see org.crosswire.jsword.book.BookMetaData#getInitials()
211 */
212 public String getInitials() {
213 return bmd.getInitials();
214 }
215
216 /*
217 * (non-Javadoc)
218 *
219 * @see org.crosswire.jsword.book.BookMetaData#getLanguage()
220 */
221 public Language getLanguage() {
222 return bmd.getLanguage();
223 }
224
225 /*
226 * (non-Javadoc)
227 *
228 * @see org.crosswire.jsword.book.BookMetaData#getName()
229 */
230 public String getName() {
231 return bmd.getName();
232 }
233
234 /*
235 * (non-Javadoc)
236 *
237 * @see org.crosswire.jsword.book.BookMetaData#getOsisID()
238 */
239 public String getOsisID() {
240 return bmd.getOsisID();
241 }
242
243 /*
244 * (non-Javadoc)
245 *
246 * @see org.crosswire.jsword.book.BookMetaData#getProperties()
247 */
248 public Map<String, Object> getProperties() {
249 return bmd.getProperties();
250 }
251
252 /*
253 * (non-Javadoc)
254 *
255 * @see org.crosswire.jsword.book.Book#getProperty(java.lang.String)
256 */
257 public Object getProperty(String key) {
258 return bmd.getProperty(key);
259 }
260
261 /*
262 * (non-Javadoc)
263 *
264 * @see org.crosswire.jsword.book.Book#putProperty(java.lang.String,
265 * java.lang.String)
266 */
267 public void putProperty(String key, Object value) {
268 bmd.putProperty(key, value);
269 }
270
271 /*
272 * (non-Javadoc)
273 *
274 * @see org.crosswire.jsword.book.BookMetaData#getType()
275 */
276 public BookCategory getBookCategory() {
277 return bmd.getBookCategory();
278 }
279
280 /*
281 * (non-Javadoc)
282 *
283 * @see org.crosswire.jsword.book.BookMetaData#isLeftToRight()
284 */
285 public boolean isLeftToRight() {
286 return bmd.isLeftToRight();
287 }
288
289 /*
290 * (non-Javadoc)
291 *
292 * @see org.crosswire.jsword.book.BookMetaData#isSupported()
293 */
294 public boolean isSupported() {
295 return bmd.isSupported();
296 }
297
298 /*
299 * (non-Javadoc)
300 *
301 * @see org.crosswire.jsword.book.BookMetaData#isEnciphered()
302 */
303 public boolean isEnciphered() {
304 return bmd.isEnciphered();
305 }
306
307 /*
308 * (non-Javadoc)
309 *
310 * @see org.crosswire.jsword.book.BookMetaData#isLocked()
311 */
312 public boolean isLocked() {
313 return bmd.isLocked();
314 }
315
316 /*
317 * (non-Javadoc)
318 *
319 * @see org.crosswire.jsword.book.BookMetaData#unlock(String)
320 */
321 public boolean unlock(String unlockKey) {
322 boolean state = bmd.unlock(unlockKey);
323 if (state) {
324 // Double check.
325 return isUnlockKeyValid();
326 }
327 return state;
328 }
329
330 /**
331 * This is a heuristic that tries out the key.
332 *
333 * @return true if there were no exceptions in reading the enciphered
334 * module.
335 */
336 private boolean isUnlockKeyValid() {
337 try {
338 Key key = getGlobalKeyList();
339 if (key == null) {
340 // weird key == null, assume it is valid
341 return true;
342 }
343
344 if (key.getCardinality() > 0) {
345 key = key.get(0);
346 }
347
348 getRawText(key);
349
350 return true;
351 } catch (Exception ex) {
352 return false;
353 }
354 }
355
356 /*
357 * (non-Javadoc)
358 *
359 * @see org.crosswire.jsword.book.BookMetaData#getUnlockKey()
360 */
361 public String getUnlockKey() {
362 return bmd.getUnlockKey();
363 }
364
365 /*
366 * (non-Javadoc)
367 *
368 * @see org.crosswire.jsword.book.BookMetaData#isQuestionable()
369 */
370 public boolean isQuestionable() {
371 return bmd.isQuestionable();
372 }
373
374 /*
375 * (non-Javadoc)
376 *
377 * @see
378 * org.crosswire.jsword.book.BookMetaData#hasFeature(org.crosswire.jsword
379 * .book.FeatureType)
380 */
381 public boolean hasFeature(FeatureType feature) {
382 return bmd.hasFeature(feature);
383 }
384
385 /*
386 * (non-Javadoc)
387 *
388 * @see
389 * org.crosswire.jsword.book.Book#addIndexStatusListener(org.crosswire.jsword
390 * .index.IndexStatusListener)
391 */
392 public void addIndexStatusListener(IndexStatusListener listener) {
393 if (listeners == null) {
394 listeners = new EventListenerList();
395 }
396 listeners.add(IndexStatusListener.class, listener);
397 }
398
399 /*
400 * (non-Javadoc)
401 *
402 * @see
403 * org.crosswire.jsword.book.Book#removeIndexStatusListener(org.crosswire
404 * .jsword.index.IndexStatusListener)
405 */
406 public void removeIndexStatusListener(IndexStatusListener listener) {
407 if (listeners == null) {
408 return;
409 }
410
411 listeners.remove(IndexStatusListener.class, listener);
412 }
413
414 /**
415 * Reports bound property changes. If <code>oldValue</code> and
416 * <code>newValue</code> are not equal and the
417 * <code>PropertyChangeEvent</code> listener list isn't empty, then fire a
418 * <code>PropertyChange</code> event to each listener.
419 *
420 * @param oldStatus
421 * the old value of the property (as an Object)
422 * @param newStatus
423 * the new value of the property (as an Object)
424 */
425 protected void firePropertyChange(IndexStatus oldStatus, IndexStatus newStatus) {
426 if (listeners != null) {
427 if (oldStatus != null && newStatus != null && oldStatus.equals(newStatus)) {
428 return;
429 }
430
431 Object[] listenerList = listeners.getListenerList();
432 for (int i = 0; i <= listenerList.length - 2; i += 2) {
433 if (listenerList[i] == IndexStatusListener.class) {
434 IndexStatusEvent ev = new IndexStatusEvent(this, newStatus);
435 IndexStatusListener li = (IndexStatusListener) listenerList[i + 1];
436 li.statusChanged(ev);
437 }
438 }
439 }
440 }
441
442 /*
443 * (non-Javadoc)
444 *
445 * @see org.crosswire.jsword.book.BookMetaData#toOSIS()
446 */
447 public Document toOSIS() {
448 return bmd.toOSIS();
449 }
450
451 /*
452 * (non-Javadoc)
453 *
454 * @see java.lang.Object#equals(java.lang.Object)
455 */
456 @Override
457 public boolean equals(Object obj) {
458 // Since this can not be null
459 if (obj == null) {
460 return false;
461 }
462
463 // We might consider checking for equality against all Books?
464 // However currently we don't.
465
466 // Check that that is the same as this
467 // Don't use instanceof since that breaks inheritance
468 if (!obj.getClass().equals(this.getClass())) {
469 return false;
470 }
471
472 // The real bit ...
473 Book that = (Book) obj;
474
475 return bmd.equals(that.getBookMetaData());
476 }
477
478 /*
479 * (non-Javadoc)
480 *
481 * @see java.lang.Object#hashCode()
482 */
483 @Override
484 public int hashCode() {
485 return bmd.hashCode();
486 }
487
488 /*
489 * (non-Javadoc)
490 *
491 * @see java.lang.Comparable#compareTo(java.lang.Object)
492 */
493 public int compareTo(Book obj) {
494 return this.bmd.compareTo(obj.getBookMetaData());
495 }
496
497 /*
498 * (non-Javadoc)
499 *
500 * @see java.lang.Object#toString()
501 */
502 @Override
503 public String toString() {
504 return bmd.toString();
505 }
506
507 /**
508 * How do we perform searches
509 */
510 private Searcher searcher;
511
512 /**
513 * The meta data for this book
514 */
515 private BookMetaData bmd;
516
517 /**
518 * The list of property change listeners
519 */
520 private EventListenerList listeners;
521 }
522