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-2013
18   *     The copyright to this program is held by it's authors.
19   *
20   */
21  package org.crosswire.jsword.book.sword;
22  
23  import java.io.IOException;
24  import java.util.ArrayList;
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import org.crosswire.common.activate.Activator;
29  import org.crosswire.common.activate.Lock;
30  import org.crosswire.common.util.IOUtil;
31  import org.crosswire.jsword.JSOtherMsg;
32  import org.crosswire.jsword.book.BookException;
33  import org.crosswire.jsword.book.OSISUtil;
34  import org.crosswire.jsword.book.basic.AbstractBook;
35  import org.crosswire.jsword.book.filter.Filter;
36  import org.crosswire.jsword.book.sword.processing.RawTextToXmlProcessor;
37  import org.crosswire.jsword.book.sword.state.OpenFileState;
38  import org.crosswire.jsword.passage.DefaultKeyList;
39  import org.crosswire.jsword.passage.DefaultLeafKeyList;
40  import org.crosswire.jsword.passage.Key;
41  import org.crosswire.jsword.passage.NoSuchKeyException;
42  import org.jdom2.Content;
43  import org.jdom2.Element;
44  
45  /**
46   * A Sword version of Dictionary.
47   * 
48   * @see gnu.lgpl.License for license details.<br>
49   *      The copyright to this program is held by it's authors.
50   * @author Joe Walker [joe at eireneh dot com]
51   */
52  public class SwordDictionary extends AbstractBook {
53      /**
54       * Start and to as much checking as we can without using memory. (i.e.
55       * actually reading the indexes)
56       */
57      protected SwordDictionary(SwordBookMetaData sbmd, AbstractBackend backend) {
58          super(sbmd);
59  
60          this.backend = (AbstractKeyBackend) backend;
61          this.filter = sbmd.getFilter();
62          active = false;
63      }
64  
65      /* (non-Javadoc)
66       * @see org.crosswire.jsword.book.Book#getOsisIterator(org.crosswire.jsword.passage.Key, boolean)
67       */
68      public Iterator<Content> getOsisIterator(final Key key, boolean allowEmpty) throws BookException {
69  
70          assert key != null;
71          assert backend != null;
72  
73          List<Content> content = new ArrayList<Content>();
74          Element title = OSISUtil.factory().createGeneratedTitle();
75          title.addContent(key.getName());
76          content.add(title);
77  
78          OpenFileState state = null;
79          String txt = null;
80          try {
81              state = backend.initState();
82              txt = backend.readRawContent(state, key);
83          } catch (IOException e) {
84              throw new BookException(e.getMessage(), e);
85          } finally {
86              IOUtil.close(state);
87          }
88  
89          List<Content> osisContent = filter.toOSIS(this, key, txt);
90          content.addAll(osisContent);
91  
92          return content.iterator();
93      }
94  
95      /* (non-Javadoc)
96       * @see org.crosswire.jsword.book.Book#getRawText(org.crosswire.jsword.passage.Key)
97       */
98      public String getRawText(Key key) throws BookException {
99          OpenFileState state = null;
100         try {
101             state = backend.initState();
102             return backend.readRawContent(state, key);
103         } catch (IOException e) {
104            throw new BookException("Unable to obtain raw content from backend", e);
105         } finally {
106             IOUtil.close(state);
107         }
108     }
109 
110     /* (non-Javadoc)
111      * @see org.crosswire.jsword.book.Book#contains(org.crosswire.jsword.passage.Key)
112      */
113     public boolean contains(Key key) {
114         return backend != null && backend.contains(key);
115     }
116 
117     /* (non-Javadoc)
118      * @see org.crosswire.jsword.book.Book#getRawText(org.crosswire.jsword.passage.Key)
119      */
120     @Override
121     public List<Content> getOsis(Key key, RawTextToXmlProcessor processor) throws BookException {
122         checkActive();
123 
124         assert key != null;
125         assert backend != null;
126 
127         return backend.readToOsis(key, processor);
128     }
129 
130     /* (non-Javadoc)
131      * @see org.crosswire.jsword.book.Book#isWritable()
132      */
133     public boolean isWritable() {
134         return backend.isWritable();
135     }
136 
137     /* (non-Javadoc)
138      * @see org.crosswire.jsword.book.Book#setRawText(org.crosswire.jsword.passage.Key, java.lang.String)
139      */
140     public void setRawText(Key key, String rawData) throws BookException {
141         throw new BookException(JSOtherMsg.lookupText("This Book is read-only."));
142     }
143 
144     /* (non-Javadoc)
145      * @see org.crosswire.jsword.book.Book#setAliasKey(org.crosswire.jsword.passage.Key, org.crosswire.jsword.passage.Key)
146      */
147     public void setAliasKey(Key alias, Key source) throws BookException {
148         throw new BookException(JSOtherMsg.lookupText("This Book is read-only."));
149     }
150 
151     /* (non-Javadoc)
152      * @see org.crosswire.jsword.book.Book#getGlobalKeyList()
153      */
154     public Key getGlobalKeyList() {
155         checkActive();
156 
157         return backend;
158     }
159 
160     /* (non-Javadoc)
161      * @see org.crosswire.jsword.book.Book#getValidKey(java.lang.String)
162      */
163     public Key getValidKey(String name) {
164         try {
165             return getKey(name);
166         } catch (NoSuchKeyException e) {
167             return createEmptyKeyList();
168         }
169     }
170 
171     /* (non-Javadoc)
172      * @see org.crosswire.jsword.book.Book#getKey(java.lang.String)
173      */
174     public Key getKey(String text) throws NoSuchKeyException {
175         checkActive();
176 
177         int pos = backend.indexOf(new DefaultLeafKeyList(text));
178         if (pos < 0) {
179             if (backend.getCardinality() > -pos - 1) {
180                 return backend.get(-pos - 1);
181             }
182             return backend.get(backend.getCardinality() - 1);
183         }
184         return backend.get(pos);
185     }
186 
187     /* (non-Javadoc)
188      * @see org.crosswire.jsword.book.Book#createEmptyKeyList()
189      */
190     public Key createEmptyKeyList() {
191         return new DefaultKeyList();
192     }
193 
194     @Override
195     public final void activate(Lock lock) {
196         super.activate(lock);
197         active = true;
198 
199         // We don't need to activate the backend because it should be capable
200         // of doing it for itself.
201     }
202 
203     @Override
204     public final void deactivate(Lock lock) {
205         super.deactivate(lock);
206         active = false;
207     }
208 
209     /**
210      * Helper method so we can quickly activate ourselves on access
211      */
212     private void checkActive() {
213         if (!active) {
214             Activator.activate(this);
215         }
216     }
217 
218     /**
219      * Are we active
220      */
221     private boolean active;
222 
223     /**
224      * To read the data from the disk
225      */
226     private AbstractKeyBackend backend;
227 
228     /**
229      * The filter to use to convert to OSIS.
230      */
231     private Filter filter;
232 
233 }
234