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: 2008
18   *     The copyright to this program is held by it's authors.
19   *
20   * ID: $Id: BookIndexer.java 1466 2007-07-02 02:48:09Z dmsmith $
21   */
22  package org.crosswire.jsword.bridge;
23  
24  import org.crosswire.jsword.book.Book;
25  import org.crosswire.jsword.book.BookException;
26  import org.crosswire.jsword.book.Books;
27  import org.crosswire.jsword.index.IndexManager;
28  import org.crosswire.jsword.index.IndexManagerFactory;
29  import org.crosswire.jsword.index.IndexStatusEvent;
30  import org.crosswire.jsword.index.IndexStatusListener;
31  
32  /**
33   * BookIndexer allows one to check the status of an index, build an index or
34   * delete an index. This is similar to SWORD's mkfastmod.
35   * 
36   * @see gnu.lgpl.License for license details.<br>
37   *      The copyright to this program is held by it's authors.
38   * @author DM Smith [dmsmith555 at yahoo dot com]
39   */
40  public class BookIndexer {
41  
42      public BookIndexer(Book book) {
43          this.book = book;
44          done = true; // not busy
45          indexManager = IndexManagerFactory.getIndexManager();
46          isl = new StatusListener(this);
47      }
48  
49      public boolean isIndexed() {
50          // If we are busy then the index is being created
51          // or it is being deleted. So for all practical purposes
52          // it is not indexed.
53          return done && indexManager.isIndexed(book);
54      }
55  
56      public void deleteIndex() throws BookException {
57          if (done) {
58              done = false;
59              book.addIndexStatusListener(isl);
60              indexManager.deleteIndex(book);
61              while (!done) {
62                  try {
63                      Thread.sleep(100);
64                  } catch (InterruptedException e) {
65                      // ok to be interrupted
66                  }
67              }
68              book.removeIndexStatusListener(isl);
69          }
70      }
71  
72      public void createIndex() throws BookException {
73          if (done) {
74              done = false;
75              book.addIndexStatusListener(isl);
76              if (isIndexed()) {
77                  deleteIndex();
78              }
79              indexManager.scheduleIndexCreation(book);
80              while (!done) {
81                  try {
82                      Thread.sleep(100);
83                  } catch (InterruptedException e) {
84                      // ok to be interrupted
85                  }
86              }
87              book.removeIndexStatusListener(isl);
88          }
89      }
90  
91      protected void setDone(boolean state) {
92          done = state;
93      }
94  
95      private Book book;
96      private IndexManager indexManager;
97      private IndexStatusListener isl;
98      private boolean done;
99  
100     /**
101      * Listen for the end of indexing.
102      */
103     public static final class StatusListener implements IndexStatusListener {
104         public StatusListener(BookIndexer indexer) {
105             this.indexer = indexer;
106         }
107 
108         public void statusChanged(IndexStatusEvent ev) {
109             indexer.setDone(true);
110         }
111 
112         private BookIndexer indexer;
113     }
114 
115     /**
116      * Call with &lt;operation&gt; book. Where operation can be one of:
117      * <ul>
118      * <li>check - returns "TRUE" or "FALSE" indicating whether the index exists
119      * or not</li>
120      * <li>create - (re)create the index</li>
121      * <li>delete - delete the index if it exists</li>
122      * </ul>
123      * And book is the initials of a book, e.g. KJV.
124      * 
125      * @param args
126      */
127     public static void main(String[] args) {
128         if (args.length != 2) {
129             usage();
130             return;
131         }
132 
133         System.err.println("BookIndexer " + args[0] + " " + args[1]);
134 
135         String operation = args[0];
136         Book b = Books.installed().getBook(args[1]);
137         if (b == null) {
138             System.err.println("Book not found");
139             return;
140         }
141 
142         BookIndexer indexer = new BookIndexer(b);
143         if (operation.equalsIgnoreCase("create")) {
144             try {
145                 indexer.createIndex();
146             } catch (BookException e) {
147                 System.err.println("Unable to re-index book.");
148                 e.printStackTrace();
149             }
150         } else if (operation.equalsIgnoreCase("delete")) {
151             try {
152                 indexer.deleteIndex();
153             } catch (BookException e) {
154                 System.err.println("Unable to delete index for book.");
155                 e.printStackTrace();
156             }
157         } else if (operation.equalsIgnoreCase("check")) {
158             System.err.println(indexer.isIndexed());
159         } else {
160             usage();
161         }
162     }
163 
164     public static void usage() {
165         System.err.println("Usage: BookIndexer operation book");
166     }
167 }
168