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