| BookSet.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: BookSet.java 2054 2010-12-10 22:12:09Z dmsmith $
21 */
22 package org.crosswire.jsword.book;
23
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.Iterator;
28 import java.util.Set;
29 import java.util.TreeSet;
30
31 import org.crosswire.common.util.Filter;
32
33 /**
34 * BookSet represents a collection of descriptions about Books which may be
35 * subsetted into other BookMetaDataSets. Each set is naturally ordered.
36 *
37 * @see gnu.lgpl.License for license details.<br>
38 * The copyright to this program is held by it's authors.
39 * @author DM Smith [dmsmith555 at yahoo dot com]
40 */
41 public class BookSet extends ArrayList<Book> implements Set<Book> {
42 public BookSet() {
43 }
44
45 public BookSet(Collection<Book> books) {
46 this();
47 addAll(books);
48 }
49
50 /**
51 * Gets the sorted set of all keys which can be used for groupings. These
52 * are all the property keys across the BookMetaDatas in this list.
53 *
54 * @return the set of all keys which can be used for grouping.
55 */
56 public Set<String> getGroups() {
57 Set<String> results = new TreeSet<String>();
58 for (Book book : this) {
59 results.addAll(book.getProperties().keySet());
60 }
61 return results;
62 }
63
64 /**
65 * Get the sorted set of all values for a particular key. If there is a
66 * BookMetaData that does not have a value for that key, then null will be
67 * in the set. This can be use to categorize books that don't have that key.
68 * For example, "Language" will return all the languages for this
69 * BookMetaDataList and null for which the language is unknown.
70 *
71 * @param key
72 * @return the values for a particular key.
73 */
74 public Set<Object> getGroup(String key) {
75 Set<Object> results = new TreeSet<Object>();
76 for (Book book : this) {
77 Object property = book.getProperty(key);
78 if (property != null) {
79 results.add(property);
80 }
81 }
82 return results;
83 }
84
85 public BookSet filter(String key, Object value) {
86 return filter(new GroupFilter(key, value));
87 }
88
89 /*
90 * (non-Javadoc)
91 *
92 * @see java.util.List#add(int, java.lang.Object)
93 */
94 @Override
95 public void add(int index, Book element) {
96 // ignore the requested index
97 add(element);
98 }
99
100 /*
101 * (non-Javadoc)
102 *
103 * @see java.util.Collection#add(java.lang.Object)
104 */
105 @Override
106 public final boolean add(Book book) {
107 // Add the item only if it is not in the list.
108 // Add it into the list so that it is in sorted order.
109 int pos = Collections.binarySearch(this, book);
110 if (pos < 0) {
111 super.add(-pos - 1, book);
112 return true;
113 }
114 return false;
115 }
116
117 /*
118 * (non-Javadoc)
119 *
120 * @see java.util.Collection#addAll(java.util.Collection)
121 */
122 @Override
123 public final boolean addAll(Collection<? extends Book> c) {
124 // Might be better to add the list to the end
125 // and then sort the list.
126 // This can be revisited if the list performs badly.
127 boolean added = false;
128 for (Book book : c) {
129 if (add(book)) {
130 added = true;
131 }
132 }
133 return added;
134 }
135
136 /*
137 * (non-Javadoc)
138 *
139 * @see java.util.List#addAll(int, java.util.Collection)
140 */
141 @Override
142 public final boolean addAll(int index, Collection<? extends Book> c) {
143 // Ignore the index
144 return addAll(c);
145 }
146
147 /*
148 * (non-Javadoc)
149 *
150 * @see java.util.List#set(int, java.lang.Object)
151 */
152 @Override
153 public Book set(int index, Book element) {
154 // remove the item at the index (keep it to return it),
155 // then insert the item into the sorted list.
156 Book item = remove(index);
157 add(element);
158 return item;
159 }
160
161 public BookSet filter(Filter filter) {
162 // create a copy of the list and
163 // remove everything that fails the test.
164 BookSet listSet = (BookSet) clone();
165 Iterator<Book> iter = listSet.iterator();
166 while (iter.hasNext()) {
167 Book obj = iter.next();
168 if (!filter.test(obj)) {
169 iter.remove();
170 }
171 }
172 return listSet;
173 }
174
175 /**
176 * GroupFilter does the SQL traditional group by.
177 */
178 private static final class GroupFilter implements Filter {
179 public GroupFilter(String aKey, Object aValue) {
180 key = aKey;
181 value = aValue;
182 }
183
184 public boolean test(Object obj) {
185 Book book = (Book) obj;
186 Object property = book.getProperty(key);
187 return property != null && property.equals(value);
188 }
189
190 private String key;
191 private Object value;
192 }
193
194 /**
195 * Serialization ID
196 */
197 private static final long serialVersionUID = 3258688806185154867L;
198
199 }
200