| BookFilters.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 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 * Copyright: 2005
18 * The copyright to this program is held by it's authors.
19 *
20 */
21 package org.crosswire.jsword.book;
22
23 import java.util.ArrayList;
24 import java.util.List;
25
26 /**
27 * Some common implementations of BookFilter.
28 *
29 * @see gnu.lgpl.License for license details.<br>
30 * The copyright to this program is held by it's authors.
31 * @author Joe Walker [joe at eireneh dot com]
32 */
33 public final class BookFilters {
34 /**
35 * Ensure we can't be created
36 */
37 private BookFilters() {
38 }
39
40 /**
41 * A simple default filter that returns everything
42 */
43 public static BookFilter getAll() {
44 return new AllBookFilter();
45 }
46
47 /**
48 * A filter that accepts everything that implements Bible or Commentary,
49 * when commentaries are listed with Bibles.
50 */
51 public static BookFilter getBibles() {
52 if (commentariesWithBibles) {
53 return either(new BookCategoryFilter(BookCategory.BIBLE), new BookCategoryFilter(BookCategory.COMMENTARY));
54 }
55 return new BookCategoryFilter(BookCategory.BIBLE);
56 }
57
58 /**
59 * A filter that accepts everything that implements Bible.
60 */
61 public static BookFilter getOnlyBibles() {
62 return new BookCategoryFilter(BookCategory.BIBLE);
63 }
64
65 /**
66 * A filter that accepts everything that's not a Bible or a Commentary, when
67 * commentaries are listed with Bibles.
68 */
69 public static BookFilter getNonBibles() {
70 if (commentariesWithBibles) {
71 return both(new NotBookCategoryFilter(BookCategory.BIBLE), new NotBookCategoryFilter(BookCategory.COMMENTARY));
72 }
73 return new NotBookCategoryFilter(BookCategory.BIBLE);
74 }
75
76 /**
77 * A filter that accepts everything that implements Dictionary
78 */
79 public static BookFilter getDictionaries() {
80 return new BookCategoryFilter(BookCategory.DICTIONARY);
81 }
82
83 /**
84 * A filter that accepts everything that implements Dictionary
85 */
86 public static BookFilter getGlossaries() {
87 return new BookCategoryFilter(BookCategory.GLOSSARY);
88 }
89
90 /**
91 * A filter that accepts everything that implements DailyDevotionals
92 */
93 public static BookFilter getDailyDevotionals() {
94 return new BookCategoryFilter(BookCategory.DAILY_DEVOTIONS);
95 }
96
97 /**
98 * A filter that accepts everything that implements Commentary
99 */
100 public static BookFilter getCommentaries() {
101 return new BookCategoryFilter(BookCategory.COMMENTARY);
102 }
103
104 /**
105 * A filter that accepts everything that implements GeneralBook
106 */
107 public static BookFilter getGeneralBooks() {
108 return new BookCategoryFilter(BookCategory.GENERAL_BOOK);
109 }
110
111 /**
112 * A filter that accepts everything that implements Maps
113 */
114 public static BookFilter getMaps() {
115 return new BookCategoryFilter(BookCategory.MAPS);
116 }
117
118 /**
119 * A filter that accepts everything that is a Greek Definition Dictionary
120 */
121 public static BookFilter getGreekDefinitions() {
122 return new BookFeatureFilter(FeatureType.GREEK_DEFINITIONS);
123 }
124
125 /**
126 * A filter that accepts everything that is a Greek Parse/Morphology
127 * Dictionary
128 */
129 public static BookFilter getGreekParse() {
130 return new BookFeatureFilter(FeatureType.GREEK_PARSE);
131 }
132
133 /**
134 * A filter that accepts everything that is a Hebrew Definition Dictionary
135 */
136 public static BookFilter getHebrewDefinitions() {
137 return new BookFeatureFilter(FeatureType.HEBREW_DEFINITIONS);
138 }
139
140 /**
141 * A filter that accepts everything that is a Hebrew Parse/Morphology
142 * Dictionary
143 */
144 public static BookFilter getHebrewParse() {
145 return new BookFeatureFilter(FeatureType.HEBREW_PARSE);
146 }
147
148 /**
149 * Determine whether the getBible should return the current Bible or the
150 * user's chosen default.
151 *
152 * @return true if the bible tracks the user's selection
153 */
154 public static boolean isCommentariesWithBibles() {
155 return commentariesWithBibles;
156 }
157
158 /**
159 * Establish whether the getBible should return the current Bible or the
160 * user's chosen default.
161 *
162 * @param current
163 */
164 public static void setCommentariesWithBibles(boolean current) {
165 commentariesWithBibles = current;
166 }
167
168 /**
169 * Whether biblesBookFilter includes commentaries. Initally false.
170 */
171 private static boolean commentariesWithBibles;
172
173 /**
174 * Filter for all books
175 */
176 static class AllBookFilter implements BookFilter {
177 /*
178 * (non-Javadoc)
179 *
180 * @see
181 * org.crosswire.jsword.book.BookFilter#test(org.crosswire.jsword.book
182 * .Book)
183 */
184 public boolean test(Book book) {
185 return true;
186 }
187 }
188
189 /**
190 * Filter for books by category
191 */
192 static class BookCategoryFilter implements BookFilter {
193 BookCategoryFilter(BookCategory category) {
194 this.category = category;
195 }
196
197 /*
198 * (non-Javadoc)
199 *
200 * @see
201 * org.crosswire.jsword.book.BookFilter#test(org.crosswire.jsword.book
202 * .Book)
203 */
204 public boolean test(Book book) {
205 return book.getBookCategory().equals(category) && !book.isLocked();
206 }
207
208 private BookCategory category;
209 }
210
211 /**
212 * Filter for books by category
213 */
214 static class NotBookCategoryFilter implements BookFilter {
215 NotBookCategoryFilter(BookCategory category) {
216 this.category = category;
217 }
218
219 /*
220 * (non-Javadoc)
221 *
222 * @see
223 * org.crosswire.jsword.book.BookFilter#test(org.crosswire.jsword.book
224 * .Book)
225 */
226 public boolean test(Book book) {
227 return !book.getBookCategory().equals(category) && !book.isLocked();
228 }
229
230 private BookCategory category;
231 }
232
233 /**
234 * Filter for books by feature
235 */
236 public static class BookFeatureFilter implements BookFilter {
237 public BookFeatureFilter(FeatureType feature) {
238 this.feature = feature;
239 }
240
241 /*
242 * (non-Javadoc)
243 *
244 * @see
245 * org.crosswire.jsword.book.BookFilter#test(org.crosswire.jsword.book
246 * .Book)
247 */
248 public boolean test(Book book) {
249 return book.hasFeature(feature) && !book.isLocked();
250 }
251
252 private FeatureType feature;
253 }
254
255 /**
256 * A filter that accepts Books that match two criteria.
257 */
258 public static BookFilter both(final BookFilter b1, final BookFilter b2) {
259 return new BookFilter() {
260 public boolean test(Book book) {
261 return b1.test(book) && b2.test(book);
262 }
263 };
264 }
265
266 /**
267 * A filter that accepts Books that match either of two criteria.
268 */
269 public static BookFilter either(final BookFilter b1, final BookFilter b2) {
270 return new BookFilter() {
271 public boolean test(Book book) {
272 return b1.test(book) || b2.test(book);
273 }
274 };
275 }
276
277 /**
278 * A filter that accepts Books that match by book driver.
279 */
280 public static BookFilter getBooksByDriver(final BookDriver driver) {
281 return new BookFilter() {
282 public boolean test(Book book) {
283 return book.getDriver() == driver;
284 }
285 };
286 }
287
288 /**
289 * A simple default filter that returns everything. The match parameter is a
290 * set of name value pairs like this: <br/>
291 * <code>initials=ESV;type=Bible;driverName=Sword</code><br/>
292 * Before the = there must be the name of a property on Book and after the
293 * value to match (.toString()) is called on the results of the getter.
294 *
295 * @param match
296 * a ; separated list of properties (of Book) to match
297 * @see Book
298 */
299 public static BookFilter getCustom(String match) {
300 return new CustomBookFilter(match);
301 }
302
303 /**
304 * Custom Filter
305 */
306 static class CustomBookFilter implements BookFilter {
307 /**
308 * Ctor
309 *
310 * @param match
311 * The match spec.
312 * @see BookFilters#getCustom(String)
313 */
314 public CustomBookFilter(String match) {
315 List<Test> cache = new ArrayList<Test>();
316 String[] filters = match.split(";");
317 for (int i = 0; i < filters.length; i++) {
318 cache.add(new Test(filters[i]));
319 }
320
321 tests = cache.toArray(new Test[cache.size()]);
322 }
323
324 /*
325 * (non-Javadoc)
326 *
327 * @see
328 * org.crosswire.jsword.book.BookFilter#test(org.crosswire.jsword.book
329 * .Book)
330 */
331 public boolean test(Book book) {
332 for (int i = 0; i < tests.length; i++) {
333 Test test = tests[i];
334 Object result = book.getProperty(test.property);
335 if (result == null || !test.result.equals(result.toString())) {
336 return false;
337 }
338 }
339
340 return true;
341 }
342
343 private Test[] tests;
344
345 /**
346 *
347 */
348 static class Test {
349 protected Test(String filter) {
350 String[] parts = filter.split("=");
351 if (parts.length != 2 || parts[0].length() == 0 || parts[1].length() == 0) {
352 throw new IllegalArgumentException("Filter format is 'property=value', given: " + filter);
353 }
354 this.property = parts[0];
355 this.result = parts[1];
356
357 }
358 protected Test(String property, String result) {
359 this.property = property;
360 this.result = result;
361 }
362 protected String property;
363 protected String result;
364 }
365 }
366 }
367