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 | } |