Config allows an application to separate the responsibilities of setting itself up, and providing a user interface from the real work that it needs to do.

## Introduction

Config is (mostly) all kept in a few packages in the util source tree. The design aims for the following goals:

- Application Transparency - It should be possible to add a configuration dialog to an application without adding hundreds of hooks either to your application to read the current state, or to the configuration system to work with the application. This is achieved via an xml config file and a healthy dose of reflection.
- View Independance - Currently there are a number of Swing front ends - a Mozilla style config dialog with a tree, a more conventional tabbed dialog, and a prototype wizard style interface. There has also been a servlet front-end however the code to do this has suffered bit-rot, and should not be considered useful. It does however prove the view independance concept.

### How To Use Config

There are a number of simple steps. First a config.xml file is needed to tell the config system what to configure and how.

    <config>

      <!-- A configuration is a set of options ... -->
      <!-- The key is a dot separated name - Imaging this in a Mozilla tree or some nested tabs. -->
      <option key="Bibles.Sword.Base Directory" type="string">
        <!-- The type (above) along with the introspect line configures what JavaBean methods will be called -->
        <introspect class="org.crosswire.jsword.book.sword.SwordBibleDriver" property="SwordDir"/>
        <!-- The tool-tip (or similar) describing what is going on -->
        <help>Where is the SWORD Project base directory.</help>
      </option>

      <!-- Another option, this time it is a boolean option which will show up as a tickbox -->
      <option key="Bibles.Display.Persistent Naming" level="advanced" type="boolean">
        <introspect class="org.crosswire.jsword.passage.PassageUtil" property="PersistentNaming"/>
        <help>True if the passage editor re-writes the references to conform to its notation.</help>
      </option>

      <!-- Another type again this one for the look and feel. -->
      <!-- The reason for the helper class here is to alter windows that are not currently mapped -->
        <option key="Looks.Look and Feel" type="class">
        <introspect class="org.crosswire.common.swing.LookAndFeelUtil" property="LookAndFeel"/>
        <help>The look and feel of the application</help>
      </option>

      <!-- When we have have an Enum style config option ... -->
        <option key="Bibles.Display.Book Case" level="advanced" type="int-options">
        <introspect class="org.crosswire.jsword.passage.Books" property="Case"/>
        <help>What case should we use to display the references.</help>
        <alternative number="0" name="lower"/>
        <alternative number="1" name="Sentence"/>
        <alternative number="2" name="UPPER"/>
        <alternative number="3" name="mIXeD"/>
      </option>

      <!-- The options here are more complex and need to be provided as a string array by Java code (see below) -->
        <option key="Bibles.Default" type="string-options">
        <introspect class="org.crosswire.jsword.book.Bibles" property="DefaultName"/>
        <help>Which of the available Bibles is the default.</help>
        <map name="biblenames"/>
      </option>

      <!-- This option is 'advanced' which means it is not visible to all users (see below) -->
        <option key="Advanced.Source Path" level="advanced" type="path">
        <introspect class="org.crosswire.common.swing.DetailedExceptionPane" property="SourcePath"/>
        <help>The directories to search for source code in when investigating an exception.</help>
      </option>

      <!-- When the choice is very custom you can always do your own implementation -->
      <!-- This allows us to set users levels so not everyone gets asked hard questions -->
        <option key="Advanced.User Level" type="custom" class="org.crosswire.common.util.UserLevel$UserLevelChoice">
        <help>How advanced is your knowledge of this program.</help>
      </option>

      <!-- There are other examples in config.xml -->
    </config>

Then you need to add the Java code:

    // To load the config.xml file:
    Config config = new Config("Tool Shed Options");
    Document xmlconfig = Project.resource().getDocument("config"); // Or whatever to get a JDOM Document
    config.add(xmlconfig);

    // To load a saved config
    config.setProperties(Project.resource().getProperties("desktop")); // Or however you get a Properties
    config.localToApplication(true);

    // And display it ...
    URL configurl = Project.resource().getPropertiesURL("desktop"); // URL of the Properties file to save to
    SwingConfig.showDialog(config, parentWind, configurl);

    // The code above needed help in setting up a string choice. This is how ...
    ChoiceFactory.getDataMap().put("biblenames", Bibles.getBibleNames());

There are more examples in `org.crosswire.bibledesktop.desktop.OptionsAction.`