org.crosswire.jsword.passage

## Interface Passage

- All Superinterfaces:
    Cloneable, Comparable<Key>, Iterable<Key>, Key, Serializable, VerseKey<Passage>
  All Known Implementing Classes:
    AbstractPassage, BitwisePassage, DistinctPassage, PassageTally, RangedPassage, ReadOnlyPassage, RocketPassage, SynchronizedPassage

      public interface Passage
      extends VerseKey<Passage>

  A Passage is a specialized Collection of Verses. The additions are:
  - List blurring
  - Range Counting and iteration (in addition to Verse counting etc)
  - List change notification, so you can register to update yourself, and this goes hand in hand with a added thread-safe contract.
  - getName() to be more VerseBase like.
  - Human readable serialization. So we can read and write to and from OLB style Passage files.

  Passage no longer extends the Collection interface to avoid J2SE 1.1/1.2 portability problems, and because many of the things that a Passage does rely on consecutive Verses which are an alien concept to Collections. So users would have to use the Passage interface anyway.

  Other arguments for and against.

  - The generic version will postpone some type errors to runtime. Is this a huge problem? Are there many syntax errors that would be lost? Probably not.
  - The specific version would stop enhancements like add("Gen 1:1"); (But this is just syntactical sugar anyway).
  - The specific version allows functionality by is-a as well as has-a. But a Passage is fundamentally different so this is not that much use.
  - At the end of the day I expect people to use getName() instead of toString() and blur(), both of which are Passage things not Collection things. So the general use of these classes is via a Passage interface not a Collections one.
  - Note that the implementations of Passage could not adhere strictly to the Collections interface in returning false from add(), remove() etc, to specify if the Collection was changed. Given ranges and the like this can get very time consuming and complex.

  The upshot of all this is that I am removing the Collections interface from Passage.

  I considered giving Passages names to allow for a CLI that could use named RangedPassages, however that is perhaps better left to another class.

  Author:
    Joe Walker
  See Also:
    `The GNU Lesser General Public License for details.`

- - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `add(Key that)` Add this Verse/VerseRange to this Passage
    `void` | `addPassageListener(PassageListener li)` Event Listeners - Add Listener
    `int` | `booksInPassage()` How many books are there in this Passage
    `boolean` | `contains(Key that)` Returns true if this collection contains all the specified Verse
    `boolean` | `containsAll(Passage that)` Returns true if this Passage contains all of the verses in that Passage
    `int` | `countRanges(RestrictionType restrict)` Like countVerses() that counts VerseRanges instead of Verses Returns the number of fragments in this collection.
    `int` | `countVerses()` Returns the number of verses in this collection.
    `String` | `getOverview()` A summary of the verses in this Passage For example "10 verses in 4 books"
    `VerseRange` | `getRangeAt(int offset, RestrictionType restrict)` Get a specific VerseRange from this collection
    `Verse` | `getVerseAt(int offset)` Get a specific Verse from this collection
    `boolean` | `hasRanges(RestrictionType restrict)` Determine whether there are two or more ranges.
    `void` | `optimizeReads()` For performance reasons we may well want to hint to the Passage that we have done editing it for now and that it is safe to cache certain values to speed up future reads.
    `Iterator<VerseRange>` | `rangeIterator(RestrictionType restrict)` Like iterator() that iterates over VerseRanges instead of Verses.
    `void` | `readDescription(Reader in)` To be compatible with humans we read/write ourselves to a file that a human can read and even edit.
    `void` | `remove(Key that)` Remove this Verse/VerseRange from this Passage
    `void` | `removePassageListener(PassageListener li)` Event Listeners - Remove Listener
    `Passage` | `trimRanges(int count, RestrictionType restrict)` Ensures that there are a maximum of `count` VerseRanges in this Passage.
    `Passage` | `trimVerses(int count)` Ensures that there are a maximum of `count` Verses in this Passage.
    `void` | `writeDescription(Writer out)` To be compatible with humans we read/write ourselves to a file that a human can read and even edit.

    - ### Methods inherited from interface org.crosswire.jsword.passage.VerseKey

      `getVersification, getWhole, isWhole, reversify`

    - ### Methods inherited from interface org.crosswire.jsword.passage.Key

      `addAll, blur, canHaveChildren, clear, clone, equals, get, getCardinality, getChildCount, getName, getName, getOsisID, getOsisRef, getParent, getRootName, hashCode, indexOf, isEmpty, removeAll, retainAll`

    - ### Methods inherited from interface java.lang.Comparable

      `compareTo`

    - ### Methods inherited from interface java.lang.Iterable

      `iterator`

