org.crosswire.common.util

## Class IniSection

- java.lang.Object
- - org.crosswire.common.util.IniSection

- All Implemented Interfaces:
    Iterable

      public final class IniSection
      extends Object
      implements Iterable

  A utility class for a section of an INI style configuration file. Keys and values are maintained in insertion order. A key may have more than one value.

  SWORD defines a conf as an INI file with one or more sections. Originally, all modules were described in a single conf, but now each module has its own conf.

  SWORD will be using a single conf to hold overrides for many modules. This is the motivation for this class as opposed to allowing only a single section as `IniSection`.

  Since the most common use case is for a single section, this implementation has an API for delegating to the first IniSection.

  This implementation allows for:
  - Case Insensitive -- Section names, keys and values are case insensitive.
  - Comments -- ; and # preceded only by white space indicate that a line is a comment. Note: SWORD does not support ; but it is present in some 3rd Party repositories such as IBT.
  - Multiple Values -- Each key can have one or more values.
  - Order -- Order of sections, keys and values are retained
  This implementation does not allow for:
  - Globals -- (key,value) pairs before the first section.
  - Quoted Values -- Values surrounded by "" or ''. If present they are part of the value.
  - Retaining comments -- Comments are ignored.
  - Comments after content -- Comments are on lines to themselves.
  - : -- as an alternative for =.
  - nulls -- null values.
  Author:
    DM Smith
  See Also:
    `The GNU Lesser General Public License for details.
    `

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `private String` | `charset`
    `private File` | `configFile`
    `private static int` | `MAX_BUFF_SIZE` Buffer size is based on file size but keep it with within reasonable limits
    `private String` | `name` The name of the section.
    `private String` | `report`
    `private Map<String,List<String>>` | `section` A map of values by key names.
    `private StringBuilder` | `warnings`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `IniSection()` Create an empty INI config without a name.
    `IniSection(IniSection config)` Copy constructor
    `IniSection(String name)` Create an empty INI Config.

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `boolean` | `add(String key, String value)` Add a value for the key.
    `private String` | `advance(BufferedReader bin)` Get the next line from the input
    `private boolean` | `allowed(String key, String value)`
    `void` | `clear()` Start over.
    `boolean` | `containsKey(String key)` Returns `true` if the IniSection contains any values for the specified key.
    `boolean` | `containsValue(String value)` Returns `true` if the IniSection contains the specified value for any key.
    `boolean` | `containsValue(String key, String value)` Returns `true` if the IniSection contains the specified value for the given key.
    `private void` | `doLoad(Reader in, Filter<String> filter)`
    `private String` | `format(String value)` A helper to format the output of the content as expected
    `String` | `get(String key)` Get the first value for the key.
    `String` | `get(String key, int index)` Get the value for the key specified by the index.
    `String` | `get(String key, String defaultValue)`
    `Collection<String>` | `getKeys()` Get the unmodifiable unordered list of keys.
    `String` | `getName()` Get the [name] of this section
    `private Collection<String>` | `getOrCreateValues(String key)`
    `private int` | `getSplitPos(String line)` Does this line of text represent a key/value pair?
    `Collection<String>` | `getValues(String key)` Get the unmodifiable collection of values of a key.
    `private boolean` | `isCommentLine(String line)` Determine if the given line is a blank or a comment line.
    `boolean` | `isEmpty()` Determine whether this section has any keys
    `private boolean` | `isSectionLine(String line)` Is this line a [section]?
    `Iterator` | `iterator()`
    `void` | `load(byte[] buffer, String encoding)` Load the conf from a buffer.
    `void` | `load(byte[] buffer, String encoding, Filter<String> filter)` Load the conf from a buffer.
    `void` | `load(File file, String encoding)` Load the INI from a file using the given encoding.
    `void` | `load(File file, String encoding, Filter<String> filter)` Load the INI from a file using the given encoding.
    `void` | `load(InputStream is, String encoding)` Load the INI from an InputStream using the given encoding.
    `void` | `load(InputStream is, String encoding, Filter<String> filter)` Load the INI from an InputStream using the given encoding.
    `private String` | `more(BufferedReader bin, String value)` Get continuation lines, if any.
    `private static boolean` | `more(String line)` Is there more following this line
    `boolean` | `remove(String key)` Remove the key and all its values, if present.
    `boolean` | `remove(String key, String value)` Remove the value if present.
    `boolean` | `replace(String key, String value)` Replace the value(s) for the key with a new value.
    `String` | `report()` Obtain a report of issues with this IniSection.
    `void` | `save()` Save this INI to the file from which it was loaded.
    `void` | `save(File file, String encoding)` Save the INI to a file using the given encoding.
    `void` | `save(Writer out)` Output this section using the print writer.
    `void` | `setName(String name)` Set the name of this INI config.
    `int` | `size()` Get the number of keys in this section.
    `int` | `size(String key)` Get the number of values for a key.

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

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

