1
20 package org.crosswire.jsword.passage;
21
22 import java.io.BufferedReader;
23 import java.io.BufferedWriter;
24 import java.io.IOException;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.io.Reader;
28 import java.io.Writer;
29 import java.util.ArrayList;
30 import java.util.BitSet;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.NoSuchElementException;
34
35 import org.crosswire.common.util.StringUtil;
36 import org.crosswire.jsword.JSMsg;
37 import org.crosswire.jsword.JSOtherMsg;
38 import org.crosswire.jsword.versification.BibleBook;
39 import org.crosswire.jsword.versification.Versification;
40 import org.crosswire.jsword.versification.system.Versifications;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44
55 public abstract class AbstractPassage implements Passage {
56
62 protected AbstractPassage(Versification v11n) {
63 this(v11n, null);
64 }
65
66
74 protected AbstractPassage(Versification v11n, String passageName) {
75 this.v11n = v11n;
76 this.originalName = passageName;
77 this.listeners = new ArrayList<PassageListener>();
78 }
79
80
83 public Versification getVersification() {
84 return v11n;
85 }
86
87
90 public Passage reversify(Versification newVersification) {
91 if (v11n.equals(newVersification)) {
92 return this;
93 }
94 throw new UnsupportedOperationException();
95 }
96
97
100 public boolean isWhole() {
101 throw new UnsupportedOperationException();
102 }
103
104
107 public Passage getWhole() {
108 throw new UnsupportedOperationException();
109 }
110
111
114 public int compareTo(Key obj) {
115 Passage thatref = (Passage) obj;
116 if (thatref.countVerses() == 0) {
117 if (countVerses() == 0) {
118 return 0;
119 }
120 return -1;
122 }
123
124 if (countVerses() == 0) {
125 return 1;
127 }
128
129 Verse thatfirst = thatref.getVerseAt(0);
130 Verse thisfirst = getVerseAt(0);
131
132 return getVersification().distance(thatfirst, thisfirst);
133 }
134
135 @Override
136 public AbstractPassage clone() {
137 AbstractPassage copy = null;
139
140 try {
141 copy = (AbstractPassage) super.clone();
142 copy.listeners = new ArrayList<PassageListener>();
143 copy.listeners.addAll(listeners);
144
145 copy.originalName = originalName;
146 } catch (CloneNotSupportedException e) {
147 assert false : e;
148 }
149
150 return copy;
151 }
152
153 @Override
154 public boolean equals(Object obj) {
155 if (!(obj instanceof Passage)) {
162 return false;
163 }
164 Passage that = (Passage) obj;
165 return that.getOsisRef().equals(getOsisRef());
168 }
169
170 @Override
171 public int hashCode() {
172 return getOsisRef().hashCode();
173 }
174
175
178 public String getName() {
179 if (PassageUtil.isPersistentNaming() && originalName != null) {
180 return originalName;
181 }
182
183 StringBuilder retcode = new StringBuilder();
184
185 Iterator<VerseRange> it = rangeIterator(RestrictionType.NONE);
186 Verse current = null;
187 while (it.hasNext()) {
188 VerseRange range = it.next();
189 retcode.append(range.getName(current));
190
191 if (it.hasNext()) {
194 retcode.append(AbstractPassage.REF_PREF_DELIM);
195 }
196
197 current = range.getStart();
198 }
199
200 return retcode.toString();
201 }
202
203
206 public String getName(Key base) {
207 return getName();
208 }
209
210
213 public String getRootName() {
214 Iterator<VerseRange> it = rangeIterator(RestrictionType.NONE);
215 while (it.hasNext()) {
216 VerseRange range = it.next();
217 return range.getRootName();
218 }
219
220 return getName();
221 }
222
223
226 public String getOsisRef() {
227 StringBuilder retcode = new StringBuilder();
228
229 Iterator<VerseRange> it = rangeIterator(RestrictionType.NONE);
230 boolean hasNext = it.hasNext();
231 while (hasNext) {
232 Key range = it.next();
233 retcode.append(range.getOsisRef());
234
235 hasNext = it.hasNext();
236 if (hasNext) {
237 retcode.append(AbstractPassage.REF_OSIS_DELIM);
238 }
239 }
240
241 return retcode.toString();
242 }
243
244
247 public String getOsisID() {
248 StringBuilder retcode = new StringBuilder();
249
250 Iterator<VerseRange> it = rangeIterator(RestrictionType.NONE);
251 boolean hasNext = it.hasNext();
252 while (hasNext) {
253 Key range = it.next();
254 retcode.append(range.getOsisID());
255
256 hasNext = it.hasNext();
257 if (hasNext) {
258 retcode.append(AbstractPassage.REF_OSIS_DELIM);
259 }
260 }
261
262 return retcode.toString();
263 }
264
265 @Override
266 public String toString() {
267 return getName();
268 }
269
270
273 public String getOverview() {
274 return JSMsg.gettext("{0,number,integer} {0,choice,0#verses|1#verse|1<verses} in {1,number,integer} {1,choice,0#books|1#book|1<books}",
291 Integer.valueOf(countVerses()), Integer.valueOf(booksInPassage()
292 ));
293 }
294
295
298 public boolean isEmpty() {
299 return !iterator().hasNext();
301 }
302
303
306 public int countVerses() {
307 int count = 0;
308
309 for (Iterator<?> iter = iterator(); iter.hasNext(); iter.next()) {
310 count++;
311 }
312
313 return count;
314 }
315
316
319 public boolean hasRanges(RestrictionType restrict) {
320 int count = 0;
321
322 Iterator<VerseRange> it = rangeIterator(restrict);
323 while (it.hasNext()) {
324 it.next();
325 count++;
326 if (count == 2) {
327 return true;
328 }
329 }
330
331 return false;
332 }
333
334
337 public int countRanges(RestrictionType restrict) {
338 int count = 0;
339
340 Iterator<VerseRange> it = rangeIterator(restrict);
341 while (it.hasNext()) {
342 it.next();
343 count++;
344 }
345
346 return count;
347 }
348
349
352 public int booksInPassage() {
353 BibleBook currentBook = null;
355 int bookCount = 0;
356
357 for (Key aKey : this) {
358 Verse verse = (Verse) aKey;
359 if (currentBook != verse.getBook()) {
360 currentBook = verse.getBook();
361 bookCount++;
362 }
363 }
364
365 return bookCount;
366 }
367
368
371 public Verse getVerseAt(int offset) throws ArrayIndexOutOfBoundsException {
372 Iterator<Key> it = iterator();
373 Object retcode = null;
374
375 for (int i = 0; i <= offset; i++) {
376 if (!it.hasNext()) {
377 throw new ArrayIndexOutOfBoundsException(JSOtherMsg.lookupText("Index out of range (Given {0,number,integer}, Max {1,number,integer}).", Integer.valueOf(offset), Integer.valueOf(countVerses())));
378 }
379
380 retcode = it.next();
381 }
382
383 return (Verse) retcode;
384 }
385
386
389 public VerseRange getRangeAt(int offset, RestrictionType restrict) throws ArrayIndexOutOfBoundsException {
390 Iterator<VerseRange> it = rangeIterator(restrict);
391 Object retcode = null;
392
393 for (int i = 0; i <= offset; i++) {
394 if (!it.hasNext()) {
395 throw new ArrayIndexOutOfBoundsException(JSOtherMsg.lookupText("Index out of range (Given {0,number,integer}, Max {1,number,integer}).", Integer.valueOf(offset), Integer.valueOf(countVerses())));
396 }
397
398 retcode = it.next();
399 }
400
401 return (VerseRange) retcode;
402 }
403
404
407 public Iterator<VerseRange> rangeIterator(RestrictionType restrict) {
408 return new VerseRangeIterator(getVersification(), iterator(), restrict);
409 }
410
411
414 public boolean containsAll(Passage that) {
415 if (that instanceof RangedPassage) {
416 Iterator<VerseRange> iter = null;
417
418 iter = ((RangedPassage) that).rangeIterator(RestrictionType.NONE);
419 while (iter.hasNext()) {
420 if (!contains(iter.next())) {
421 return false;
422 }
423 }
424 } else {
425 Iterator<Key> iter = that.iterator();
426 while (iter.hasNext()) {
427 if (!contains(iter.next())) {
428 return false;
429 }
430 }
431
432 }
433
434 return true;
435 }
436
437
440 public Passage trimVerses(int count) {
441 optimizeWrites();
442 raiseNormalizeProtection();
443
444 int i = 0;
445 boolean overflow = false;
446
447 Passage remainder = this.clone();
448
449 for (Key verse : this) {
450 i++;
451 if (i > count) {
452 remove(verse);
453 overflow = true;
454 } else {
455 remainder.remove(verse);
456 }
457 }
458
459 lowerNormalizeProtection();
460
462 if (overflow) {
463 return remainder;
464 }
465 return null;
466 }
467
468
471 public Passage trimRanges(int count, RestrictionType restrict) {
472 optimizeWrites();
473 raiseNormalizeProtection();
474
475 int i = 0;
476 boolean overflow = false;
477
478 Passage remainder = this.clone();
479
480 Iterator<VerseRange> it = rangeIterator(restrict);
481 while (it.hasNext()) {
482 i++;
483 Key range = it.next();
484
485 if (i > count) {
486 remove(range);
487 overflow = true;
488 } else {
489 remainder.remove(range);
490 }
491 }
492
493 lowerNormalizeProtection();
494
496 if (overflow) {
497 return remainder;
498 }
499 return null;
500 }
501
502
506 public void addAll(Key key) {
507 if (key.isEmpty()) {
509 return;
511 }
512
513 optimizeWrites();
514 raiseEventSuppresion();
515 raiseNormalizeProtection();
516
517
518 if (key instanceof RangedPassage) {
519 Iterator<VerseRange> it = ((RangedPassage) key).rangeIterator(RestrictionType.NONE);
520 while (it.hasNext()) {
521 add(it.next());
523 }
524 } else {
525 for (Key subkey : key) {
526 add(subkey);
527 }
528 }
529
530 lowerNormalizeProtection();
531 if (lowerEventSuppressionAndTest()) {
532 if (key instanceof Passage) {
533 Passage that = (Passage) key;
534 fireIntervalAdded(this, that.getVerseAt(0), that.getVerseAt(that.countVerses() - 1));
535 } else if (key instanceof VerseRange) {
536 VerseRange that = (VerseRange) key;
537 fireIntervalAdded(this, that.getStart(), that.getEnd());
538 } else if (key instanceof Verse) {
539 Verse that = (Verse) key;
540 fireIntervalAdded(this, that, that);
541 }
542 }
543 }
544
545
548 public void removeAll(Key key) {
549 optimizeWrites();
550 raiseEventSuppresion();
551 raiseNormalizeProtection();
552
553 if (key instanceof RangedPassage) {
554 Iterator<VerseRange> it = ((RangedPassage) key).rangeIterator(RestrictionType.NONE);
555 while (it.hasNext()) {
556 remove(it.next());
558 }
559 } else {
560 Iterator<Key> it = key.iterator();
561 while (it.hasNext()) {
562 remove(it.next());
564 }
565 }
566
567 lowerNormalizeProtection();
568 if (lowerEventSuppressionAndTest()) {
569 if (key instanceof Passage) {
570 Passage that = (Passage) key;
571 fireIntervalRemoved(this, that.getVerseAt(0), that.getVerseAt(that.countVerses() - 1));
572 } else if (key instanceof VerseRange) {
573 VerseRange that = (VerseRange) key;
574 fireIntervalRemoved(this, that.getStart(), that.getEnd());
575 } else if (key instanceof Verse) {
576 Verse that = (Verse) key;
577 fireIntervalRemoved(this, that, that);
578 }
579 }
580 }
581
582
585 public void retainAll(Key key) {
586 optimizeWrites();
587 raiseEventSuppresion();
588 raiseNormalizeProtection();
589
590 Passage temp = this.clone();
591 for (Key verse : temp) {
592 if (!key.contains(verse)) {
593 remove(verse);
594 }
595 }
596
597 lowerNormalizeProtection();
598 if (lowerEventSuppressionAndTest()) {
599 fireIntervalRemoved(this, null, null);
600 }
601 }
602
603
606 public void clear() {
607 optimizeWrites();
608 raiseNormalizeProtection();
609
610 remove(getVersification().getAllVerses());
611
612 if (lowerEventSuppressionAndTest()) {
613 fireIntervalRemoved(this, null, null);
614 }
615 }
616
617
620 public void blur(int verses, RestrictionType restrict) {
621 optimizeWrites();
622 raiseEventSuppresion();
623 raiseNormalizeProtection();
624
625 Passage temp = this.clone();
626 Iterator<VerseRange> it = temp.rangeIterator(RestrictionType.NONE);
627
628 while (it.hasNext()) {
629 VerseRange range = restrict.blur(getVersification(), it.next(), verses, verses);
630 add(range);
631 }
632
633 lowerNormalizeProtection();
634 if (lowerEventSuppressionAndTest()) {
635 fireIntervalAdded(this, null, null);
636 }
637 }
638
639
642 public void writeDescription(Writer out) throws IOException {
643 BufferedWriter bout = new BufferedWriter(out);
644 bout.write(v11n.getName());
645 bout.newLine();
646
647 Iterator<VerseRange> it = rangeIterator(RestrictionType.NONE);
648
649 while (it.hasNext()) {
650 Key range = it.next();
651 bout.write(range.getName());
652 bout.newLine();
653 }
654
655 bout.flush();
656 }
657
658
661 public void readDescription(Reader in) throws IOException, NoSuchVerseException {
662 raiseEventSuppresion();
663 raiseNormalizeProtection();
664
665 int count = 0; BufferedReader bin = new BufferedReader(in, 8192);
669
670 String v11nName = bin.readLine();
671 v11n = Versifications.instance().getVersification(v11nName);
672
673 while (true) {
674 String line = bin.readLine();
675 if (line == null) {
676 break;
677 }
678
679 count++;
680 addVerses(line, null);
681 }
682
683 if (count == 0) {
685 return;
686 }
687
688 lowerNormalizeProtection();
689 if (lowerEventSuppressionAndTest()) {
690 fireIntervalAdded(this, getVerseAt(0), getVerseAt(countVerses() - 1));
691 }
692 }
693
694
697 public void optimizeReads() {
698 }
699
700
703 protected void optimizeWrites() {
704 }
705
706
709 public void addPassageListener(PassageListener li) {
710 synchronized (listeners) {
711 listeners.add(li);
712 }
713 }
714
715
718 public void removePassageListener(PassageListener li) {
719 synchronized (listeners) {
720 listeners.remove(li);
721 }
722 }
723
724
727 public boolean contains(Key key) {
728 Passage ref = KeyUtil.getPassage(key);
729 return containsAll(ref);
730 }
731
732
735 public int getCardinality() {
736 return countVerses();
737 }
738
739
742 public int indexOf(Key that) {
743 int index = 0;
744 for (Key key : this) {
745 if (key.equals(that)) {
746 return index;
747 }
748
749 index++;
750 }
751
752 return -1;
753 }
754
755
758 public boolean canHaveChildren() {
759 return false;
760 }
761
762
765 public int getChildCount() {
766 return 0;
767 }
768
769
772 public Key get(int index) {
773 return getVerseAt(index);
774 }
775
776
779 public Key getParent() {
780 return parent;
781 }
782
783
790 public void setParent(Key parent) {
791 this.parent = parent;
792 }
793
794
807 protected void fireIntervalAdded(Object source, Verse start, Verse end) {
808 if (suppressEvents != 0) {
809 return;
810 }
811
812 PassageEvent ev = new PassageEvent(source, PassageEvent.EventType.ADDED, start, end);
814
815 List<PassageListener> temp;
817 synchronized (listeners) {
818 temp = new ArrayList<PassageListener>();
819 temp.addAll(listeners);
820 }
821
822 for (int i = 0; i < temp.size(); i++) {
824 PassageListener rl = temp.get(i);
825 rl.versesAdded(ev);
826 }
827 }
828
829
842 protected void fireIntervalRemoved(Object source, Verse start, Verse end) {
843 if (suppressEvents != 0) {
844 return;
845 }
846
847 PassageEvent ev = new PassageEvent(source, PassageEvent.EventType.REMOVED, start, end);
849
850 List<PassageListener> temp;
852 synchronized (listeners) {
853 temp = new ArrayList<PassageListener>();
854 temp.addAll(listeners);
855 }
856
857 for (int i = 0; i < temp.size(); i++) {
859 PassageListener rl = temp.get(i);
860 rl.versesRemoved(ev);
861 }
862 }
863
864
877 protected void fireContentsChanged(Object source, Verse start, Verse end) {
878 if (suppressEvents != 0) {
879 return;
880 }
881
882 PassageEvent ev = new PassageEvent(source, PassageEvent.EventType.CHANGED, start, end);
884
885 List<PassageListener> temp;
887 synchronized (listeners) {
888 temp = new ArrayList<PassageListener>();
889 temp.addAll(listeners);
890 }
891
892 for (int i = 0; i < temp.size(); i++) {
894 PassageListener rl = temp.get(i);
895 rl.versesChanged(ev);
896 }
897 }
898
899
912 protected void addVerses(String refs, Key basis) throws NoSuchVerseException {
913 optimizeWrites();
914
915 String[] parts = StringUtil.split(refs, AbstractPassage.REF_ALLOWED_DELIMS);
916 if (parts.length == 0) {
917 return;
918 }
919
920 int start = 0;
921 VerseRange vrBasis = null;
922 if (basis instanceof Verse) {
923 vrBasis = new VerseRange(v11n, (Verse) basis);
924 } else if (basis instanceof VerseRange) {
925 vrBasis = (VerseRange) basis;
926 } else {
927 vrBasis = VerseRangeFactory.fromString(v11n, parts[0].trim());
931 add(vrBasis);
933 start = 1;
934 }
935
936 for (int i = start; i < parts.length; i++) {
939 VerseRange next = VerseRangeFactory.fromString(v11n, parts[i].trim(), vrBasis);
940 add(next);
941 vrBasis = next;
942 }
943 }
944
945
951 void normalize() {
952 }
955
956
961 public void raiseNormalizeProtection() {
962 skipNormalization++;
963
964 if (skipNormalization > 10) {
965
969 log.warn("skip_normalization={}", Integer.toString(skipNormalization));
970 }
971 }
972
973
979 public void lowerNormalizeProtection() {
980 skipNormalization--;
981
982 if (skipNormalization == 0) {
983 normalize();
984 }
985
986 assert skipNormalization >= 0;
987 }
988
989
994 public void raiseEventSuppresion() {
995 suppressEvents++;
996
997 if (suppressEvents > 10) {
998
1002 log.warn("suppress_events={}", Integer.toString(suppressEvents));
1003 }
1004 }
1005
1006
1013 public boolean lowerEventSuppressionAndTest() {
1014 suppressEvents--;
1015 assert suppressEvents >= 0;
1016
1017 return suppressEvents == 0;
1018 }
1019
1020
1030 protected static VerseRange toVerseRange(Versification v11n, Object base) throws ClassCastException {
1031 assert base != null;
1032
1033 if (base instanceof VerseRange) {
1034 return (VerseRange) base;
1035 } else if (base instanceof Verse) {
1036 return new VerseRange(v11n, (Verse) base);
1037 }
1038
1039 throw new ClassCastException(JSOtherMsg.lookupText("Can only use Verses and VerseRanges in this Collection"));
1040 }
1041
1042
1045 protected static final class VerseRangeIterator implements Iterator<VerseRange> {
1046
1049 protected VerseRangeIterator(Versification v11n, Iterator<Key> it, RestrictionType restrict) {
1050 this.v11n = v11n;
1051 this.it = it;
1052 this.restrict = restrict;
1053
1054 if (it.hasNext()) {
1055 nextVerse = (Verse) it.next();
1056 }
1057
1058 calculateNext();
1059 }
1060
1061
1064 public boolean hasNext() {
1065 return nextRange != null;
1066 }
1067
1068
1071 public VerseRange next() throws NoSuchElementException {
1072 VerseRange retcode = nextRange;
1073
1074 if (retcode == null) {
1075 throw new NoSuchElementException();
1076 }
1077
1078 calculateNext();
1079 return retcode;
1080 }
1081
1082
1085 public void remove() throws UnsupportedOperationException {
1086 throw new UnsupportedOperationException();
1087 }
1088
1089
1092 private void calculateNext() {
1093 if (nextVerse == null) {
1094 nextRange = null;
1095 return;
1096 }
1097
1098 Verse start = nextVerse;
1099 Verse end = nextVerse;
1100
1101 findnext: while (true) {
1102 if (!it.hasNext()) {
1103 nextVerse = null;
1104 break;
1105 }
1106
1107 nextVerse = (Verse) it.next();
1108
1109 if (!v11n.isAdjacentVerse(end, nextVerse)) {
1111 break;
1112 }
1113
1114 if (!restrict.isSameScope(v11n, end, nextVerse)) {
1117 break findnext;
1118 }
1119
1120 end = nextVerse;
1121 }
1122
1123 nextRange = new VerseRange(v11n, start, end);
1124 }
1125
1126
1129 private Versification v11n;
1130
1131
1134 private Iterator<Key> it;
1135
1136
1139 private VerseRange nextRange;
1140
1141
1144 private Verse nextVerse;
1145
1146
1149 private RestrictionType restrict;
1150 }
1151
1152
1174 protected void writeObjectSupport(ObjectOutputStream out) throws IOException {
1175 out.writeUTF(v11n.getName());
1177
1178 int bitwiseSize = v11n.maximumOrdinal();
1180 int rangedSize = 8 * countRanges(RestrictionType.NONE);
1181 int distinctSize = 4 * countVerses();
1182
1183 if (bitwiseSize <= rangedSize && bitwiseSize <= distinctSize) {
1185 out.writeInt(BITWISE);
1186
1187 BitSet store = new BitSet(bitwiseSize);
1188 Iterator<Key> iter = iterator();
1189 while (iter.hasNext()) {
1190 Verse verse = (Verse) iter.next();
1191 store.set(verse.getOrdinal());
1192 }
1193
1194 out.writeObject(store);
1195 } else if (distinctSize <= rangedSize) {
1196 out.writeInt(DISTINCT);
1199 out.writeInt(countVerses());
1200
1201 for (Key aKey : this) {
1203 Verse verse = (Verse) aKey;
1204 out.writeInt(verse.getOrdinal());
1205 }
1206 } else {
1207 out.writeInt(RANGED);
1210 out.writeInt(countRanges(RestrictionType.NONE));
1211
1212 Iterator<VerseRange> it = rangeIterator(RestrictionType.NONE);
1214 while (it.hasNext()) {
1215 VerseRange range = it.next();
1216 out.writeInt(range.getStart().getOrdinal());
1217 out.writeInt(range.getCardinality());
1218 }
1219 }
1220
1221 }
1225
1226
1233 private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
1234 listeners = new ArrayList<PassageListener>();
1235 originalName = null;
1236 parent = null;
1237 skipNormalization = 0;
1238 suppressEvents = 0;
1239
1240 is.defaultReadObject();
1241 }
1242
1243
1253 protected void readObjectSupport(ObjectInputStream is) throws IOException, ClassNotFoundException {
1254 raiseEventSuppresion();
1255 raiseNormalizeProtection();
1256
1257 String v11nName = is.readUTF();
1259 v11n = Versifications.instance().getVersification(v11nName);
1260
1261 int type = is.readInt();
1262 switch (type) {
1263 case BITWISE:
1264 BitSet store = (BitSet) is.readObject();
1265 for (int i = 0; i < v11n.maximumOrdinal(); i++) {
1266 if (store.get(i)) {
1267 add(v11n.decodeOrdinal(i));
1268 }
1269 }
1270 break;
1271
1272 case DISTINCT:
1273 int verses = is.readInt();
1274 for (int i = 0; i < verses; i++) {
1275 int ord = is.readInt();
1276 add(v11n.decodeOrdinal(ord));
1277 }
1278 break;
1279
1280 case RANGED:
1281 int ranges = is.readInt();
1282 for (int i = 0; i < ranges; i++) {
1283 int ord = is.readInt();
1284 int count = is.readInt();
1285 add(RestrictionType.NONE.toRange(getVersification(), v11n.decodeOrdinal(ord), count));
1286 }
1287 break;
1288
1289 default:
1290 throw new ClassCastException(JSOtherMsg.lookupText("Can only use Verses and VerseRanges in this Collection"));
1291 }
1292
1293
1296 lowerEventSuppressionAndTest();
1299 lowerNormalizeProtection();
1300 }
1301
1302
1305 private static final Logger log = LoggerFactory.getLogger(AbstractPassage.class);
1306
1307
1310 protected static final int BITWISE = 0;
1311
1312
1315 protected static final int DISTINCT = 1;
1316
1317
1320 protected static final int RANGED = 2;
1321
1322
1325 protected static final int METHOD_COUNT = 3;
1326
1327
1330 private transient Versification v11n;
1331
1332
1338 private transient Key parent;
1339
1340
1343 protected transient List<PassageListener> listeners;
1344
1345
1348 protected transient String originalName;
1349
1350
1356 protected transient int suppressEvents;
1357
1358
1362 protected transient int skipNormalization;
1363
1364
1367 public static final String REF_ALLOWED_DELIMS = ",;\n\r\t";
1368
1369
1372 public static final String REF_PREF_DELIM = ", ";
1373
1374
1377 public static final String REF_OSIS_DELIM = " ";
1378
1379
1382 private static final long serialVersionUID = -5931560451407396276L;
1383}
1384