- - ### Method Detail

    - #### getOverview

          String getOverview()

      A summary of the verses in this Passage For example "10 verses in 4 books"
      Returns:
        a String containing an overview of the verses

    - #### countVerses

          int countVerses()

      Returns the number of verses in this collection. Like Collection.size() This does not mean the Passage needs to use Verses, just that it understands the concept.
      Returns:
        the number of Verses in this collection
      See Also:
        `Verse`

    - #### hasRanges

          boolean hasRanges(RestrictionType restrict)

      Determine whether there are two or more ranges.
      Parameters:
        `restrict` - Do we break ranges at chapter/book boundaries
      Returns:
        whether there are two or more ranges
      See Also:
        `VerseRange`

    - #### countRanges

          int countRanges(RestrictionType restrict)

      Like countVerses() that counts VerseRanges instead of Verses Returns the number of fragments in this collection. This does not mean the Passage needs to use VerseRanges, just that it understands the concept.
      Parameters:
        `restrict` - Do we break ranges at chapter/book boundaries
      Returns:
        the number of VerseRanges in this collection
      See Also:
        `VerseRange`

    - #### trimVerses

          Passage trimVerses(int count)

      Ensures that there are a maximum of `count` Verses in this Passage. If there were more than `count` Verses then a new Passage is created containing the Verses from `count`+1 onwards. If there was not greater than `count` in the Passage, then the passage remains unchanged, and null is returned.
      Parameters:
        `count` - The maximum number of Verses to allow in this collection
      Returns:
        A new Passage containing the remaining verses or null
      See Also:
        `Verse`

    - #### trimRanges

          Passage trimRanges(int count,
                           RestrictionType restrict)

      Ensures that there are a maximum of `count` VerseRanges in this Passage. If there were more than `count` VerseRanges then a new Passage is created containing the VerseRanges from `count`+1 onwards. If there was not greater than `count` in the Passage, then the passage remains unchanged, and null is returned.
      Parameters:
        `count` - The maximum number of VerseRanges to allow in this collection
        `restrict` - Do we break ranges at chapter/book boundaries
      Returns:
        A new Passage containing the remaining verses or null
      See Also:
        `VerseRange`

    - #### booksInPassage

          int booksInPassage()

      How many books are there in this Passage
      Returns:
        The number of distinct books

    - #### getVerseAt

          Verse getVerseAt(int offset)
                           throws ArrayIndexOutOfBoundsException

      Get a specific Verse from this collection
      Parameters:
        `offset` - The verse offset (legal values are 0 to countVerses()-1)
      Returns:
        The Verse
      Throws:
        `ArrayIndexOutOfBoundsException` - If the offset is out of range

    - #### getRangeAt

          VerseRange getRangeAt(int offset,
                              RestrictionType restrict)
                                throws ArrayIndexOutOfBoundsException

      Get a specific VerseRange from this collection
      Parameters:
        `offset` - The verse range offset (legal values are 0 to countRanges()-1)
        `restrict` - Do we break ranges at chapter/book boundaries
      Returns:
        The Verse Range
      Throws:
        `ArrayIndexOutOfBoundsException` - If the offset is out of range

    - #### rangeIterator

          Iterator<VerseRange> rangeIterator(RestrictionType restrict)

      Like iterator() that iterates over VerseRanges instead of Verses. Exactly the same data will be traversed, however using rangeIterator() will usually give fewer iterations (and never more)
      Parameters:
        `restrict` - Do we break ranges over chapters
      Returns:
        A list enumerator

    - #### contains

          boolean contains(Key that)

      Returns true if this collection contains all the specified Verse
      Specified by:
        `contains` in interface `Key`
      Parameters:
        `that` - Verse or VerseRange that may exist in this Passage
      Returns:
        true if this collection contains that

    - #### add

          void add(Key that)

      Add this Verse/VerseRange to this Passage
      Parameters:
        `that` - The Verses to be added from this Passage

    - #### remove

          void remove(Key that)

      Remove this Verse/VerseRange from this Passage
      Parameters:
        `that` - The Verses to be removed from this Passage

    - #### containsAll

          boolean containsAll(Passage that)

      Returns true if this Passage contains all of the verses in that Passage
      Parameters:
        `that` - Passage to be checked for containment in this collection.
      Returns:
        true if this reference contains all of the Verses in that Passage

    - #### readDescription

          void readDescription(Reader in)
                               throws IOException,
                                      NoSuchVerseException

      To be compatible with humans we read/write ourselves to a file that a human can read and even edit. OLB verse.lst integration is a good goal here.
      Parameters:
        `in` - The stream to read from
      Throws:
        `IOException` - If the file/network etc breaks
        `NoSuchVerseException` - If the file was invalid

    - #### writeDescription

          void writeDescription(Writer out)
                                throws IOException

      To be compatible with humans we read/write ourselves to a file that a human can read and even edit. OLB verse.lst integration is a good goal here.
      Parameters:
        `out` - The stream to write to
      Throws:
        `IOException` - If the file/network etc breaks

    - #### optimizeReads

          void optimizeReads()

      For performance reasons we may well want to hint to the Passage that we have done editing it for now and that it is safe to cache certain values to speed up future reads. Any action taken by this method will be undone simply by making a future edit, and the only loss in calling optimizeReads() is a loss of time if you then persist in writing to the Passage.

    - #### addPassageListener

          void addPassageListener(PassageListener li)

      Event Listeners - Add Listener
      Parameters:
        `li` - The listener to add

    - #### removePassageListener

          void removePassageListener(PassageListener li)

      Event Listeners - Remove Listener
      Parameters:
        `li` - The listener to remove