| SwordGenBook.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: SwordGenBook.java 2222 2012-01-25 22:11:28Z dmsmith $
21 */
22 package org.crosswire.jsword.book.sword;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.crosswire.common.activate.Activator;
31 import org.crosswire.common.activate.Lock;
32 import org.crosswire.jsword.JSMsg;
33 import org.crosswire.jsword.JSOtherMsg;
34 import org.crosswire.jsword.book.BookException;
35 import org.crosswire.jsword.book.basic.AbstractBook;
36 import org.crosswire.jsword.book.filter.Filter;
37 import org.crosswire.jsword.passage.DefaultKeyList;
38 import org.crosswire.jsword.passage.Key;
39 import org.crosswire.jsword.passage.NoSuchKeyException;
40 import org.crosswire.jsword.passage.ReadOnlyKeyList;
41 import org.jdom.Content;
42
43 /**
44 * A Sword version of Dictionary.
45 *
46 * @see gnu.lgpl.License for license details.<br>
47 * The copyright to this program is held by it's authors.
48 * @author Joe Walker [joe at eireneh dot com]
49 */
50 public class SwordGenBook extends AbstractBook {
51 /**
52 * Start and to as much checking as we can without using memory. (i.e.
53 * actually reading the indexes)
54 */
55 protected SwordGenBook(SwordBookMetaData sbmd, AbstractBackend backend) {
56 super(sbmd);
57
58 this.backend = backend;
59 this.filter = sbmd.getFilter();
60 map = null;
61 set = null;
62 global = null;
63 active = false;
64 }
65
66 /* (non-Javadoc)
67 * @see org.crosswire.jsword.book.basic.AbstractBook#activate(org.crosswire.common.activate.Lock)
68 */
69 @Override
70 public final void activate(Lock lock) {
71 super.activate(lock);
72
73 set = backend.readIndex();
74
75 map = new HashMap<String, Key>();
76 for (Key key : set) {
77 map.put(key.getName(), key);
78 }
79
80 global = new ReadOnlyKeyList(set, false);
81
82 active = true;
83
84 // We don't need to activate the backend because it should be capable
85 // of doing it for itself.
86 }
87
88 /* (non-Javadoc)
89 * @see org.crosswire.jsword.book.basic.AbstractBook#deactivate(org.crosswire.common.activate.Lock)
90 */
91 @Override
92 public final void deactivate(Lock lock) {
93 super.deactivate(lock);
94
95 map = null;
96 set = null;
97 global = null;
98
99 Activator.deactivate(backend);
100
101 active = false;
102 }
103
104 /* (non-Javadoc)
105 * @see org.crosswire.jsword.book.Book#getOsisIterator(org.crosswire.jsword.passage.Key, boolean)
106 */
107 public Iterator<Content> getOsisIterator(Key key, boolean allowEmpty) throws BookException {
108 checkActive();
109
110 assert key != null;
111 assert backend != null;
112
113 List<Content> content = new ArrayList<Content>();
114
115 String txt = backend.getRawText(key);
116
117 List<Content> osisContent = filter.toOSIS(this, key, txt);
118 content.addAll(osisContent);
119
120 return content.iterator();
121 }
122
123 /* (non-Javadoc)
124 * @see org.crosswire.jsword.book.Book#contains(org.crosswire.jsword.passage.Key)
125 */
126 public boolean contains(Key key) {
127 return backend != null && backend.contains(key);
128 }
129
130 /* (non-Javadoc)
131 * @see org.crosswire.jsword.book.Book#getRawText(org.crosswire.jsword.passage.Key)
132 */
133 public String getRawText(Key key) throws BookException {
134 checkActive();
135
136 assert key != null;
137 assert backend != null;
138
139 return backend.getRawText(key);
140 }
141
142 /* (non-Javadoc)
143 * @see org.crosswire.jsword.book.Book#isWritable()
144 */
145 public boolean isWritable() {
146 return backend.isWritable();
147 }
148
149 /* (non-Javadoc)
150 * @see org.crosswire.jsword.book.Book#setRawText(org.crosswire.jsword.passage.Key, java.lang.String)
151 */
152 public void setRawText(Key key, String rawData) throws BookException {
153 throw new BookException(JSOtherMsg.lookupText("This Book is read-only."));
154 }
155
156 /* (non-Javadoc)
157 * @see org.crosswire.jsword.book.Book#setAliasKey(org.crosswire.jsword.passage.Key, org.crosswire.jsword.passage.Key)
158 */
159 public void setAliasKey(Key alias, Key source) throws BookException {
160 throw new BookException(JSOtherMsg.lookupText("This Book is read-only."));
161 }
162
163 /* (non-Javadoc)
164 * @see org.crosswire.jsword.passage.KeyFactory#getGlobalKeyList()
165 */
166 public Key getGlobalKeyList() {
167 checkActive();
168
169 return global;
170 }
171
172 /* (non-Javadoc)
173 * @see org.crosswire.jsword.passage.KeyFactory#getValidKey(java.lang.String)
174 */
175 public Key getValidKey(String name) {
176 try {
177 return getKey(name);
178 } catch (NoSuchKeyException e) {
179 return createEmptyKeyList();
180 }
181 }
182
183 /* (non-Javadoc)
184 * @see org.crosswire.jsword.passage.KeyFactory#getKey(java.lang.String)
185 */
186 public Key getKey(String text) throws NoSuchKeyException {
187 checkActive();
188
189 Key key = map.get(text);
190 if (key != null) {
191 return key;
192 }
193
194 // First check for keys that match ignoring case
195 for (String keyName : map.keySet()) {
196 if (keyName.equalsIgnoreCase(text)) {
197 return map.get(keyName);
198 }
199 }
200
201 // Next keys that start with the given text
202 for (String keyName : map.keySet()) {
203 if (keyName.startsWith(text)) {
204 return map.get(keyName);
205 }
206 }
207
208 // Next try keys that contain the given text
209 for (String keyName : map.keySet()) {
210 if (keyName.indexOf(text) != -1) {
211 return map.get(keyName);
212 }
213 }
214
215 // TRANSLATOR: Error condition: Indicates that something could not be found in the book.
216 // {0} is a placeholder for the unknown key.
217 // {1} is the short name of the book
218 throw new NoSuchKeyException(JSMsg.gettext("No entry for '{0}' in {1}.", text, getInitials()));
219 }
220
221 /* (non-Javadoc)
222 * @see org.crosswire.jsword.passage.KeyFactory#createEmptyKeyList()
223 */
224 public Key createEmptyKeyList() {
225 return new DefaultKeyList();
226 }
227
228 /**
229 * Helper method so we can quickly activate ourselves on access
230 */
231 private void checkActive() {
232 if (!active) {
233 Activator.activate(this);
234 }
235 }
236
237 /**
238 * The global key list
239 */
240 private Key global;
241
242 /**
243 * Are we active
244 */
245 private boolean active;
246
247 /**
248 * So we can quickly find a Key given the text for the key
249 */
250 private Map<String, Key> map;
251
252 /**
253 * So we can implement getIndex() easily
254 */
255 private Key set;
256
257 /**
258 * To read the data from the disk
259 */
260 private AbstractBackend backend;
261
262 /**
263 * The filter to use to convert to OSIS.
264 */
265 private Filter filter;
266 }
267