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