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