- - ### Field Detail

    - #### name

          private String name

      The name of the section.

    - #### section

          private Map<String,List<String>> section

      A map of values by key names.

    - #### configFile

          private File configFile

    - #### charset

          private String charset

    - #### warnings

          private StringBuilder warnings

    - #### report

          private String report

    - #### MAX_BUFF_SIZE

          private static final int MAX_BUFF_SIZE

      Buffer size is based on file size but keep it with within reasonable limits
      See Also:
        Constant Field Values

  - ### Constructor Detail

    - #### IniSection

          public IniSection()

      Create an empty INI config without a name.

    - #### IniSection

          public IniSection(String name)

      Create an empty INI Config.
      Parameters:
        `name` - the section name

    - #### IniSection

          public IniSection(IniSection config)

      Copy constructor
      Parameters:
        `config` - the config to copy

  - ### Method Detail

    - #### clear

          public void clear()

      Start over.

    - #### setName

          public void setName(String name)

      Set the name of this INI config.
      Parameters:
        `name` -

    - #### getName

          public String getName()

      Get the [name] of this section
      Returns:
        the name

    - #### size

          public int size()

      Get the number of keys in this section.
      Returns:
        the count

    - #### size

          public int size(String key)

      Get the number of values for a key.
      Parameters:
        `key` - the key
      Returns:
        the number of values for a key or 0 if the key does not exist.

    - #### isEmpty

          public boolean isEmpty()

      Determine whether this section has any keys
      Returns:
        `true` if this section is empty

    - #### iterator

          public Iterator iterator()

      Specified by:
        `iterator` in interface `Iterable`

    - #### getKeys

          public Collection<String> getKeys()

      Get the unmodifiable unordered list of keys.
      Returns:
        the set of keys

    - #### containsKey

          public boolean containsKey(String key)

      Returns `true` if the IniSection contains any values for the specified key.
      Parameters:
        `key` - key to search for in IniSection
      Returns:
        `true` if the key exists

    - #### containsValue

          public boolean containsValue(String value)

      Returns `true` if the IniSection contains the specified value for any key.
      Parameters:
        `value` - value to search for in IniSection
      Returns:
        `true` if the value exists.

    - #### containsValue

          public boolean containsValue(String key,
                              String value)

      Returns `true` if the IniSection contains the specified value for the given key.
      Parameters:
        `key` - the key for the section
        `value` - value to search for in IniSection
      Returns:
        `true` if the value exists.

    - #### add

          public boolean add(String key,
                    String value)

      Add a value for the key. Duplicate values are not allowed.
      Parameters:
        `key` - the key for the section
        `value` - the value for the key
      Returns:
        whether the value was added or is already present.

    - #### getValues

          public Collection<String> getValues(String key)

      Get the unmodifiable collection of values of a key. The collection has insertion order. Note many keys only have one value. A key that has no values returns null.
      Parameters:
        `key` - the key
      Returns:
        the keyed values or null if the key doesn't exist

    - #### get

          public String get(String key,
                   int index)

      Get the value for the key specified by the index.
      Parameters:
        `key` - the key
        `index` - the index
      Returns:
        the value at the specified index
      Throws:
        `ArrayIndexOutOfBoundsException` - when the index is out of bounds

    - #### get

          public String get(String key)

      Get the first value for the key.
      Parameters:
        `key` - the key
      Returns:
        the value at the specified index or null

    - #### get

          public String get(String key,
                   String defaultValue)

    - #### remove

          public boolean remove(String key,
                       String value)

      Remove the value if present. If it were the last value for the key, the key is removed.
      Parameters:
        `key` - the key for the section
        `value` - the value for the key
      Returns:
        whether the value was present and removed

    - #### remove

          public boolean remove(String key)

      Remove the key and all its values, if present.
      Parameters:
        `key` - the key for the section
      Returns:
        whether the key was present and removed

    - #### replace

          public boolean replace(String key,
                        String value)

      Replace the value(s) for the key with a new value.
      Parameters:
        `key` - the key for the section
        `value` - the value for the key
      Returns:
        whether the replace happened

    - #### load

          public void load(InputStream is,
                  String encoding)
                    throws IOException

      Load the INI from an InputStream using the given encoding.
      Parameters:
        `is` - the InputStream to read from
        `encoding` - the encoding of the file
      Throws:
        `IOException`

    - #### load

          public void load(InputStream is,
                  String encoding,
                  Filter<String> filter)
                    throws IOException

      Load the INI from an InputStream using the given encoding. Filter keys as specified.
      Parameters:
        `is` - the InputStream to read from
        `encoding` - the encoding of the file
        `filter` - the filter, possibly null, for the desired keys
      Throws:
        `IOException`

    - #### load

          public void load(File file,
                  String encoding)
                    throws IOException

      Load the INI from a file using the given encoding.
      Parameters:
        `file` - the file to load
        `encoding` - the encoding of the file
      Throws:
        `IOException`

    - #### load

          public void load(File file,
                  String encoding,
                  Filter<String> filter)
                    throws IOException

      Load the INI from a file using the given encoding. Filter keys as specified.
      Parameters:
        `file` - the file to load
        `encoding` - the encoding of the file
        `filter` - the filter, possibly null, for the desired keys
      Throws:
        `IOException`

    - #### load

          public void load(byte[] buffer,
                  String encoding)
                    throws IOException

      Load the conf from a buffer. This is used to load conf entries from the mods.d.tar.gz file.
      Parameters:
        `buffer` - the buffer to load
        `encoding` - the character encoding of this INI
      Throws:
        `IOException`

    - #### load

          public void load(byte[] buffer,
                  String encoding,
                  Filter<String> filter)
                    throws IOException

      Load the conf from a buffer. Filter keys as specified. This is used to load conf entries from the mods.d.tar.gz file.
      Parameters:
        `buffer` - the buffer to load
        `encoding` - the character encoding of this INI
        `filter` - the filter, possibly null, for the desired keys
      Throws:
        `IOException`

    - #### save

          public void save()
                    throws IOException

      Save this INI to the file from which it was loaded.
      Throws:
        `IOException`

    - #### save

          public void save(File file,
                  String encoding)
                    throws IOException

      Save the INI to a file using the given encoding.
      Parameters:
        `file` - the file to load
        `encoding` - the encoding of the file
      Throws:
        `IOException`

    - #### save

          public void save(Writer out)

      Output this section using the print writer. The section ends with a blank line. The items are output in insertion order.
      Parameters:
        `out` - the output stream

    - #### report

          public String report()

      Obtain a report of issues with this IniSection. It only reports once per load.
      Returns:
        the report with one issue per line or an empty string if there are no issues

    - #### format

          private String format(String value)

      A helper to format the output of the content as expected
      Parameters:
        `value` - the value to be formatted
      Returns:
        the transformed value

    - #### getOrCreateValues

          private Collection<String> getOrCreateValues(String key)

    - #### doLoad

          private void doLoad(Reader in,
                    Filter<String> filter)
                       throws IOException

      Throws:
        `IOException`

    - #### advance

          private String advance(BufferedReader bin)
                          throws IOException

      Get the next line from the input
      Parameters:
        `bin` - The reader to get data from
      Returns:
        the next line or null if there is nothing more
      Throws:
        `IOException` - if encountered

    - #### isCommentLine

          private boolean isCommentLine(String line)

      Determine if the given line is a blank or a comment line.
      Parameters:
        `line` - The line to check.
      Returns:
        true if the line is empty or starts with one of the comment characters

    - #### isSectionLine

          private boolean isSectionLine(String line)

      Is this line a [section]?
      Parameters:
        `line` - The line to check.
      Returns:
        true if the line designates a section

    - #### getSplitPos

          private int getSplitPos(String line)

      Does this line of text represent a key/value pair?
      Parameters:
        `line` - The line to check.
      Returns:
        the position of the split position or -1

    - #### more

          private String more(BufferedReader bin,
                    String value)
                       throws IOException

      Get continuation lines, if any.
      Throws:
        `IOException`

    - #### more

          private static boolean more(String line)

      Is there more following this line
      Parameters:
        `line` - the trimmed string to check
      Returns:
        whether this line continues

    - #### allowed

          private boolean allowed(String key,
                        String value)