1
20 package org.crosswire.jsword.passage;
21
22 import java.io.IOException;
23 import java.io.ObjectInputStream;
24 import java.io.ObjectOutputStream;
25 import java.util.BitSet;
26 import java.util.Iterator;
27 import java.util.NoSuchElementException;
28
29 import org.crosswire.jsword.versification.Versification;
30 import org.crosswire.jsword.versification.system.Versifications;
31
32
51 public class BitwisePassage extends AbstractPassage {
52
59 public BitwisePassage(Versification v11n) {
60 super(v11n);
61 store = new BitSet(v11n.maximumOrdinal() + 1);
62 }
63
64
84 protected BitwisePassage(Versification v11n, String refs, Key basis) throws NoSuchVerseException {
85 super(v11n, refs);
86 store = new BitSet(v11n.maximumOrdinal() + 1);
87 addVerses(refs, basis);
88 }
89
90
108 protected BitwisePassage(Versification v11n, String refs) throws NoSuchVerseException {
109 this(v11n, refs, null);
110 }
111
112 @Override
113 public BitwisePassage clone() {
114 BitwisePassage copy = (BitwisePassage) super.clone();
116
117 copy.store = (BitSet) store.clone();
118
119 return copy;
120 }
121
122 @Override
123 public int countVerses() {
124 return store.cardinality();
125 }
126
127 @Override
128 public boolean isEmpty() {
129 return store.isEmpty();
130 }
131
132
135 public Iterator<Key> iterator() {
136 return new VerseIterator();
137 }
138
139 @Override
140 public boolean contains(Key obj) {
141 for (Key aKey : obj) {
142 Verse verse = (Verse) aKey;
143 if (!store.get(verse.getOrdinal())) {
144 return false;
145 }
146 }
147
148 return true;
149 }
150
151
154 public void add(Key obj) {
155 optimizeWrites();
156
157 Verse firstVerse = null;
158 Verse lastVerse = null;
159 for (Key aKey : obj) {
160 lastVerse = (Verse) aKey;
161 if (firstVerse == null) {
162 firstVerse = lastVerse;
163 }
164 store.set(lastVerse.getOrdinal());
165 }
166
167 if (suppressEvents == 0) {
170 fireIntervalAdded(this, firstVerse, lastVerse);
171 }
172 }
173
174
181 public void addVersifiedOrdinal(int ordinal) {
182 optimizeWrites();
183 store.set(ordinal);
184
185 if (suppressEvents == 0) {
188 Verse verse = getVersification().decodeOrdinal(ordinal);
189 fireIntervalAdded(this, verse, verse);
190 }
191 }
192
193
196 public void remove(Key obj) {
197 optimizeWrites();
198
199 Verse firstVerse = null;
200 Verse lastVerse = null;
201 for (Key aKey : obj) {
202 lastVerse = (Verse) aKey;
203 if (firstVerse == null) {
204 firstVerse = lastVerse;
205 }
206 store.clear(lastVerse.getOrdinal());
207 }
208
209 if (suppressEvents == 0) {
212 fireIntervalAdded(this, firstVerse, lastVerse);
213 }
214 }
215
216 @Override
217 public void addAll(Key key) {
218 if (key.isEmpty()) {
220 return;
222 }
223
224 optimizeWrites();
225
226 if (key instanceof BitwisePassage) {
227 BitwisePassage thatRef = (BitwisePassage) key;
228 store.or(thatRef.store);
229 } else {
230 super.addAll(key);
231 }
232
233 if (suppressEvents == 0 && !key.isEmpty()) {
236 if (key instanceof Passage) {
237 Passage that = (Passage) key;
238 fireIntervalAdded(this, that.getVerseAt(0), that.getVerseAt(that.countVerses() - 1));
239 } else if (key instanceof VerseRange) {
240 VerseRange that = (VerseRange) key;
241 fireIntervalAdded(this, that.getStart(), that.getEnd());
242 } else if (key instanceof Verse) {
243 Verse that = (Verse) key;
244 fireIntervalAdded(this, that, that);
245 }
246 }
247 }
248
249 @Override
250 public void removeAll(Key key) {
251 optimizeWrites();
252
253 if (key instanceof BitwisePassage) {
254 BitwisePassage thatRef = (BitwisePassage) key;
255
256 store.andNot(thatRef.store);
257 } else {
258 super.removeAll(key);
259 }
260
261 if (suppressEvents == 0 && !key.isEmpty()) {
264 if (key instanceof Passage) {
265 Passage that = (Passage) key;
266 fireIntervalRemoved(this, that.getVerseAt(0), that.getVerseAt(that.countVerses() - 1));
267 } else if (key instanceof VerseRange) {
268 VerseRange that = (VerseRange) key;
269 fireIntervalRemoved(this, that.getStart(), that.getEnd());
270 } else if (key instanceof Verse) {
271 Verse that = (Verse) key;
272 fireIntervalRemoved(this, that, that);
273 }
274 }
275 }
276
277 @Override
278 public void retainAll(Key key) {
279 optimizeWrites();
280
281 BitSet thatStore = null;
282 if (key instanceof BitwisePassage) {
283 thatStore = ((BitwisePassage) key).store;
284 } else {
285 Versification v11n = getVersification();
286 thatStore = new BitSet(v11n.maximumOrdinal() + 1);
287
288 for (Key aKey : key) {
289 int ord = ((Verse) aKey).getOrdinal();
290 if (store.get(ord)) {
291 thatStore.set(ord);
292 }
293 }
294 }
295 store.and(thatStore);
296
297 fireIntervalRemoved(this, null, null);
298 }
299
300 @Override
301 public void clear() {
302 optimizeWrites();
303
304 store.clear();
305
306 fireIntervalRemoved(this, null, null);
307 }
308
309 @Override
310 public void blur(int verses, RestrictionType restrict) {
311 assert verses >= 0;
312 optimizeWrites();
313 raiseNormalizeProtection();
314
315 if (!restrict.equals(RestrictionType.NONE)) {
316 super.blur(verses, restrict);
317 } else {
318 optimizeWrites();
319 raiseEventSuppresion();
320 raiseNormalizeProtection();
321
322 int maximumOrdinal = getVersification().maximumOrdinal();
323 BitSet newStore = new BitSet(maximumOrdinal + 1);
324
325 for (int i = store.nextSetBit(0); i >= 0; i = store.nextSetBit(i + 1)) {
326 int start = Math.max(1, i - verses);
327 int end = Math.min(maximumOrdinal, i + verses);
328
329 for (int j = start; j <= end; j++) {
330 newStore.set(j);
331 }
332 }
333
334 store = newStore;
335
336 lowerNormalizeProtection();
337 if (lowerEventSuppressionAndTest()) {
338 fireIntervalAdded(this, null, null);
339 }
340 }
341 }
342
343
349 private final class VerseIterator implements Iterator<Key> {
350
353 VerseIterator() {
354 next = -1;
355 calculateNext();
356 }
357
358
361 public boolean hasNext() {
362 return next >= 0;
363 }
364
365
368 public Key next() throws NoSuchElementException {
369 if (!hasNext()) {
370 throw new NoSuchElementException();
371 }
372
373 Key retcode = getVersification().decodeOrdinal(next);
374 calculateNext();
375
376 return retcode;
377 }
378
379
382 public void remove() throws UnsupportedOperationException {
383 store.clear(next);
384 }
385
386
389 private void calculateNext() {
390 next = store.nextSetBit(next + 1);
391 }
392
393
396 private int next;
397 }
398
399
409 private void writeObject(ObjectOutputStream out) throws IOException {
410 out.defaultWriteObject();
411
412 out.writeUTF(getVersification().getName());
414
415 writeObjectSupport(out);
416 }
417
418
430 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
431 optimizeWrites();
432
433 in.defaultReadObject();
434
435 String v11nName = in.readUTF();
437 Versification v11n = Versifications.instance().getVersification(v11nName);
438
439 store = new BitSet(v11n.maximumOrdinal() + 1);
440
441 readObjectSupport(in);
442 }
443
444
447 private static final long serialVersionUID = -5931560451407396276L;
448
449
452 protected transient BitSet store;
453 }
454