org.crosswire.jsword.book.sword

## Class ZVerseBackend

- java.lang.Object
- - org.crosswire.jsword.book.sword.AbstractBackend<ZVerseBackendState>
  - - org.crosswire.jsword.book.sword.ZVerseBackend

- All Implemented Interfaces:
    Backend<ZVerseBackendState>, StatefulFileBackedBackend<ZVerseBackendState>

      public class ZVerseBackend
      extends AbstractBackend<ZVerseBackendState>

  A backend to read compressed data verse based files. While the text file contains data compressed with ZIP or LZSS, it cannot be uncompressed using a stand alone zip utility, such as WinZip or gzip. The reason for this is that the data file is a concatenation of blocks of compressed data.

  The blocks can either be "b", book (aka testament); "c", chapter or "v", verse. The choice is a matter of trade offs. The program needs to uncompress a block into memory. Having it at the book level is very memory expensive. Having it at the verse level is very disk expensive, but takes the least amount of memory. The most common is chapter.

  In order to find the data in the text file, we need to find the block. The first index (idx) is used for this. Each verse is indexed to a tuple (block number, verse start, verse size). This data allows us to find the correct block, and to extract the verse from the uncompressed block, but it does not help us uncompress the block.

  Once the block is known, then the next index (comp) gives the location of the compressed block, its compressed size and its uncompressed size.

  There are 3 files for each testament, 2 (idx and comp) are indexes into the third (text) which contains the data. The key into each index is the verse index within that testament, which is determined by book, chapter and verse of that key.

  All unsigned numbers are stored 2-complement, little endian.

  Then proceed as follows, at all times working on the set of files for the testament in question:

  The three files are laid out in the following fashion:
  - The idx file has one entry per verse in the versification. The number of verses varies by versification and testament. Each entry describes the compressed block in which it is found, the start of the verse in the uncompressed block and the length of the verse.
    - Block number - 32-bit/4-bytes - the number of the entry in the comp file.
    - Verse start - 32 bit/4-bytes - the start of the verse in the uncompressed block in the dat file.
    - Verse length - 16 bit/4-bytes - the length of the verse in the uncompressed block from the dat file.
    Algorithm:
    - Given the ordinal value of the verse, seek to the ordinal * 10 and read 10 bytes.
    - Decode the 10 bytes as Block Number, Verse start and length
  - The comp file has one entry per block. Each entry describes the location of a compressed block, giving its start and size in the next file.
    - Block Start - 32-bit/4-byte - the start of the block in the dat file
    - Compressed Block Size - 32-bit/4-byte - the size of the compressed block in the dat file
    - Uncompressed Block Size - 32-bit/4-byte - the size of the block after uncompressing
    Algorithm:
    - Given a block number, seek to block-index * 12 and read 12 bytes
    - Decode the 12 bytes as Block Start, Compressed Block Size and Uncompressed Block Size
  - The dat file is compressed blocks of verses.
    Algorithm:
    - Given the entry from the comp file, seek to the start and read the indicated compressed block size
    - If the book is enciphered it, decipher it.
    - Uncompress the block, using the uncompressed size as an optimization.
    - Using the verse start, seek to that location in the uncompressed block and read the indicated verse size.
    - Convert the bytes to a String using the books indicated charset.
  Author:
    Joe Walker, DM Smith
  See Also:
    `The GNU Lesser General Public License for details.`

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `private BlockType` | `blockType` Whether the book is blocked by Book, Chapter or Verse.
    `private static int` | `COMP_ENTRY_SIZE` How many bytes in the comp index?
    `private static int` | `IDX_ENTRY_SIZE` How many bytes in the idx index?
    `private static org.slf4j.Logger` | `log` The log stream

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `ZVerseBackend(SwordBookMetaData sbmd, BlockType blockType)` Simple ctor

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `boolean` | `contains(Key key)` Determine whether this Book contains the key in question
    `void` | `dumpCompRaf(RandomAccessFile raf)` Experimental code.
    `void` | `dumpIdxRaf(Versification v11n, int ordinalStart, RandomAccessFile raf)` Experimental code.
    `Key` | `getGlobalKeyList()` Gets the fast global key list, and if this operation is not supported, throws a `UnsupportedOperationException`
    `int` | `getRawTextLength(Key key)` Determine the size of the raw data for the key in question.
    `ZVerseBackendState` | `initState()` Initialises the state required to read from files, specific to each different backend
    `String` | `readRawContent(ZVerseBackendState rafBook, Key key)`
    `void` | `setAliasKey(ZVerseBackendState rafBook, Key alias, Key source)` Sets alias for a comment on a verse range I.e.
    `void` | `setRawText(ZVerseBackendState rafBook, Key key, String text)` Set the text allotted for the given verse

    - ### Methods inherited from class org.crosswire.jsword.book.sword.AbstractBackend

      `create, decipher, encipher, getBookMetaData, getRawText, isSupported, isWritable, readIndex, readToOsis, setAliasKey`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### blockType

          private final BlockType blockType

      Whether the book is blocked by Book, Chapter or Verse.

    - #### IDX_ENTRY_SIZE

          private static final int IDX_ENTRY_SIZE

      How many bytes in the idx index?
      See Also:
        Constant Field Values

    - #### COMP_ENTRY_SIZE

          private static final int COMP_ENTRY_SIZE

      How many bytes in the comp index?
      See Also:
        Constant Field Values

    - #### log

          private static final org.slf4j.Logger log

      The log stream

  - ### Constructor Detail

    - #### ZVerseBackend

          public ZVerseBackend(SwordBookMetaData sbmd,
                       BlockType blockType)

      Simple ctor
      Parameters:
        `sbmd` -
        `blockType` -

  - ### Method Detail

    - #### contains

          public boolean contains(Key key)

      Description copied from interface: `Backend`
      Determine whether this Book contains the key in question
      Specified by:
        `contains` in interface `Backend<ZVerseBackendState>`
      Specified by:
        `contains` in class `AbstractBackend<ZVerseBackendState>`
      Parameters:
        `key` - The key whose presence is desired.
      Returns:
        true if the Book contains the key

    - #### getRawTextLength

          public int getRawTextLength(Key key)

      Description copied from interface: `Backend`
      Determine the size of the raw data for the key in question. This method may not be faster than getting the raw text and getting its size.
      Specified by:
        `getRawTextLength` in interface `Backend<ZVerseBackendState>`
      Overrides:
        `getRawTextLength` in class `AbstractBackend<ZVerseBackendState>`
      Parameters:
        `key` - The key whose raw data length is desired.
      Returns:
        The length of the raw data, 0 if not a valid key.

    - #### getGlobalKeyList

          public Key getGlobalKeyList()
                               throws BookException

      Description copied from interface: `Backend`
      Gets the fast global key list, and if this operation is not supported, throws a `UnsupportedOperationException`
      Specified by:
        `getGlobalKeyList` in interface `Backend<ZVerseBackendState>`
      Overrides:
        `getGlobalKeyList` in class `AbstractBackend<ZVerseBackendState>`
      Returns:
        the fast global key list
      Throws:
        `BookException` - the book exception if for some reason the book failed to be read properly.

    - #### initState

          public ZVerseBackendState initState()
                                       throws BookException

      Description copied from interface: `StatefulFileBackedBackend`
      Initialises the state required to read from files, specific to each different backend
      Returns:
        the state that has been initialised
      Throws:
        `BookException`

    - #### readRawContent

          public String readRawContent(ZVerseBackendState rafBook,
                              Key key)
                                throws IOException

      Parameters:
        `rafBook` - the state object containing all the open random access files
        `key` - the verse that is sought
      Returns:
        the raw text
      Throws:
        `IOException` - something went wrong when reading the verse

    - #### setAliasKey

          public void setAliasKey(ZVerseBackendState rafBook,
                         Key alias,
                         Key source)
                           throws IOException

      Description copied from interface: `StatefulFileBackedBackend`
      Sets alias for a comment on a verse range I.e. setRawText() was for verse range Gen.1.1-3 then setAliasKey should be called for Gen.1.1.2 and Gen.1.1.3
      Parameters:
        `rafBook` - the open file state
        `alias` - Alias Key
        `source` - Source Key
      Throws:
        `IOException` - Exception when anything goes wrong on writing the alias

    - #### setRawText

          public void setRawText(ZVerseBackendState rafBook,
                        Key key,
                        String text)
                          throws BookException,
                                 IOException

      Description copied from interface: `StatefulFileBackedBackend`
      Set the text allotted for the given verse
      Parameters:
        `rafBook` - TODO
        `key` - The key to set text to
        `text` - The text to be set for key
      Throws:
        `BookException` - If the data can not be set.
        `IOException` - If the module data path could not be created.

    - #### dumpIdxRaf

          public void dumpIdxRaf(Versification v11n,
                        int ordinalStart,
                        RandomAccessFile raf)

      Experimental code.
      Parameters:
        `v11n` -
        `ordinalStart` -
        `raf` -

    - #### dumpCompRaf

          public void dumpCompRaf(RandomAccessFile raf)

      Experimental code.
      Parameters:
        `raf` -