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   * © CrossWire Bible Society, 2008 - 2016
18   *
19   */
20  package org.crosswire.jsword.book.sword;
21  
22  import java.io.IOException;
23  import java.util.Iterator;
24  import java.util.NoSuchElementException;
25  
26  import org.crosswire.jsword.book.BookException;
27  import org.crosswire.jsword.book.sword.state.OpenFileState;
28  import org.crosswire.jsword.passage.Key;
29  import org.crosswire.jsword.passage.RestrictionType;
30  
31  /**
32   * A Backend that can be used as a global key list.
33   * 
34   * @param <T> The type of the OpenFileState that this class extends.
35   * @see gnu.lgpl.License The GNU Lesser General Public License for details.
36   * @author DM Smith
37   */
38  public abstract class AbstractKeyBackend<T extends OpenFileState> extends AbstractBackend<T> implements Key {
39      /**
40       * Simple ctor
41       * 
42       * @param sbmd
43       *            the book's metadata
44       */
45      public AbstractKeyBackend(SwordBookMetaData sbmd) {
46          super(sbmd);
47      }
48  
49      /* (non-Javadoc)
50       * @see org.crosswire.jsword.passage.Key#canHaveChildren()
51       */
52      public boolean canHaveChildren() {
53          return false;
54      }
55  
56      /* (non-Javadoc)
57       * @see org.crosswire.jsword.passage.Key#getChildCount()
58       */
59      public int getChildCount() {
60          return 0;
61      }
62  
63      /* (non-Javadoc)
64       * @see org.crosswire.jsword.passage.Key#isEmpty()
65       */
66      public boolean isEmpty() {
67          return getCardinality() == 0;
68      }
69  
70      /* (non-Javadoc)
71       * @see org.crosswire.jsword.book.sword.AbstractBackend#contains(org.crosswire.jsword.passage.Key)
72       */
73      @Override
74      public boolean contains(Key key) {
75          return indexOf(key) >= 0;
76      }
77  
78      /* (non-Javadoc)
79       * @see java.lang.Iterable#iterator()
80       */
81      public Iterator<Key> iterator() {
82          return new Iterator<Key>() {
83  
84              /* (non-Javadoc)
85               * @see java.util.Iterator#hasNext()
86               */
87              public boolean hasNext() {
88                  return here < count;
89              }
90  
91              /* (non-Javadoc)
92               * @see java.util.Iterator#next()
93               */
94              public Key next() throws NoSuchElementException {
95                  if (here >= count) {
96                      throw new NoSuchElementException();
97                  }
98                  return get(here++);
99              }
100 
101             /* (non-Javadoc)
102              * @see java.util.Iterator#remove()
103              */
104             public void remove() {
105                 throw new UnsupportedOperationException();
106             }
107 
108             private int here;
109             private int count = getCardinality();
110         };
111     }
112 
113 
114     /* (non-Javadoc)
115      * @see org.crosswire.jsword.passage.Key#addAll(org.crosswire.jsword.passage.Key)
116      */
117     public void addAll(Key key) {
118         throw new UnsupportedOperationException();
119     }
120 
121     /* (non-Javadoc)
122      * @see org.crosswire.jsword.passage.Key#removeAll(org.crosswire.jsword.passage.Key)
123      */
124     public void removeAll(Key key) {
125         throw new UnsupportedOperationException();
126     }
127 
128     /* (non-Javadoc)
129      * @see org.crosswire.jsword.passage.Key#clear()
130      */
131     public void clear() {
132         throw new UnsupportedOperationException();
133     }
134 
135     public void setAliasKey(T state, Key alias, Key source) throws IOException {
136         throw new UnsupportedOperationException();
137     }
138 
139     public void setRawText(T state, Key key, String text) throws BookException, IOException {
140         throw new UnsupportedOperationException();
141     }
142 
143     /* (non-Javadoc)
144      * @see org.crosswire.jsword.passage.Key#getParent()
145      */
146     public Key getParent() {
147         return null;
148     }
149 
150     @Override
151     public AbstractKeyBackend<T> clone() {
152         AbstractKeyBackend<T> clone = null;
153         try {
154             clone = (AbstractKeyBackend<T>) super.clone();
155         } catch (CloneNotSupportedException e) {
156             assert false : e;
157         }
158         return clone;
159     }
160 
161     /* (non-Javadoc)
162      * @see org.crosswire.jsword.passage.Key#getName()
163      */
164     public String getName() {
165         return getBookMetaData().getInitials();
166     }
167 
168     /* (non-Javadoc)
169      * @see org.crosswire.jsword.passage.Key#getName(org.crosswire.jsword.passage.Key)
170      */
171     public String getName(Key base) {
172         return getName();
173     }
174 
175     /* (non-Javadoc)
176      * @see org.crosswire.jsword.passage.Key#getOsisID()
177      */
178     public String getOsisID() {
179         return getName();
180     }
181 
182     /* (non-Javadoc)
183      * @see org.crosswire.jsword.passage.Key#getOsisRef()
184      */
185     public String getOsisRef() {
186         return getName();
187     }
188 
189    /* (non-Javadoc)
190      * @see org.crosswire.jsword.passage.Key#getRootName()
191      */
192     public String getRootName() {
193         return getName();
194     }
195 
196     /* (non-Javadoc)
197      * @see org.crosswire.jsword.passage.Key#retainAll(org.crosswire.jsword.passage.Key)
198      */
199     public void retainAll(Key key) {
200         throw new UnsupportedOperationException();
201     }
202 
203     @Override
204     public boolean equals(Object obj) {
205         // Since this can not be null
206         if (obj == null) {
207             return false;
208         }
209 
210         // Check that that is the same as this
211         // Don't use instanceOf since that breaks inheritance
212         if (!obj.getClass().equals(this.getClass())) {
213             return false;
214         }
215 
216         return compareTo((Key) obj) == 0;
217     }
218 
219     @Override
220     public int hashCode() {
221         return getName().hashCode();
222     }
223 
224     /* (non-Javadoc)
225      * @see java.lang.Comparable#compareTo(java.lang.Object)
226      */
227     public int compareTo(Key that) {
228 
229         if (this == that) {
230             return 0;
231         }
232 
233         if (that == null) {
234             // he is empty, we are not so he is greater
235             return -1;
236         }
237 
238         int ret = this.getName().compareTo(that.getName());
239 
240         if (ret != 0) {
241             return ret;
242         }
243 
244         // Compare the contents.
245         Iterator<Key> thisIter = this.iterator();
246         Iterator<Key> thatIter = that.iterator();
247 
248         Key thisfirst = null;
249         Key thatfirst = null;
250 
251         if (thisIter.hasNext()) {
252             thisfirst = thisIter.next();
253         }
254 
255         if (thatIter.hasNext()) {
256             thatfirst = thatIter.next();
257         }
258 
259         if (thisfirst == null) {
260             if (thatfirst == null) {
261                 // we are both empty, and rank the same
262                 return 0;
263             }
264             // i am empty, he is not so we are greater
265             return 1;
266         }
267 
268         if (thatfirst == null) {
269             // he is empty, we are not so he is greater
270             return -1;
271         }
272 
273         return thisfirst.getName().compareTo(thatfirst.getName());
274     }
275 
276     /* (non-Javadoc)
277      * @see org.crosswire.jsword.passage.Key#blur(int, org.crosswire.jsword.passage.RestrictionType)
278      */
279     public void blur(int by, RestrictionType restrict) {
280     }
281 
282     /**
283      * Serialization ID
284      */
285     private static final long serialVersionUID = -2782112117361556089L;
286 }
287