RocketPassage.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 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, 2005 - 2016 18 * 19 */ 20 package org.crosswire.jsword.passage; 21 22 import java.io.IOException; 23 import java.io.ObjectInputStream; 24 import java.util.Iterator; 25 26 import org.crosswire.jsword.versification.Versification; 27 28 /** 29 * A RocketPassage is a bit and heavy implementation of Passage that goes fairly 30 * quickly once let of the leash. It manages its speed by creating contained 31 * instances of DistinctPassage and RangedPassage and selects the fastest 32 * implementation for each of its methods from the 3 available. 33 * 34 * @see gnu.lgpl.License The GNU Lesser General Public License for details. 35 * @author Joe Walker 36 */ 37 public class RocketPassage extends BitwisePassage { 38 /** 39 * Create a new RocketPassage 40 * 41 * @param v11n 42 * The Versification to which this Passage belongs. 43 */ 44 public RocketPassage(Versification v11n) { 45 super(v11n); 46 } 47 48 /** 49 * Create a Verse from a human readable string. The opposite of getName(), 50 * Given any RangedPassage v1, and the following 51 * <code>RangedPassage v2 = new RangedPassage(v1.getName());</code> Then 52 * <code>v1.equals(v2);</code> Theoretically, since there are many ways of 53 * representing a RangedPassage as text string comparison along the lines 54 * of: <code>v1.getName().equals(v2.getName())</code> could be false. 55 * However since getName() is standardized this will be true. We don't need 56 * to worry about thread safety in a ctor since we don't exist yet. 57 * 58 * 59 * @param v11n 60 * The Versification to which this Passage belongs. 61 * @param refs 62 * A String containing the text of the RangedPassage 63 * @param basis 64 * The basis by which to interpret refs 65 * @throws NoSuchVerseException 66 * if refs is invalid 67 */ 68 protected RocketPassage(Versification v11n, String refs, Key basis) throws NoSuchVerseException { 69 super(v11n, refs, basis); 70 } 71 72 /** 73 * Create a Verse from a human readable string. The opposite of getName(), 74 * Given any RangedPassage v1, and the following 75 * <code>RangedPassage v2 = new RangedPassage(v1.getName());</code> Then 76 * <code>v1.equals(v2);</code> Theoretically, since there are many ways of 77 * representing a RangedPassage as text string comparison along the lines 78 * of: <code>v1.getName().equals(v2.getName())</code> could be false. 79 * However since getName() is standardized this will be true. We don't need 80 * to worry about thread safety in a ctor since we don't exist yet. 81 * 82 * 83 * @param v11n 84 * The Versification to which this Passage belongs. 85 * @param refs 86 * A String containing the text of the RangedPassage 87 * @throws NoSuchVerseException 88 * if refs is invalid 89 */ 90 protected RocketPassage(Versification v11n, String refs) throws NoSuchVerseException { 91 this(v11n, refs, null); 92 } 93 94 /* 95 * (non-Javadoc) 96 * 97 * @see org.crosswire.jsword.passage.AbstractPassage#optimizeReads() 98 */ 99 @Override 100 public void optimizeReads() { 101 raiseEventSuppresion(); 102 103 // We have to create the cached versions of these separately 104 // so that the calculations made by addAll(this) can 105 // safely call methods like countVerses() without any 106 // danger of them being optimized before the optimizations 107 // are ready for use. 108 109 DistinctPassage dtemp = new DistinctPassage(getVersification()); 110 dtemp.raiseEventSuppresion(); 111 dtemp.addAll(this); 112 dtemp.lowerEventSuppressionAndTest(); 113 114 RangedPassage rtemp = new RangedPassage(getVersification()); 115 rtemp.raiseEventSuppresion(); 116 rtemp.addAll(this); 117 rtemp.lowerEventSuppressionAndTest(); 118 119 distinct = dtemp; 120 ranged = rtemp; 121 122 // This is just an optimization so we dont need to fire any events 123 lowerEventSuppressionAndTest(); 124 } 125 126 /* 127 * (non-Javadoc) 128 * 129 * @see org.crosswire.jsword.passage.AbstractPassage#optimizeWrites() 130 */ 131 @Override 132 protected void optimizeWrites() { 133 distinct = null; 134 ranged = null; 135 } 136 137 /* 138 * (non-Javadoc) 139 * 140 * @see org.crosswire.jsword.passage.Passage#countRanges(int) 141 */ 142 @Override 143 public int countRanges(RestrictionType restrict) { 144 if (ranged != null) { 145 return ranged.countRanges(restrict); 146 } 147 148 return super.countRanges(restrict); 149 } 150 151 /* 152 * (non-Javadoc) 153 * 154 * @see org.crosswire.jsword.passage.Passage#countVerses() 155 */ 156 @Override 157 public int countVerses() { 158 if (distinct != null) { 159 return distinct.countVerses(); 160 } 161 162 return super.countVerses(); 163 } 164 165 /* 166 * (non-Javadoc) 167 * 168 * @see java.lang.Iterable#iterator() 169 */ 170 @Override 171 public Iterator<Key> iterator() { 172 if (distinct != null) { 173 return distinct.iterator(); 174 } 175 176 return super.iterator(); 177 } 178 179 /* 180 * (non-Javadoc) 181 * 182 * @see org.crosswire.jsword.passage.Passage#rangeIterator(int) 183 */ 184 @Override 185 public Iterator<VerseRange> rangeIterator(RestrictionType restrict) { 186 if (ranged != null) { 187 return ranged.rangeIterator(restrict); 188 } 189 190 return super.rangeIterator(restrict); 191 } 192 193 /* 194 * (non-Javadoc) 195 * 196 * @see org.crosswire.jsword.passage.Passage#isEmpty() 197 */ 198 @Override 199 public boolean isEmpty() { 200 if (distinct != null) { 201 return distinct.isEmpty(); 202 } 203 204 return super.isEmpty(); 205 } 206 207 /* 208 * (non-Javadoc) 209 * 210 * @see org.crosswire.jsword.passage.Passage#getVerseAt(int) 211 */ 212 @Override 213 public Verse getVerseAt(int offset) throws ArrayIndexOutOfBoundsException { 214 if (distinct != null) { 215 return distinct.getVerseAt(offset); 216 } 217 218 return super.getVerseAt(offset); 219 } 220 221 /* 222 * (non-Javadoc) 223 * 224 * @see org.crosswire.jsword.passage.Passage#getVerseRangeAt(int, int) 225 */ 226 @Override 227 public VerseRange getRangeAt(int offset, RestrictionType restrict) throws ArrayIndexOutOfBoundsException { 228 if (ranged != null) { 229 return ranged.getRangeAt(offset, restrict); 230 } 231 232 return super.getRangeAt(offset, restrict); 233 } 234 235 /* 236 * (non-Javadoc) 237 * 238 * @see org.crosswire.jsword.passage.Passage#booksInPassage() 239 */ 240 @Override 241 public int booksInPassage() { 242 if (distinct != null) { 243 return distinct.booksInPassage(); 244 } 245 246 return super.booksInPassage(); 247 } 248 249 /* 250 * (non-Javadoc) 251 * 252 * @see 253 * org.crosswire.jsword.passage.Passage#containsAll(org.crosswire.jsword 254 * .passage.Passage) 255 */ 256 @Override 257 public boolean containsAll(Passage that) { 258 if (ranged != null) { 259 return ranged.containsAll(that); 260 } 261 262 return super.containsAll(that); 263 } 264 265 /** 266 * Serialization support 267 * 268 * @param is 269 * The stream to read our state from 270 * @throws IOException 271 * if the read fails 272 * @throws ClassNotFoundException 273 * If the read data is incorrect 274 */ 275 private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException { 276 optimizeWrites(); 277 is.defaultReadObject(); 278 } 279 280 /** 281 * The contained DistinctPassage 282 */ 283 private transient DistinctPassage distinct; 284 285 /** 286 * The contained RangedPassage 287 */ 288 private transient RangedPassage ranged; 289 290 /** 291 * Serialization ID 292 */ 293 private static final long serialVersionUID = 3258125864771401268L; 294 } 295