Source code: com/eireneh/bible/passage/Passage.java
1
2 package com.eireneh.bible.passage;
3
4 import java.io.Serializable;
5 import java.io.IOException;
6 import java.io.Reader;
7 import java.io.Writer;
8 import java.util.Enumeration;
9
10 /**
11 * A Passage is a specialized Collection of Verses.
12 * The additions are:<ul>
13 * <li>List blurring
14 * <li>Range Counting and iteration (in addition to Verse counting etc)
15 * <li>List change notification, so you can register to update yourself, and
16 * this goes hand in hand with a added thread-safe contract.
17 * <li>getName() to be more VerseBase like.
18 * <li>Human readable serialization. So we can read and write to and from
19 * OLB style Passage files.
20 * </ul>
21 *
22 * <p>Passage no longer extends the Collection interface to avoid JDK 1.1/2.0
23 * portability problems, and because many of the things that a Passage does
24 * rely on consecutive Verses which are an alien concept to Collections.
25 * So users would have to use the Passage interface anyway.
26 *
27 * <p>Other arguments for and against.<ul>
28 * <li>The generic version will postpone some type errors to runtime. Is this a
29 * huge problem? Are there many syntax errors that would be lost? Probably not.
30 * <li>The specific version would stop enhancements like add("Gen 1:1");
31 * (But this is just syntactical sugar anyway).
32 * <li>The specific version allows funcionality by is-a as well as has-a.
33 * But a Passage is fundamentally different so this is not that much use.
34 * <li>At the end of the day I expect people to use getName() instead of toString()
35 * and blur(), both of which are Passage things not Collection things. So
36 * the general use of these classes is via a Passage interface not a
37 * Collections one.
38 * <li>Note that the implementations of Passage could not adhere strictly to
39 * the Collections interface in returning false from add(), remove() etc,
40 * to specify if the Collection was changed. Given ranges and the like this
41 * can get very time consuming and complex.
42 * </ul>
43 *
44 * <p>The upshot of all this is that I am removing the Collections interface from
45 * Passage, but writing a PassageCollection as a proxy.
46 *
47 * <p>I considered giving Passages names to allow for a CLI that could
48 * use named RangedPassages, however that is perhaps better left to another class.
49 *
50 * <table border='1' cellPadding='3' cellSpacing='0' width="100%">
51 * <tr><td bgColor='white'class='TableRowColor'><font size='-7'>
52 * Distribution Licence:<br />
53 * Project B is free software; you can redistribute it
54 * and/or modify it under the terms of the GNU General Public License,
55 * version 2 as published by the Free Software Foundation.<br />
56 * This program is distributed in the hope that it will be useful,
57 * but WITHOUT ANY WARRANTY; without even the implied warranty of
58 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
59 * General Public License for more details.<br />
60 * The License is available on the internet
61 * <a href='http://www.gnu.org/copyleft/gpl.html'>here</a>, by writing to
62 * <i>Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
63 * MA 02111-1307, USA</i>, Or locally at the Licence link below.<br />
64 * The copyright to this program is held by it's authors.
65 * </font></td></tr></table>
66 * @see <a href='http://www.eireneh.com/servlets/Web'>Project B Home</a>
67 * @see docs.Licence
68 * @author Joe Walker
69 * @version $Id:$
70 * @stereotype role
71 */
72 public interface Passage extends Serializable, Cloneable, PassageConstants
73 {
74 /**
75 * A Human readable version of the verse list.
76 * Uses short books names, and the shortest sensible rendering eg "Mat 3:1-4"
77 * and "Mar 1:1, 3, 5" and "3Jo, Jude"
78 * @returns a String containing a description of the verses
79 */
80 public String getName();
81
82 /**
83 * A summary of the verses in this Passage
84 * For example "10 verses in 4 books"
85 * @returns a String containing an overview of the verses
86 */
87 public String getOverview();
88
89 /**
90 * Does this Passage have 0 members
91 * @return true if the Passage is empty
92 */
93 public boolean isEmpty();
94
95 /**
96 * Returns the number of verses in this collection. Like Collection.size()
97 * This does not mean the Passage needs to use Verses, just that it understands the concept.
98 * @return the number of Verses in this collection
99 * @see Verse
100 */
101 public int countVerses();
102
103 /**
104 * Like countVerses() that counts VerseRanges instead of Verses
105 * Returns the number of fragments in this collection.
106 * This does not mean the Passage needs to use VerseRanges, just that it understands the concept.
107 * @return the number of VerseRanges in this collection
108 * @see VerseRange
109 */
110 public int countRanges();
111
112 /**
113 * Ensures that there are a maximum of <code>count</code> Verses in
114 * this Passage. If there were more than <code>count</code> Verses
115 * then a new Passage is created containing the Verses from
116 * <code>count</code>+1 onwards. If there was not greater than
117 * <code>count</code> in the Passage, then the passage remains
118 * unchanged, and null is returned.
119 * @param count The maximum number of Verses to allow in this collection
120 * @return A new Passage conatining the remaining verses or null
121 * @see Verse
122 */
123 public Passage trimVerses(int count);
124
125 /**
126 * Ensures that there are a maximum of <code>count</code> VerseRanges
127 * in this Passage. If there were more than <code>count</code>
128 * VerseRanges then a new Passage is created containing the
129 * VerseRanges from <code>count</code>+1 onwards. If there was not
130 * greater than <code>count</code> in the Passage, then the passage
131 * remains unchanged, and null is returned.
132 * @param count The maximum number of VerseRanges to allow in this collection
133 * @return A new Passage conatining the remaining verses or null
134 * @see VerseRange
135 */
136 public Passage trimRanges(int count);
137
138 /**
139 * How many books are there in this Passage
140 * @param ref The Passage to check
141 * @return The number of distinct books
142 */
143 public int booksInPassage();
144
145 /**
146 * How many chapters are there in a particular book in this Passage
147 * @param book The book to check (0 for distinct chapters in all books)
148 * @return The number of distinct chapters
149 */
150 public int chaptersInPassage(int book) throws NoSuchVerseException;
151
152 /**
153 * How many chapters are there in a particular book in this Passage
154 * Note that <code>versesInPassage(ref, 0, 0) == ref.countVerses()</code>
155 * @param book The book to check (0 for distinct chapters in all books)
156 * @param chapter The chapter to check (0 for distinct verses in all chapters)
157 * @return The number of distinct chapters
158 */
159 public int versesInPassage(int book, int chapter) throws NoSuchVerseException;
160
161 /**
162 * Get a specific Verse from this collection
163 * @param offset The verse offset (legal values are 0 to countVerses()-1)
164 * @return The Verse
165 * @throws ArrayIndexOutOfBoundsException If the offset is out of range
166 */
167 public Verse getVerseAt(int offset) throws ArrayIndexOutOfBoundsException;
168
169 /**
170 * Get a specific VerseRange from this collection
171 * @param offset The verse range offset (legal values are 0 to countRanges()-1)
172 * @return The Verse Range
173 * @throws ArrayIndexOutOfBoundsException If the offset is out of range
174 */
175 public VerseRange getVerseRangeAt(int offset) throws ArrayIndexOutOfBoundsException;
176
177 /**
178 * Iterate over the Verses in this collection
179 * @return A list enumerator
180 */
181 public Enumeration verseElements();
182
183 /**
184 * Like verseElements() that iterates over VerseRanges instead
185 * of Verses. Exactly the same data will be traversed, however using
186 * rangeIterator() will usually give less iterations (and never more)
187 * @return A list enumerator
188 */
189 public Enumeration rangeElements();
190
191 /**
192 * Returns true if this collection contains all the specified Verse
193 * @param that Verse or VerseRange that may exist in this Passage
194 * @return true if this collection contains that
195 */
196 public boolean contains(VerseBase that);
197
198 /**
199 * Add this Verse/VerseRange to this Passage
200 * @param that The Verses to be removed from this Passage
201 */
202 public void add(VerseBase that);
203
204 /**
205 * Remove this Verse/VerseRange from this Passage
206 * @param that The Verses to be removed from this Passage
207 */
208 public void remove(VerseBase that);
209
210 /**
211 * Returns true if this Passage contains all of the verses in that Passage
212 * @param that Passage to be checked for containment in this collection.
213 * @return true if this reference contains all of the Verses in that Passage
214 */
215 public boolean containsAll(Passage that);
216
217 /**
218 * Adds all that Passage's verses to this Passage
219 * @param that The Verses to be removed from this Passage
220 */
221 public void addAll(Passage that);
222
223 /**
224 * Removes all this collection's elements that are also contained in the
225 * specified collection.
226 * @param that The Verses to be removed from this Passage
227 */
228 public void removeAll(Passage that);
229
230 /**
231 * Removes all the Verses from this reference that are not in that reference
232 * specified collection.
233 * @param that The Verses to be removed from this Passage
234 */
235 public void retainAll(Passage that);
236
237 /**
238 * Removes all the verses is this Passage
239 */
240 public void clear();
241
242 /**
243 * Widen the range of the verses in this list. This is primarily for
244 * "find x within n verses of y" type applications.
245 * @param verses The number of verses to widen by
246 * @param restrict How should we restrict the blurring?
247 * @see com.eireneh.bible.passage.Passage
248 */
249 public void blur(int verses, int restrict);
250
251 /**
252 * To be compatible with humans we read/write ourselves to a file that a human can
253 * read and even edit. OLB verse.lst integration is a good goal here.
254 * @param out The stream to write to
255 * @exception java.io.IOException If the file/network etc breaks
256 * @exception com.eireneh.bible.passage.NoSuchVerseException If the file was invalid
257 */
258 public void readDescription(Reader in) throws IOException, NoSuchVerseException;
259
260 /**
261 * To be compatible with humans we read/write ourselves to a file that a human can
262 * read and even edit. OLB verse.lst integration is a good goal here.
263 * @param in The stream to read from
264 * @exception java.io.IOException If the file/network etc breaks
265 */
266 public void writeDescription(Writer out) throws IOException;
267
268 /**
269 * For preformance reasons we may well want to hint to the Passage that we
270 * have done editing it for now and that it is safe to cache certain
271 * values to speed up future reads. Any action taken by this method will be
272 * undone simply by making a future edit, and the only loss in calling
273 * optimizeReads() is a loss of time if you then persist in writing to the
274 * Passage.
275 */
276 public void optimizeReads();
277
278 /**
279 * Event Listeners - Add Listener
280 * @param li The listener to add
281 */
282 public void addPassageListener(PassageListener li);
283
284 /**
285 * Event Listeners - Remove Listener
286 * @param li The listener to remove
287 */
288 public void removePassageListener(PassageListener li);
289
290 /**
291 * I'm not sure why we have to keep on redeclaring this. But If I don't
292 * Then I get accused of attempting to reduce access level of clone();
293 * Maybe this is a bug in MS JVM. It has been behaving strangely here.
294 * @return A complete copy of ourselves
295 * @exception java.lang.CloneNotSupportedException We don't do this but our kids might
296 */
297 public Object clone() throws CloneNotSupportedException;
298 }