| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| BookIndexer |
|
| 3.0;3 | ||||
| BookIndexer$1 |
|
| 3.0;3 | ||||
| BookIndexer$StatusListener |
|
| 3.0;3 |
| 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, 2008 - 2016 | |
| 18 | * | |
| 19 | */ | |
| 20 | package org.crosswire.jsword.bridge; | |
| 21 | ||
| 22 | import org.crosswire.jsword.book.Book; | |
| 23 | import org.crosswire.jsword.book.BookException; | |
| 24 | import org.crosswire.jsword.book.Books; | |
| 25 | import org.crosswire.jsword.index.IndexManager; | |
| 26 | import org.crosswire.jsword.index.IndexManagerFactory; | |
| 27 | import org.crosswire.jsword.index.IndexStatus; | |
| 28 | import org.crosswire.jsword.index.IndexStatusEvent; | |
| 29 | import org.crosswire.jsword.index.IndexStatusListener; | |
| 30 | ||
| 31 | /** | |
| 32 | * BookIndexer allows one to check the status of an index, build an index or | |
| 33 | * delete an index. This is similar to SWORD's mkfastmod. | |
| 34 | * | |
| 35 | * @see gnu.lgpl.License The GNU Lesser General Public License for details. | |
| 36 | * @author DM Smith | |
| 37 | */ | |
| 38 | public class BookIndexer { | |
| 39 | ||
| 40 | 0 | public BookIndexer(Book book) { |
| 41 | 0 | this.book = book; |
| 42 | 0 | done = true; // not busy |
| 43 | 0 | indexManager = IndexManagerFactory.getIndexManager(); |
| 44 | 0 | isl = new StatusListener(this); |
| 45 | 0 | } |
| 46 | ||
| 47 | public boolean isIndexed() { | |
| 48 | // If we are busy then the index is being created | |
| 49 | // or it is being deleted. So for all practical purposes | |
| 50 | // it is not indexed. | |
| 51 | 0 | return done && indexManager.isIndexed(book); |
| 52 | } | |
| 53 | ||
| 54 | public void deleteIndex() throws BookException { | |
| 55 | 0 | if (done) { |
| 56 | 0 | done = false; |
| 57 | 0 | book.addIndexStatusListener(isl); |
| 58 | 0 | indexManager.deleteIndex(book); |
| 59 | 0 | while (!done) { |
| 60 | try { | |
| 61 | 0 | Thread.sleep(100); |
| 62 | 0 | } catch (InterruptedException e) { |
| 63 | // This is allowed | |
| 64 | 0 | } |
| 65 | } | |
| 66 | 0 | book.removeIndexStatusListener(isl); |
| 67 | } | |
| 68 | 0 | } |
| 69 | ||
| 70 | public void createIndex() throws BookException { | |
| 71 | 0 | if (done) { |
| 72 | 0 | done = false; |
| 73 | 0 | book.addIndexStatusListener(isl); |
| 74 | 0 | if (isIndexed()) { |
| 75 | 0 | deleteIndex(); |
| 76 | } | |
| 77 | 0 | Thread work = new Thread(new Runnable() { |
| 78 | public void run() { | |
| 79 | 0 | indexManager.scheduleIndexCreation(book); |
| 80 | 0 | } |
| 81 | }); | |
| 82 | 0 | work.start(); |
| 83 | 0 | while (!done) { |
| 84 | try { | |
| 85 | 0 | Thread.sleep(100); |
| 86 | 0 | } catch (InterruptedException e) { |
| 87 | // This is allowed | |
| 88 | 0 | } |
| 89 | } | |
| 90 | 0 | book.removeIndexStatusListener(isl); |
| 91 | } | |
| 92 | 0 | } |
| 93 | ||
| 94 | protected void setDone(boolean state) { | |
| 95 | 0 | done = state; |
| 96 | 0 | } |
| 97 | ||
| 98 | ||
| 99 | ||
| 100 | ||
| 101 | ||
| 102 | /* //todo static function: Demo of how clients can reindex, after a upgrade on a user computer. If reindexAll successful, update Installed.Index.DefaultVersion prop on the client computer | |
| 103 | ||
| 104 | //note: Need separate method for downloadLatestIndexForAllBooksIfNeeded() | |
| 105 | public static void reindexAllBooksIfNeeded() throws Exception { | |
| 106 | ||
| 107 | Books myBooks = Books.installed(); | |
| 108 | ||
| 109 | for(Book insBook: myBooks.getBooks()) { | |
| 110 | //reindex if needsReindexing(insBook) true | |
| 111 | if(indexManager.needsReindexing(insBook)) { | |
| 112 | createIndex(insBook); | |
| 113 | //reindex & update Books Installed.Index.Version | |
| 114 | InstalledIndex.instance().storeLatestVersionAsInstalledIndexMetadata(insBook); | |
| 115 | } | |
| 116 | //manage all Installed.Index.Version property values in metadata file | |
| 117 | } | |
| 118 | //set Installed.Index.DefaultVersion={Latest Version} | |
| 119 | PropertyMap map = new PropertyMap(); | |
| 120 | map.put(InstalledIndex.INSTALLED_INDEX_DEFAULT_VERSION , IndexMetadata.instance().getLatestIndexVersionStr()); | |
| 121 | InstalledIndex.instance().storeInstalledIndexMetadata(map); | |
| 122 | ||
| 123 | ||
| 124 | } | |
| 125 | */ | |
| 126 | ||
| 127 | ||
| 128 | ||
| 129 | protected Book book; | |
| 130 | protected IndexManager indexManager; | |
| 131 | private IndexStatusListener isl; | |
| 132 | private boolean done; | |
| 133 | ||
| 134 | /** | |
| 135 | * Listen for the end of indexing. | |
| 136 | */ | |
| 137 | public static final class StatusListener implements IndexStatusListener { | |
| 138 | 0 | public StatusListener(BookIndexer indexer) { |
| 139 | 0 | this.indexer = indexer; |
| 140 | 0 | } |
| 141 | ||
| 142 | public void statusChanged(IndexStatusEvent ev) { | |
| 143 | 0 | IndexStatus newStatus = ev.getIndexStatus(); |
| 144 | 0 | if (IndexStatus.DONE.equals(newStatus) || IndexStatus.UNDONE.equals(newStatus) || IndexStatus.INVALID.equals(newStatus)) { |
| 145 | 0 | indexer.setDone(true); |
| 146 | } | |
| 147 | 0 | } |
| 148 | ||
| 149 | private BookIndexer indexer; | |
| 150 | } | |
| 151 | ||
| 152 | /** | |
| 153 | * Call with <operation> book. Where operation can be one of: | |
| 154 | * <ul> | |
| 155 | * <li>check - returns "TRUE" or "FALSE" indicating whether the index exists | |
| 156 | * or not</li> | |
| 157 | * <li>create - (re)create the index</li> | |
| 158 | * <li>delete - delete the index if it exists</li> | |
| 159 | * </ul> | |
| 160 | * And book is the initials of a book, e.g. KJV. | |
| 161 | * | |
| 162 | * @param args | |
| 163 | */ | |
| 164 | public static void main(String[] args) { | |
| 165 | 0 | if (args.length != 2) { |
| 166 | 0 | usage(); |
| 167 | 0 | return; |
| 168 | } | |
| 169 | ||
| 170 | 0 | System.err.println("BookIndexer " + args[0] + " " + args[1]); |
| 171 | ||
| 172 | 0 | String operation = args[0]; |
| 173 | 0 | Book b = Books.installed().getBook(args[1]); |
| 174 | 0 | if (b == null) { |
| 175 | 0 | System.err.println("Book not found"); |
| 176 | 0 | return; |
| 177 | } | |
| 178 | ||
| 179 | 0 | BookIndexer indexer = new BookIndexer(b); |
| 180 | 0 | if ("create".equalsIgnoreCase(operation)) { |
| 181 | try { | |
| 182 | 0 | indexer.createIndex(); |
| 183 | 0 | } catch (BookException e) { |
| 184 | 0 | System.err.println("Unable to re-index book."); |
| 185 | 0 | e.printStackTrace(); |
| 186 | 0 | } |
| 187 | 0 | } else if ("delete".equalsIgnoreCase(operation)) { |
| 188 | try { | |
| 189 | 0 | indexer.deleteIndex(); |
| 190 | 0 | } catch (BookException e) { |
| 191 | 0 | System.err.println("Unable to delete index for book."); |
| 192 | 0 | e.printStackTrace(); |
| 193 | 0 | } |
| 194 | 0 | } else if ("check".equalsIgnoreCase(operation)) { |
| 195 | 0 | System.err.println(indexer.isIndexed()); |
| 196 | } else { | |
| 197 | 0 | usage(); |
| 198 | } | |
| 199 | 0 | } |
| 200 | ||
| 201 | public static void usage() { | |
| 202 | 0 | System.err.println("Usage: BookIndexer operation book"); |
| 203 | 0 | } |
| 204 | } |