Index: /gli/trunk/src/org/greenstone/gatherer/cdm/Argument.java
===================================================================
--- /gli/trunk/src/org/greenstone/gatherer/cdm/Argument.java	(revision 14782)
+++ /gli/trunk/src/org/greenstone/gatherer/cdm/Argument.java	(revision 14783)
@@ -51,596 +51,605 @@
  */
 public class Argument
-    implements Comparable, Serializable {
-    /** An element of the argument type enumeration specifying a combobox control. */
-    static final public byte ENUM = 0;
-    /** An element of the argument type enumeration specifying a checkbox control. */
-    static final public byte FLAG = 1;
-    /** An element of the argument type enumeration specifying a tree control. */
-    static final public byte HIERARCHY = 2;
-    /** An element of the argument type enumeration specifying a spinner control. */
-    static final public byte INTEGER = 3;
-    /** An element of the argument type enumeration specifying a language combobox control. */
-    static final public byte LANGUAGE = 4;
-    /** An element of the argument type enumeration specifying a list control. */
-    static final public byte METADATA = 5;
-    /** An element of the argument type enumeration specifying a metadata combobox control. */
-    static final public byte METADATUM = 6;
-    /** An element of the argument type enumeration specifying a text field. */
-    static final public byte STRING = 7;
-    /** An element of the argument type enumeration specifying a regular expression text field. */
-    static final public byte REGEXP = 8;
-    /** An element of the argument type enumeration specifying a metadata set combobox control. */
-    static final public byte METADATA_SET_NAMESPACE = 9;
-
- ///////////kk added the number was 9, I changed it to 10//////////////
-  /** An element of the argument type enumeration specifying a text field. */
-    static final public byte URL = 10;
-    /////////////////////////////////////////////////////////////////
-
-    /** true if this argument should actually be hidden within the GLI. This is important for arguments such as import dir or other location critical arguments. */
-    private boolean hidden_gli = false;
-    /** <i>true</i> if this argument is required for the applicable script to work properly, <i>false</i> otherwise. */
-    private boolean required = false;
-    /** The type of this argument. Used to be an int, but bytes are cheaper. */
-    private byte type = STRING;
-    /** The maximum value an integer based control can have. */
-    private int maximum = Integer.MAX_VALUE;
-    /** The minimum value an integer based control can have. */
-    private int minimum = Integer.MIN_VALUE;
-    /** Every argument has a detail mode level at which it becomes available to the user to edit. 
-     * @see org.greenstone.gatherer.Configuration
-     */
-    private int mode_level = Configuration.LIBRARIAN_MODE;
-    /** The DOM element this argument is built around, if any. */
-    private Element element;
-    /** If the argument is of type ENUM then this map holds all the various options. Each entry is an &lt;option value&gt; -&gt; &lt;description&gt; mapping. */
-    private ArrayList option_list = null;
-    /** A default value for parameter-type arguments. May be a Perl pattern. */
-    private String default_value = null;
-    /** The text description of this argument parsed from the pluginfo output. */
-    private String description = null;
-    /** The argument flag as it appears in the command. Also used as the unique identifier of an argument. */
-    private String name = null;
-    /** The plugin that owns this argument, for the purposes of visualising inheritance. */
-    private String owner = null;
-
-    private String display_name = null;
-
-    /** Default Constructor. */
-    public Argument() {
-    }
-
-    /** Another constructor but this one is a little more interesting as it takes a DOM element.
-     * @param element the Element this argument is based around
-     */
-    public Argument(Element element) {
-	this.element = element;
-    }
-
-    /** Method to add an element to the option_list.
-     * @param name the name value of the option as a String
-     * @param desc the description of this options as a String
-     */
-    public void addOption(String name, String desc) {
-	if(type == ENUM && name != null) {
-	    if(desc == null) {
-		desc = "";
-	    }
-	    if(option_list == null) {
-		option_list = new ArrayList();
-	    }
-	    option_list.add(new ArgumentOption(name, desc));
-	}
-    }
-
-    /** Method to compare two arguments for ordering.
-     * @param object the argument we are comparing to, as an Object
-     * @return an int specifying the argument order, using values as set out in String
-     * @see org.greenstone.gatherer.cdm.Argument
-     */
-    public int compareTo(Object object) {
-	if(object instanceof Argument) {
-	    return getName().compareTo(((Argument)object).getName());
-	}
-	else {
-	    return toString().compareTo(object.toString());
-	}
-    }
-
-    /** Create a copy of this argument.
-     * @return a newly created Argument with the same details as this one
-     */
-    public Argument copy() {
-	Argument copy = new Argument();
-	copy.setDefaultValue(default_value);
-	copy.setDescription(description);
-	copy.setOptions(option_list);
-	copy.setOwner(owner);
-	copy.setName(name);
-	copy.setRequired(required);
-	copy.setType(type);
-	copy.setMinimum(minimum);
-	copy.setMaximum(maximum);
-	copy.setModeLevel(mode_level);
-	copy.setHiddenGLI(hidden_gli);
-	return copy;
-    }
-
-    /** Method to determine if two arguments are equal.
-     * @param object the argument to test against, as an Object
-     * @return true if the arguments names match, false otherwise
-     */
-    public boolean equals(Object object) {
-	return (compareTo(object) == 0);
-    }
-
-    /** Method to retrieve the value of default_value.
-     * @return a String containing the default value
-     */
-    public String getDefaultValue() {
-	return default_value;
-    }
-
-    /** Method to retrieve this arguments description.
-     * @return a String containing the description
-     */
-    public String getDescription() {
-	return description;
-    }
-
-    public Element getElement() {
-	return element;
-    }
-    /** Retrieve the upper bound of a range based argument.
-     * @return the maximum as an int
-     */
-    public int getMaximum() {
-	return maximum;
-    }
-
-    /** Retrieve the lower bound of a range based argument.
-     * @return the minimum as an int
-     */
-    public int getMinimum() {
-	return minimum;
-    }
-
-    /** Retrieves the mode level at which this argument should become available. Any higher levels should also see this argument.
-     * @return the mode level as an int
-     */
-    public int getModeLevel() {
-	return mode_level;
-    }
-
-    /** Method to retrieve the value of name.
-     * @return a String containing the argument name
-     * @see org.greenstone.gatherer.util.StaticStrings#NAME_ATTRIBUTE
-     */
-    public String getName() {
-	if(name == null && element != null) {
-	    name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
-	}
-	return name;
-    }
-
-    public String getDisplayName() {
-	return display_name;
-    }
-
-
-    /** Method to retrieve the option list for this argument.
-     * @return a HashMap containing &lt;option value&gt; -&gt; &lt;description&gt; entries
-     */
-    public ArrayList getOptions() {
-	return option_list;
-    }
-
-    /** Retrieve the name of the owner of this argument.
-     * @return the owners name as a String
-     */
-    public String getOwner() {
-	return owner;
-    }
-    
-    /** Method to determine the type of this argument.
-     * @return a byte specifying the type
-     */
-    public byte getType() {
-	return type;
-    }
-
-    /** Method to retrieve the value of value.
-     * @return the value of value as a String
-     * @see org.greenstone.gatherer.Gatherer#c_man
-     * @see org.greenstone.gatherer.collection.CollectionManager#getCollection
-     */
-    public String getValue()
-    {
-	// Only assigned arguments have values.
-	if (element == null) {
-	    return null;
-	}
-
-	return XMLTools.getValue(element);
-    }
-
-
-    /** Method to determine if this argument has been assigned.
-     * @return true if it has, false otherwise
-     * @see org.greenstone.gatherer.util.StaticStrings#ASSIGNED_ATTRIBUTE
-     * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
-     */
-    public boolean isAssigned() {
-	return (element != null && element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
-    }
-
-    /** Determine if this is a custom argument ie one that has been parsed from the config file but doesn't have a matching entry in the argument library.
-     * @return true if this argument is a custom, false otherwise
-     * @see org.greenstone.gatherer.util.StaticStrings#CUSTOM_ATTRIBUTE
-     * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
-     */
-    public boolean isCustomArgument() {
-	return (element != null && element.getAttribute(StaticStrings.CUSTOM_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
-    }
-
-    /** Determine if this argument is hidden in GLI
-     * @return true if the argument is hidden, false otherwise
-     */
-    public boolean isHiddenGLI() {
-	return hidden_gli;
-    }
-
-    /** Method to determine of this argument is required for the associated script to work.
-     * @return true if this argument is required, false otherwise
-     */
-    public boolean isRequired() {
-	return required;
-    }
-
-    /** Method to allow for the activation of arguments that might never have their setValue() method called.
-     * @param assigned the desired state as a boolean
-     * @see org.greenstone.gatherer.util.StaticStrings#ASSIGNED_ATTRIBUTE
-     * @see org.greenstone.gatherer.util.StaticStrings#FALSE_STR
-     * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
-     */
-    public void setAssigned(boolean assigned) {
-	if(element != null) {
-	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
-	}
-    }
-
-    /** Sets the value of default_value.
-     * @param default_value The new value for default_value as a <strong>String</strong>.
-     */
-    public void setDefaultValue(String default_value) {
-	this.default_value = default_value;
-    }
-
-    /** Set the value of desc.
-     * @param description the new value of desc as a String
-     */
-    public void setDescription(String description) {
-	this.description = description;
-    }
-
-    /** Set the element this argument should be based upon.
-     * @param element the Element
-     */
-    public void setElement(Element element) {
-	this.element = element;
-    }
-
-    /** Mark this argument as being hidden in GLI. */
-    public void setHiddenGLI(boolean hidden) {
-	this.hidden_gli = hidden;
-    }
-
-    /** Set the upper bound for a range type argument.
-     * @param maximum the maximum as an int
-     */
-    public void setMaximum(int maximum) {
-	this.maximum = maximum;
-    }
-
-    /** Set the lower bound for a range type argument.
-     * @param minimum the minimum as an int
-     */
-    public void setMinimum(int minimum) {
-	this.minimum = minimum;
-    }
-
-    /** Set the detail mode level where this argument will become available.
-     * @param mode_level the mode level as an int
-     */
-    public void setModeLevel(int mode_level) {
-	this.mode_level = mode_level;
-    }
-
-    /** Set the value of name.
-     * @param name the new value of name as a String
-     */
-    public void setName(String name) {
-	this.name = name;
-    }
-
-    /** Sets the value of the options list.
-     * @param list the new options list as a HashMap
-     */
-    public void setOptions(ArrayList list) {
-	this.option_list = list;
-    }
-
-    /** Set the owner of this argument.
-     * @param owner the name of the owner of this argument as a String
-     */
-    public void setOwner(String owner) {
-	this.owner = owner;
-    }
-
-    /** Set the value of required.
-     * @param required the new value of required as a boolean
-     */
-    public void setRequired(boolean required) {
-	this.required = required;
-    }
-
-    /** Set the value of type.
-     * @param type the new value of type as an byte
-     */
-    public void setType(byte type) {
-	this.type = type;
-    }
-
-    /** Set the value of type, by matching a type to the given string.
-     * @param new_type a String which contains the name of a certain argument type
-     * @see org.greenstone.gatherer.util.StaticStrings#ENUM_STR
-     * @see org.greenstone.gatherer.util.StaticStrings#FLAG_STR
-     * @see org.greenstone.gatherer.util.StaticStrings#HIERARCHY_STR
-     * @see org.greenstone.gatherer.util.StaticStrings#INT_STR
-     * @see org.greenstone.gatherer.util.StaticStrings#LANGUAGE_STR
-     * @see org.greenstone.gatherer.util.StaticStrings#METADATA_TYPE_STR
-     * @see org.greenstone.gatherer.util.StaticStrings#METADATUM_TYPE_STR
-     * @see org.greenstone.gatherer.util.StaticStrings#REGEXP_STR
-     */
-    public void setType(String new_type) {
-	if(new_type.equalsIgnoreCase(StaticStrings.ENUM_STR)) {
-	    this.type = ENUM;
-	    option_list = new ArrayList();
-	}
-	else if(new_type.equalsIgnoreCase(StaticStrings.FLAG_STR)) {
-	    this.type = FLAG;
-	}
-	else if(new_type.equalsIgnoreCase(StaticStrings.HIERARCHY_STR)) {
-	    this.type = HIERARCHY;
-	}
-	else if(new_type.equalsIgnoreCase(StaticStrings.INT_STR)) {
-	    this.type = INTEGER;
-	}
-	else if(new_type.equalsIgnoreCase(StaticStrings.LANGUAGE_STR)) {
-	    this.type = LANGUAGE;
-	}
-	else if(new_type.equalsIgnoreCase(StaticStrings.METADATA_TYPE_STR)) {
-	    this.type = METADATA;
-	}
-	else if(new_type.equalsIgnoreCase(StaticStrings.METADATUM_TYPE_STR)) {
-	    this.type = METADATUM;
-	}
-	else if(new_type.equalsIgnoreCase(StaticStrings.REGEXP_STR)) {
-	    this.type = REGEXP;
-	}
-	else {
-	    this.type = STRING;
-	}
-    }
-
-    /** Method to set the value of this argument.
-     * @param value the new value for the argument
-     * @see org.greenstone.gatherer.Gatherer#println
-     */
-    public void setValue(String value) {
-	if(element != null) {
-	    XMLTools.setValue(element, value);
-	}
-	else {
-	    DebugStream.println("Argument.setValue(" + value + ") called on a base Argument.");
-	}
-    }
-
-    /** Set the values vector to the given values. Currently I just assign the new values, whereas I may later want to implement a deep clone.
-     * @param values an ArrayList of values
-     * @see org.greenstone.gatherer.Gatherer#println
-     */
-    public void setValues(ArrayList values) {
-	if(element != null) {
-	    StringBuffer value = new StringBuffer();
-	    int value_length = values.size();
-	    for(int i = 0; i < value_length; i++) {
-		value.append(values.get(i));
-		value.append(StaticStrings.COMMA_CHARACTER);
-	    }
-	    value.deleteCharAt(value.length() - 1); // Remove last ','
-	    XMLTools.setValue(element, value.toString());
-	}
-	else {
-	    DebugStream.println("Argument.setValues([" + values.size() + " items]) called on a base Argument.");
-	}
-    }
-
-    /** Method for translating the data of this class into a string.
-     * @return a String containing a fragment of the total arguments string
-     * @see org.greenstone.gatherer.Gatherer#c_man
-     * @see org.greenstone.gatherer.collection.CollectionManager#getCollection
-     * @see org.greenstone.gatherer.util.StaticStrings#COMMA_CHARACTER
-     * @see org.greenstone.gatherer.util.StaticStrings#NAME_ATTRIBUTE
-     * @see org.greenstone.gatherer.util.StaticStrings#SPACE_CHARACTER
-     * @see org.greenstone.gatherer.util.StaticStrings#SPEECH_CHARACTER
-     */
-    public String toString()
-    {
-	StringBuffer text = new StringBuffer("-");
-
-	if (element == null) {
-	    return text.toString();
-	}
-
-	if (name == null) {
-	    name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
-	}
-	text.append(name);
-
-	String value = XMLTools.getValue(element);
-	if (value.length() == 0) {
-	    return text.toString();
-	}
-
-	text.append(StaticStrings.SPACE_CHARACTER);
-
-// 	// Handle metadata elements specially
-// 	if (type == METADATA || type == METADATUM) {
-// 	    // Tokenize the string
-// 	    StringTokenizer tokenizer = new StringTokenizer(value, ",");
-// 	    while (tokenizer.hasMoreTokens()) {
-// 		String token = tokenizer.nextToken();
-
-// 		MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName(token);
-// 		if (metadata_element != null) {
-// 		    text.append(metadata_element.getFullName());
-// 		}
-// 		else {
-// 		    text.append(token);
-// 		}
-
-// 		if (tokenizer.hasMoreTokens()) {
-// 		    text.append(StaticStrings.COMMA_CHARACTER);
-// 		}
-// 	    }
-// 	    return text.toString();
-// 	}
-
-	// If the value contains a space, add speech marks
-	//   (Except for metadata elements, which won't have spaces when written out to collect.cfg)
-	if (value.indexOf(StaticStrings.SPACE_CHARACTER) != -1 && !(type == METADATUM || type == METADATA)) {
-	    value = StaticStrings.SPEECH_CHARACTER + value + StaticStrings.SPEECH_CHARACTER;
-	}
-
-	text.append(value);
-	return text.toString();
-    } 
-
-    /** parse the <Option> XML from eg import.pl -xml or pluginfo.pl -xml */
-    public void parseXML(Element option) {
-
-	for(Node node = option.getFirstChild(); node != null; node = node.getNextSibling()) {
-	    String node_name = node.getNodeName();
-	    if(node_name.equals("Name")) {
-		setName(XMLTools.getValue(node));
-	    }
-	    else if(node_name.equals("Desc")) {
-		setDescription(XMLTools.getValue(node));
-	    }
-	    else if(node_name.equals("Type")) {
-		setType(XMLTools.getValue(node));
-	    }
-	    else if(node_name.equals("Default")) {
-		setDefaultValue(XMLTools.getValue(node));
-	    }
-	    else if(node_name.equals("Required")) {
-		String v = XMLTools.getValue(node);
-		if(v != null && v.equals("yes")) {
-		    setRequired(true);
-		}
-	    }
-	    else if(node_name.equals("List")) {
-		// Two final loops are required to parse lists.
-		for(Node value = node.getFirstChild(); value != null; value = value.getNextSibling()) {
-		    if(value.getNodeName().equals("Value")) {
-			String key = null;
-			String desc = "";
-			for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) {
-			    node_name = subvalue.getNodeName();
-			    if(node_name.equals("Name")) {
-				key = XMLTools.getValue(subvalue);
-			    }
-			    else if(node_name.equals("Desc")) {
-				desc = XMLTools.getValue(subvalue);
-			    }
-			}
-			if(key != null) {
-			    addOption(key, desc);
-			}
-		    }
-		}
-	    }
-	    else if(node_name.equals("Range")) {
-		String range_raw = XMLTools.getValue(node);
-		int index = -1;
-		if((index = range_raw.indexOf(StaticStrings.COMMA_CHARACTER)) != -1) {
-		    if(index > 0) {
-			try {
-			    String first_number = range_raw.substring(0, index);
-			    setMinimum(Integer.parseInt(first_number));
-			    first_number = null;
-			}
-			catch(Exception exception) {
-			}
-		    }
-		    
-		    if(index + 1 < range_raw.length()) {
-			try {
-			    String second_number = range_raw.substring(index + 1);
-			    setMaximum(Integer.parseInt(second_number));
-			    second_number = null;    
-			}
-			catch(Exception exception) {
-			}
-		    }
-		}
-		// Else it wasn't a valid range anyway, so ignore it
-	    }
-	    else if(node_name.equals("HiddenGLI")) {
-		setHiddenGLI(true);
-	    }
-	    else if(node_name.equals("ModeGLI")) {
-		String mode_level_str = XMLTools.getValue(node);
-		try {
-		    int mode_level = Integer.parseInt(mode_level_str);
-		    setModeLevel(mode_level);
-		}
-		catch(Exception exception) {
-		    DebugStream.println("Exception in Argument.parseXML() - Unexpected but non-fatal");
-		    DebugStream.printStackTrace(exception);
-		}
-	    }
-	    
-	} // for each option
+implements Comparable, Serializable {
+	/** An element of the argument type enumeration specifying a combobox control. */
+	static final public byte ENUM = 0;
+	/** An element of the argument type enumeration specifying a checkbox control. */
+	static final public byte FLAG = 1;
+	/** An element of the argument type enumeration specifying a tree control. */
+	static final public byte HIERARCHY = 2;
+	/** An element of the argument type enumeration specifying a spinner control. */
+	static final public byte INTEGER = 3;
+	/** An element of the argument type enumeration specifying a language combobox control. */
+	static final public byte LANGUAGE = 4;
+	/** An element of the argument type enumeration specifying a list control. */
+	static final public byte METADATA = 5;
+	/** An element of the argument type enumeration specifying a metadata combobox control. */
+	static final public byte METADATUM = 6;
+	/** An element of the argument type enumeration specifying a text field. */
+	static final public byte STRING = 7;
+	/** An element of the argument type enumeration specifying a regular expression text field. */
+	static final public byte REGEXP = 8;
+	/** An element of the argument type enumeration specifying a metadata set combobox control. */
+	static final public byte METADATA_SET_NAMESPACE = 9;
+
+	///////////kk added the number was 9, I changed it to 10//////////////
+	/** An element of the argument type enumeration specifying a text field. */
+	static final public byte URL = 10;
+	/////////////////////////////////////////////////////////////////
+
+	/** true if this argument should actually be hidden within the GLI. This is important for arguments such as import dir or other location critical arguments. */
+	private boolean hidden_gli = false;
+	/** <i>true</i> if this argument is required for the applicable script to work properly, <i>false</i> otherwise. */
+	private boolean required = false;
+	/** The type of this argument. Used to be an int, but bytes are cheaper. */
+	private byte type = STRING;
+	/** The maximum value an integer based control can have. */
+	private int maximum = Integer.MAX_VALUE;
+	/** The minimum value an integer based control can have. */
+	private int minimum = Integer.MIN_VALUE;
+	/** Every argument has a detail mode level at which it becomes available to the user to edit. 
+	 * @see org.greenstone.gatherer.Configuration
+	 */
+	private int mode_level = Configuration.LIBRARIAN_MODE;
+	/** The DOM element this argument is built around, if any. */
+	private Element element;
+	/** If the argument is of type ENUM then this map holds all the various options. Each entry is an &lt;option value&gt; -&gt; &lt;description&gt; mapping. */
+	private ArrayList option_list = null;
+	/** A default value for parameter-type arguments. May be a Perl pattern. */
+	private String default_value = null;
+	/** The text description of this argument parsed from the pluginfo output. */
+	private String description = null;
+	/** The argument flag as it appears in the command. Also used as the unique identifier of an argument. */
+	private String name = null;
+	/** The plugin that owns this argument, for the purposes of visualising inheritance. */
+	private String owner = null;
+
+	private String display_name = null;
+
+	/** Default Constructor. */
+	public Argument() {
+	}
+
+	/** Another constructor but this one is a little more interesting as it takes a DOM element.
+	 * @param element the Element this argument is based around
+	 */
+	public Argument(Element element) {
+		this.element = element;
+	}
+
+	/** Method to add an element to the option_list.
+	 * @param name the name value of the option as a String
+	 * @param desc the description of this options as a String
+	 */
+	public void addOption(String name, String desc) {
+		if(type == ENUM && name != null) {
+			if(desc == null) {
+				desc = "";
+			}
+			if(option_list == null) {
+				option_list = new ArrayList();
+			}
+			option_list.add(new ArgumentOption(name, desc));
+		}
+	}
+
+	/** Method to compare two arguments for ordering.
+	 * @param object the argument we are comparing to, as an Object
+	 * @return an int specifying the argument order, using values as set out in String
+	 * @see org.greenstone.gatherer.cdm.Argument
+	 */
+	public int compareTo(Object object) {
+		if(object instanceof Argument) {
+			return getName().compareTo(((Argument)object).getName());
+		}
+		else {
+			return toString().compareTo(object.toString());
+		}
+	}
+
+	/** Create a copy of this argument.
+	 * @return a newly created Argument with the same details as this one
+	 */
+	public Argument copy() {
+		Argument copy = new Argument();
+		copy.setDefaultValue(default_value);
+		copy.setDescription(description);
+		copy.setOptions(option_list);
+		copy.setOwner(owner);
+		copy.setName(name);		
+		copy.setDispalyName(display_name);
+		copy.setRequired(required);
+		copy.setType(type);
+		copy.setMinimum(minimum);
+		copy.setMaximum(maximum);
+		copy.setModeLevel(mode_level);
+		copy.setHiddenGLI(hidden_gli);
+		return copy;
+	}
+
+	/** Method to determine if two arguments are equal.
+	 * @param object the argument to test against, as an Object
+	 * @return true if the arguments names match, false otherwise
+	 */
+	public boolean equals(Object object) {
+		return (compareTo(object) == 0);
+	}
+
+	/** Method to retrieve the value of default_value.
+	 * @return a String containing the default value
+	 */
+	public String getDefaultValue() {
+		return default_value;
+	}
+
+	/** Method to retrieve this arguments description.
+	 * @return a String containing the description
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	public Element getElement() {
+		return element;
+	}
+	/** Retrieve the upper bound of a range based argument.
+	 * @return the maximum as an int
+	 */
+	public int getMaximum() {
+		return maximum;
+	}
+
+	/** Retrieve the lower bound of a range based argument.
+	 * @return the minimum as an int
+	 */
+	public int getMinimum() {
+		return minimum;
+	}
+
+	/** Retrieves the mode level at which this argument should become available. Any higher levels should also see this argument.
+	 * @return the mode level as an int
+	 */
+	public int getModeLevel() {
+		return mode_level;
+	}
+
+	/** Method to retrieve the value of name.
+	 * @return a String containing the argument name
+	 * @see org.greenstone.gatherer.util.StaticStrings#NAME_ATTRIBUTE
+	 */
+	public String getName() {
+		if(name == null && element != null) {
+			name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+		}
+		return name;
+	}
+
+	public String getDisplayName() {
+		if(display_name==null)
+			return "";
+		return display_name;
+	}
+
+	/** Method to retrieve the option list for this argument.
+	 * @return a HashMap containing &lt;option value&gt; -&gt; &lt;description&gt; entries
+	 */
+	public ArrayList getOptions() {
+		return option_list;
+	}
+
+	/** Retrieve the name of the owner of this argument.
+	 * @return the owners name as a String
+	 */
+	public String getOwner() {
+		return owner;
+	}
+
+	/** Method to determine the type of this argument.
+	 * @return a byte specifying the type
+	 */
+	public byte getType() {
+		return type;
+	}
+
+	/** Method to retrieve the value of value.
+	 * @return the value of value as a String
+	 * @see org.greenstone.gatherer.Gatherer#c_man
+	 * @see org.greenstone.gatherer.collection.CollectionManager#getCollection
+	 */
+	public String getValue()
+	{
+		// Only assigned arguments have values.
+		if (element == null) {
+			return null;
+		}
+
+		return XMLTools.getValue(element);
+	}
+
+
+	/** Method to determine if this argument has been assigned.
+	 * @return true if it has, false otherwise
+	 * @see org.greenstone.gatherer.util.StaticStrings#ASSIGNED_ATTRIBUTE
+	 * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
+	 */
+	public boolean isAssigned() {
+		return (element != null && element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
+	}
+
+	/** Determine if this is a custom argument ie one that has been parsed from the config file but doesn't have a matching entry in the argument library.
+	 * @return true if this argument is a custom, false otherwise
+	 * @see org.greenstone.gatherer.util.StaticStrings#CUSTOM_ATTRIBUTE
+	 * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
+	 */
+	public boolean isCustomArgument() {
+		return (element != null && element.getAttribute(StaticStrings.CUSTOM_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
+	}
+
+	/** Determine if this argument is hidden in GLI
+	 * @return true if the argument is hidden, false otherwise
+	 */
+	public boolean isHiddenGLI() {
+		return hidden_gli;
+	}
+
+	/** Method to determine of this argument is required for the associated script to work.
+	 * @return true if this argument is required, false otherwise
+	 */
+	public boolean isRequired() {
+		return required;
+	}
+
+	/** Method to allow for the activation of arguments that might never have their setValue() method called.
+	 * @param assigned the desired state as a boolean
+	 * @see org.greenstone.gatherer.util.StaticStrings#ASSIGNED_ATTRIBUTE
+	 * @see org.greenstone.gatherer.util.StaticStrings#FALSE_STR
+	 * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
+	 */
+	public void setAssigned(boolean assigned) {
+		if(element != null) {
+			element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+		}
+	}
+
+	/** Sets the value of default_value.
+	 * @param default_value The new value for default_value as a <strong>String</strong>.
+	 */
+	public void setDefaultValue(String default_value) {
+		this.default_value = default_value;
+	}
+
+	/** Set the value of desc.
+	 * @param description the new value of desc as a String
+	 */
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	/** Set the element this argument should be based upon.
+	 * @param element the Element
+	 */
+	public void setElement(Element element) {
+		this.element = element;
+	}
+
+	/** Mark this argument as being hidden in GLI. */
+	public void setHiddenGLI(boolean hidden) {
+		this.hidden_gli = hidden;
+	}
+
+	/** Set the upper bound for a range type argument.
+	 * @param maximum the maximum as an int
+	 */
+	public void setMaximum(int maximum) {
+		this.maximum = maximum;
+	}
+
+	/** Set the lower bound for a range type argument.
+	 * @param minimum the minimum as an int
+	 */
+	public void setMinimum(int minimum) {
+		this.minimum = minimum;
+	}
+
+	/** Set the detail mode level where this argument will become available.
+	 * @param mode_level the mode level as an int
+	 */
+	public void setModeLevel(int mode_level) {
+		this.mode_level = mode_level;
+	}
+
+	/** Set the value of name.
+	 * @param name the new value of name as a String
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
 	
-    } // parseXML
-
-    public class ArgumentOption 
+	public void setDispalyName(String name) {		
+		this.display_name = name; 
+	}	
+
+	/** Sets the value of the options list.
+	 * @param list the new options list as a HashMap
+	 */
+	public void setOptions(ArrayList list) {
+		this.option_list = list;
+	}
+
+	/** Set the owner of this argument.
+	 * @param owner the name of the owner of this argument as a String
+	 */
+	public void setOwner(String owner) {
+		this.owner = owner;
+	}
+
+	/** Set the value of required.
+	 * @param required the new value of required as a boolean
+	 */
+	public void setRequired(boolean required) {
+		this.required = required;
+	}
+
+	/** Set the value of type.
+	 * @param type the new value of type as an byte
+	 */
+	public void setType(byte type) {
+		this.type = type;
+	}
+
+	/** Set the value of type, by matching a type to the given string.
+	 * @param new_type a String which contains the name of a certain argument type
+	 * @see org.greenstone.gatherer.util.StaticStrings#ENUM_STR
+	 * @see org.greenstone.gatherer.util.StaticStrings#FLAG_STR
+	 * @see org.greenstone.gatherer.util.StaticStrings#HIERARCHY_STR
+	 * @see org.greenstone.gatherer.util.StaticStrings#INT_STR
+	 * @see org.greenstone.gatherer.util.StaticStrings#LANGUAGE_STR
+	 * @see org.greenstone.gatherer.util.StaticStrings#METADATA_TYPE_STR
+	 * @see org.greenstone.gatherer.util.StaticStrings#METADATUM_TYPE_STR
+	 * @see org.greenstone.gatherer.util.StaticStrings#REGEXP_STR
+	 */
+	public void setType(String new_type) {
+		if(new_type.equalsIgnoreCase(StaticStrings.ENUM_STR)) {
+			this.type = ENUM;
+			option_list = new ArrayList();
+		}
+		else if(new_type.equalsIgnoreCase(StaticStrings.FLAG_STR)) {
+			this.type = FLAG;
+		}
+		else if(new_type.equalsIgnoreCase(StaticStrings.HIERARCHY_STR)) {
+			this.type = HIERARCHY;
+		}
+		else if(new_type.equalsIgnoreCase(StaticStrings.INT_STR)) {
+			this.type = INTEGER;
+		}
+		else if(new_type.equalsIgnoreCase(StaticStrings.LANGUAGE_STR)) {
+			this.type = LANGUAGE;
+		}
+		else if(new_type.equalsIgnoreCase(StaticStrings.METADATA_TYPE_STR)) {
+			this.type = METADATA;
+		}
+		else if(new_type.equalsIgnoreCase(StaticStrings.METADATUM_TYPE_STR)) {
+			this.type = METADATUM;
+		}
+		else if(new_type.equalsIgnoreCase(StaticStrings.REGEXP_STR)) {
+			this.type = REGEXP;
+		}
+		else {
+			this.type = STRING;
+		}
+	}
+
+	/** Method to set the value of this argument.
+	 * @param value the new value for the argument
+	 * @see org.greenstone.gatherer.Gatherer#println
+	 */
+	public void setValue(String value) {
+		if(element != null) {
+			XMLTools.setValue(element, value);
+		}
+		else {
+			DebugStream.println("Argument.setValue(" + value + ") called on a base Argument.");
+		}
+	}
+
+	/** Set the values vector to the given values. Currently I just assign the new values, whereas I may later want to implement a deep clone.
+	 * @param values an ArrayList of values
+	 * @see org.greenstone.gatherer.Gatherer#println
+	 */
+	public void setValues(ArrayList values) {
+		if(element != null) {
+			StringBuffer value = new StringBuffer();
+			int value_length = values.size();
+			for(int i = 0; i < value_length; i++) {
+				value.append(values.get(i));
+				value.append(StaticStrings.COMMA_CHARACTER);
+			}
+			value.deleteCharAt(value.length() - 1); // Remove last ','
+			XMLTools.setValue(element, value.toString());
+		}
+		else {
+			DebugStream.println("Argument.setValues([" + values.size() + " items]) called on a base Argument.");
+		}
+	}
+
+	/** Method for translating the data of this class into a string.
+	 * @return a String containing a fragment of the total arguments string
+	 * @see org.greenstone.gatherer.Gatherer#c_man
+	 * @see org.greenstone.gatherer.collection.CollectionManager#getCollection
+	 * @see org.greenstone.gatherer.util.StaticStrings#COMMA_CHARACTER
+	 * @see org.greenstone.gatherer.util.StaticStrings#NAME_ATTRIBUTE
+	 * @see org.greenstone.gatherer.util.StaticStrings#SPACE_CHARACTER
+	 * @see org.greenstone.gatherer.util.StaticStrings#SPEECH_CHARACTER
+	 */
+	public String toString()
+	{
+		StringBuffer text = new StringBuffer("-");
+
+		if (element == null) {
+			return text.toString();
+		}
+
+		if (name == null) {
+			name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+		}
+		text.append(name);
+
+		String value = XMLTools.getValue(element);
+		if (value.length() == 0) {
+			return text.toString();
+		}
+
+		text.append(StaticStrings.SPACE_CHARACTER);
+
+//		// Handle metadata elements specially
+//		if (type == METADATA || type == METADATUM) {
+//		// Tokenize the string
+//		StringTokenizer tokenizer = new StringTokenizer(value, ",");
+//		while (tokenizer.hasMoreTokens()) {
+//		String token = tokenizer.nextToken();
+
+//		MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName(token);
+//		if (metadata_element != null) {
+//		text.append(metadata_element.getFullName());
+//		}
+//		else {
+//		text.append(token);
+//		}
+
+//		if (tokenizer.hasMoreTokens()) {
+//		text.append(StaticStrings.COMMA_CHARACTER);
+//		}
+//		}
+//		return text.toString();
+//		}
+
+		// If the value contains a space, add speech marks
+		//   (Except for metadata elements, which won't have spaces when written out to collect.cfg)
+		if (value.indexOf(StaticStrings.SPACE_CHARACTER) != -1 && !(type == METADATUM || type == METADATA)) {
+			value = StaticStrings.SPEECH_CHARACTER + value + StaticStrings.SPEECH_CHARACTER;
+		}
+
+		text.append(value);
+		return text.toString();
+	} 
+
+	/** parse the <Option> XML from eg import.pl -xml or pluginfo.pl -xml */
+	public void parseXML(Element option) {
+
+		for(Node node = option.getFirstChild(); node != null; node = node.getNextSibling()) {
+			String node_name = node.getNodeName();
+			if(node_name.equals("Name")) {
+				setName(XMLTools.getValue(node));
+			}
+			else if(node_name.equals("DisplayName")) {
+				setDispalyName(XMLTools.getValue(node));
+			}
+			else if(node_name.equals("Desc")) {
+				setDescription(XMLTools.getValue(node));
+			}
+			else if(node_name.equals("Type")) {
+				setType(XMLTools.getValue(node));
+			}
+			else if(node_name.equals("Default")) {
+				setDefaultValue(XMLTools.getValue(node));
+			}
+			else if(node_name.equals("Required")) {
+				String v = XMLTools.getValue(node);
+				if(v != null && v.equals("yes")) {
+					setRequired(true);
+				}
+			}
+			else if(node_name.equals("List")) {
+				// Two final loops are required to parse lists.
+				for(Node value = node.getFirstChild(); value != null; value = value.getNextSibling()) {
+					if(value.getNodeName().equals("Value")) {
+						String key = null;
+						String desc = "";
+						for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) {
+							node_name = subvalue.getNodeName();
+							if(node_name.equals("Name")) {
+								key = XMLTools.getValue(subvalue);
+							}
+							else if(node_name.equals("Desc")) {
+								desc = XMLTools.getValue(subvalue);
+							}
+						}
+						if(key != null) {
+							addOption(key, desc);
+						}
+					}
+				}
+			}
+			else if(node_name.equals("Range")) {
+				String range_raw = XMLTools.getValue(node);
+				int index = -1;
+				if((index = range_raw.indexOf(StaticStrings.COMMA_CHARACTER)) != -1) {
+					if(index > 0) {
+						try {
+							String first_number = range_raw.substring(0, index);
+							setMinimum(Integer.parseInt(first_number));
+							first_number = null;
+						}
+						catch(Exception exception) {
+						}
+					}
+
+					if(index + 1 < range_raw.length()) {
+						try {
+							String second_number = range_raw.substring(index + 1);
+							setMaximum(Integer.parseInt(second_number));
+							second_number = null;    
+						}
+						catch(Exception exception) {
+						}
+					}
+				}
+				// Else it wasn't a valid range anyway, so ignore it
+			}
+			else if(node_name.equals("HiddenGLI")) {
+				setHiddenGLI(true);
+			}
+			else if(node_name.equals("ModeGLI")) {
+				String mode_level_str = XMLTools.getValue(node);
+				try {
+					int mode_level = Integer.parseInt(mode_level_str);
+					setModeLevel(mode_level);
+				}
+				catch(Exception exception) {
+					DebugStream.println("Exception in Argument.parseXML() - Unexpected but non-fatal");
+					DebugStream.printStackTrace(exception);
+				}
+			}
+
+		} // for each option
+
+	} // parseXML
+
+	public class ArgumentOption 
 	implements Comparable {
-	public String name;
-	public String description;
-	private String text; // cached version
-
-	public ArgumentOption(String name, String desc) {
-	    this.name = name;
-	    this.description = desc;
-	}
-	
-	public int compareTo(Object obj) {
-	    return toString().compareTo(obj.toString());
-	}
-
-	public boolean equals(Object obj) {	    
-	    return (obj != null && compareTo(obj) == 0);
-	}
-	
-	public String toString() {
-	    return name + " "+ StaticStrings.MINUS_CHARACTER + " "+ description;
-	}
-	
-	public String getToolTip() {
-	    return Utility.formatHTMLWidth(name+": "+description, 80);
-	}
-    }
+		public String name;
+		public String description;
+		private String text; // cached version
+
+		public ArgumentOption(String name, String desc) {
+			this.name = name;
+			this.description = desc;
+		}
+
+		public int compareTo(Object obj) {
+			return toString().compareTo(obj.toString());
+		}
+
+		public boolean equals(Object obj) {	    
+			return (obj != null && compareTo(obj) == 0);
+		}
+
+		public String toString() {
+			return name + " "+ StaticStrings.MINUS_CHARACTER + " "+ description;
+		}
+
+		public String getToolTip() {
+			return Utility.formatHTMLWidth(name+": "+description, 80);
+		}
+	}
 }
Index: /gli/trunk/src/org/greenstone/gatherer/cdm/ArgumentContainer.java
===================================================================
--- /gli/trunk/src/org/greenstone/gatherer/cdm/ArgumentContainer.java	(revision 14782)
+++ /gli/trunk/src/org/greenstone/gatherer/cdm/ArgumentContainer.java	(revision 14783)
@@ -43,246 +43,247 @@
  */
 abstract public class ArgumentContainer 
-    extends ArrayList 
-    implements Comparable, DOMProxyListEntry, Serializable  {
-
-    // The DOM Element this container is modelled on
-    protected Element element;
-    protected boolean is_abstract = false;
-    protected ArgumentContainer super_container;
-    protected String description;
-    protected String name;
-
-    /** Constructor used in DOMProxyListModel initializations
-     */
-    public ArgumentContainer() {
-    }
-
-    public ArgumentContainer(Element element, ArgumentContainer base_container) {
-
-	super();
-	this.element = element;
-	this.name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
-
-	// Parse in any argument options for this container, keeping a list of the ones found
-	HashMap known_arguments = new HashMap();
-	NodeList option_elements = element.getElementsByTagName(StaticStrings.OPTION_ELEMENT);
-	int option_elements_length = option_elements.getLength();
-	for(int i = 0; i < option_elements_length; i++) {
-	    Element option_element = (Element) option_elements.item(i);
-	    Argument argument = new Argument(option_element);
-	    ///ystem.err.println("Rebuilding existing argument: " + argument.getName());
-	    known_arguments.put(argument.getName(), argument);
-	}
-	// If a base classifier was given
-	if(base_container != null) {
-	    // Copy the details, and add a reference to whatever the base container's super container is
-	    description = base_container.getDescription();
-	    // Now search through the 'dummy' arguments belonging to the base container. For each found, if it is already assigned, fill out further details such as type. If any are found that are not already assigned for this container, copy them and add them, but without a value.
-	    ArrayList all_arguments = base_container.getArguments();
-	    int argument_count = all_arguments.size();
-	    for(int j = 0; j < argument_count; j++) {
-		Argument base_argument = (Argument) all_arguments.get(j);
-		String base_argument_name = base_argument.getName();
-		///ystem.err.println("Library indicates this container should have an argument: " + base_argument_name);
-		Argument existing_argument = (Argument) known_arguments.get(base_argument_name);
-		// Found an existing argument. Complete its details
-		if(existing_argument != null) {
-		    ///ystem.err.println("Found existing argument. Filling out details.");
-		    known_arguments.remove(base_argument_name);
-		    existing_argument.setDefaultValue(base_argument.getDefaultValue());
-		    existing_argument.setDescription(base_argument.getDescription());
-		    existing_argument.setOptions(base_argument.getOptions());
-		    existing_argument.setRequired(base_argument.isRequired());
-		    existing_argument.setType(base_argument.getType());
-		    existing_argument.setMinimum(base_argument.getMinimum());
-		    existing_argument.setMaximum(base_argument.getMaximum());
-		    existing_argument.setOwner(base_argument.getOwner());
-		    existing_argument.setHiddenGLI(base_argument.isHiddenGLI());
-		    add(existing_argument);
-		}
-		// No existing argument. Copy base_argument and add it, but set its assigned flag to false 
-		else {
-		    ///atherer.println("No such argument. Adding new, unassigned, argument.");
-		    // The trick thing is that we have to create a new element in the DOM as well.
-		    Argument new_argument = base_argument.copy();
-		    Element argument_element = CollectionConfiguration.createElement(StaticStrings.OPTION_ELEMENT);
-		    argument_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, base_argument_name);
-		    argument_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
-		    new_argument.setElement(argument_element);
-		    // All done. Add it.
-		    element.appendChild(argument_element);
-		    add(new_argument);
-		}
-	    }
-	}
-	
-	// The first time we do this, the args come from the config file and
-	// may contain invalid args. Here we remove them from the DOM.
-	if (!known_arguments.isEmpty()) {
-	    Set entry_set = known_arguments.entrySet();
-	    Iterator entry_iterator = entry_set.iterator();
-	    while (entry_iterator.hasNext()) {
-		Argument arg = (Argument)((Map.Entry)entry_iterator.next()).getValue();
-		Element e = arg.getElement();
-		element.removeChild(e);
-	    }
-	}
-    }
-
-
-    
-
-    /** Constructor used for the plugins that are in the DOMProxyList */
-    /** Method to add an argument to this container. Only adds the argument if it isn't already present.
-     * @param argument The <strong>Argument</strong> to add.
-     */
-    public void addArgument(Argument argument) {
-	if(element == null && !contains(argument)) {
-	    add(argument);
-	    argument.setOwner(name);
-	}
-    }
-
-    /** Method to compare two containers for ordering.
-     * @param object The container we are comparing to, as an <strong>Object</strong>.
-     * @return An <i>int</i> specifying the container order, using values as set out in String.
-     * @see java.lang.String#compareTo
-     */
-    public int compareTo(Object object) {
-	if(object == null ) {
-	    return -1;
-	}
-	return toString().compareTo(object.toString());
-    }
-
-    /** Method to determine if two containers are equal.
-     * @param object The container to test against, as an <strong>Object</strong>.
-     * @return <i>true</i> if they match (based on the equals method), <i>false</i> otherwise.
-     */
-
-    public boolean equals(Object object) {
-	return (compareTo(object) == 0);
-    }
-
-    abstract public DOMProxyListEntry create(Element element);
-    /** Method to retrieve an argument by its name.
-     * @param name The name of the argument as a <strong>String</strong>.
-     * @return The <strong>Argument</strong> requested, or <i>null</i> if no such argument.
-     */
-    public Argument getArgument(String name) {
-	// The name given may still include the '-'
-	if(name.startsWith("-")) {
-	    name = name.substring(1);
-	}
-	//ArrayList arguments = getArguments(true, true);
-	ArrayList arguments = getArguments();
-	for(int i = 0; i < arguments.size(); i++) {
-	    Argument argument = (Argument)arguments.get(i);
-	    if(argument.getName().equals(name)) {
-		return argument;
-	    }
-	}
-	return null;
-    }
-
-    /** Method to retrieve the list of arguments from this container. Note that this method returns both the containers arguments plus its 'supers' arguments if any, and alphabetically orders them.
-     * @return the arguments within a ArrayList
-     */
-    public ArrayList getArguments() {
-	ArrayList arguments = new ArrayList();
-	arguments.addAll(this);
-	if(super_container != null) {
-	    ArrayList remainder = super_container.getArguments();
-	    remainder.removeAll(arguments);
-	    arguments.addAll(remainder);
-	}
-	return arguments;
-
-    }
-
-    public String getDescription() {
-	return description;
-    }
-
-    public Element getElement() {
-	return element;
-    }
-    /** Method to retrieve the name associated with this argument container.
-     * @return the name as a String
-     */
-    public String getName() {
-	if(name == null && element != null) {
-	    name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
-	}
-	return name;
-    }
-
-    public boolean isAbstract() {
-	return is_abstract;
-    }
-
-    public boolean isAssigned() {
-	return (element != null && !element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR));
-    }
-
-    public void setAssigned(boolean assigned) {
-	if(element != null) {
-	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
-	}
-    }
-
-    public void setDescription(String description) {
-	this.description = description;
-    }
-
-    public void setElement(Element element) {
-	this.element = element;
-    }
-
-    public void setIsAbstract(boolean is_abstract) {
-	this.is_abstract = is_abstract;
-    }
-
-    public void setName(String name) {
-	this.name = name;
-    }
-
-    /** Method to set the value of the super_container.
-     * @param super_container The new value of super_container as a <strong>ArgumentContainer</strong>, or <i>null</i> if this class has no inheritance.
-     */
-    public void setSuper(ArgumentContainer super_container) {
-	this.super_container = super_container;
-    }
-
-    public String toString()
-    {
-	if (element == null) {
-	    return name;
-	}
-
-	if (name == null) {
-	    name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
-	}
-
-	StringBuffer text = new StringBuffer(" ");
-	if (!isAssigned()) {
-	    text.append("#");
-	}
-	text.append(name);
-
-	ArrayList arguments = getArguments();
-	for (int i = 0; i < arguments.size(); i++) {
-	    Argument argument = (Argument) arguments.get(i);
-	    if (argument.isAssigned()) {
-		text.append(" ");
-		text.append(argument.toString());
-	    }
-	}
-
-	return text.toString();
-    }
-
-    public ArrayList getArguments(boolean include_normal, boolean include_custom){
-	return this;
-    }
+extends ArrayList 
+implements Comparable, DOMProxyListEntry, Serializable  {
+
+	// The DOM Element this container is modelled on
+	protected Element element;
+	protected boolean is_abstract = false;
+	protected ArgumentContainer super_container;
+	protected String description;
+	protected String name;
+
+	/** Constructor used in DOMProxyListModel initializations
+	 */
+	public ArgumentContainer() {
+	}
+
+	public ArgumentContainer(Element element, ArgumentContainer base_container) {
+
+		super();
+		this.element = element;
+		this.name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
+
+		// Parse in any argument options for this container, keeping a list of the ones found
+		HashMap known_arguments = new HashMap();
+		NodeList option_elements = element.getElementsByTagName(StaticStrings.OPTION_ELEMENT);
+		int option_elements_length = option_elements.getLength();
+		for(int i = 0; i < option_elements_length; i++) {
+			Element option_element = (Element) option_elements.item(i);
+			Argument argument = new Argument(option_element);
+			///ystem.err.println("Rebuilding existing argument: " + argument.getName());
+			known_arguments.put(argument.getName(), argument);
+		}
+		// If a base classifier was given
+		if(base_container != null) {
+			// Copy the details, and add a reference to whatever the base container's super container is
+			description = base_container.getDescription();
+			// Now search through the 'dummy' arguments belonging to the base container. For each found, if it is already assigned, fill out further details such as type. If any are found that are not already assigned for this container, copy them and add them, but without a value.
+			ArrayList all_arguments = base_container.getArguments();
+			int argument_count = all_arguments.size();
+			for(int j = 0; j < argument_count; j++) {
+				Argument base_argument = (Argument) all_arguments.get(j);
+				String base_argument_name = base_argument.getName();
+				///ystem.err.println("Library indicates this container should have an argument: " + base_argument_name);
+				Argument existing_argument = (Argument) known_arguments.get(base_argument_name);
+				// Found an existing argument. Complete its details
+				if(existing_argument != null) {
+					///ystem.err.println("Found existing argument. Filling out details.");
+					known_arguments.remove(base_argument_name);
+					existing_argument.setDispalyName(base_argument.getDisplayName());
+					existing_argument.setDefaultValue(base_argument.getDefaultValue());
+					existing_argument.setDescription(base_argument.getDescription());
+					existing_argument.setOptions(base_argument.getOptions());
+					existing_argument.setRequired(base_argument.isRequired());
+					existing_argument.setType(base_argument.getType());
+					existing_argument.setMinimum(base_argument.getMinimum());
+					existing_argument.setMaximum(base_argument.getMaximum());
+					existing_argument.setOwner(base_argument.getOwner());
+					existing_argument.setHiddenGLI(base_argument.isHiddenGLI());
+					add(existing_argument);
+				}
+				// No existing argument. Copy base_argument and add it, but set its assigned flag to false 
+				else {
+					///atherer.println("No such argument. Adding new, unassigned, argument.");
+					// The trick thing is that we have to create a new element in the DOM as well.
+					Argument new_argument = base_argument.copy();
+					Element argument_element = CollectionConfiguration.createElement(StaticStrings.OPTION_ELEMENT);
+					argument_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, base_argument_name);
+					argument_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+					new_argument.setElement(argument_element);
+					// All done. Add it.
+					element.appendChild(argument_element);
+					add(new_argument);
+				}
+			}
+		}
+
+		// The first time we do this, the args come from the config file and
+		// may contain invalid args. Here we remove them from the DOM.
+		if (!known_arguments.isEmpty()) {
+			Set entry_set = known_arguments.entrySet();
+			Iterator entry_iterator = entry_set.iterator();
+			while (entry_iterator.hasNext()) {
+				Argument arg = (Argument)((Map.Entry)entry_iterator.next()).getValue();
+				Element e = arg.getElement();
+				element.removeChild(e);
+			}
+		}
+	}
+
+
+
+
+	/** Constructor used for the plugins that are in the DOMProxyList */
+	/** Method to add an argument to this container. Only adds the argument if it isn't already present.
+	 * @param argument The <strong>Argument</strong> to add.
+	 */
+	public void addArgument(Argument argument) {
+		if(element == null && !contains(argument)) {
+			add(argument);
+			argument.setOwner(name);
+		}
+	}
+
+	/** Method to compare two containers for ordering.
+	 * @param object The container we are comparing to, as an <strong>Object</strong>.
+	 * @return An <i>int</i> specifying the container order, using values as set out in String.
+	 * @see java.lang.String#compareTo
+	 */
+	public int compareTo(Object object) {
+		if(object == null ) {
+			return -1;
+		}
+		return toString().compareTo(object.toString());
+	}
+
+	/** Method to determine if two containers are equal.
+	 * @param object The container to test against, as an <strong>Object</strong>.
+	 * @return <i>true</i> if they match (based on the equals method), <i>false</i> otherwise.
+	 */
+
+	public boolean equals(Object object) {
+		return (compareTo(object) == 0);
+	}
+
+	abstract public DOMProxyListEntry create(Element element);
+	/** Method to retrieve an argument by its name.
+	 * @param name The name of the argument as a <strong>String</strong>.
+	 * @return The <strong>Argument</strong> requested, or <i>null</i> if no such argument.
+	 */
+	public Argument getArgument(String name) {
+		// The name given may still include the '-'
+		if(name.startsWith("-")) {
+			name = name.substring(1);
+		}
+		//ArrayList arguments = getArguments(true, true);
+		ArrayList arguments = getArguments();
+		for(int i = 0; i < arguments.size(); i++) {
+			Argument argument = (Argument)arguments.get(i);
+			if(argument.getName().equals(name)) {
+				return argument;
+			}
+		}
+		return null;
+	}
+
+	/** Method to retrieve the list of arguments from this container. Note that this method returns both the containers arguments plus its 'supers' arguments if any, and alphabetically orders them.
+	 * @return the arguments within a ArrayList
+	 */
+	public ArrayList getArguments() {
+		ArrayList arguments = new ArrayList();
+		arguments.addAll(this);
+		if(super_container != null) {
+			ArrayList remainder = super_container.getArguments();
+			remainder.removeAll(arguments);
+			arguments.addAll(remainder);
+		}
+		return arguments;
+
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public Element getElement() {
+		return element;
+	}
+	/** Method to retrieve the name associated with this argument container.
+	 * @return the name as a String
+	 */
+	public String getName() {
+		if(name == null && element != null) {
+			name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
+		}
+		return name;
+	}
+
+	public boolean isAbstract() {
+		return is_abstract;
+	}
+
+	public boolean isAssigned() {
+		return (element != null && !element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR));
+	}
+
+	public void setAssigned(boolean assigned) {
+		if(element != null) {
+			element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+		}
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	public void setElement(Element element) {
+		this.element = element;
+	}
+
+	public void setIsAbstract(boolean is_abstract) {
+		this.is_abstract = is_abstract;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/** Method to set the value of the super_container.
+	 * @param super_container The new value of super_container as a <strong>ArgumentContainer</strong>, or <i>null</i> if this class has no inheritance.
+	 */
+	public void setSuper(ArgumentContainer super_container) {
+		this.super_container = super_container;
+	}
+
+	public String toString()
+	{
+		if (element == null) {
+			return name;
+		}
+
+		if (name == null) {
+			name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
+		}
+
+		StringBuffer text = new StringBuffer(" ");
+		if (!isAssigned()) {
+			text.append("#");
+		}
+		text.append(name);
+
+		ArrayList arguments = getArguments();
+		for (int i = 0; i < arguments.size(); i++) {
+			Argument argument = (Argument) arguments.get(i);
+			if (argument.isAssigned()) {
+				text.append(" ");
+				text.append(argument.toString());
+			}
+		}
+
+		return text.toString();
+	}
+
+	public ArrayList getArguments(boolean include_normal, boolean include_custom){
+		return this;
+	}
 }
Index: /gli/trunk/src/org/greenstone/gatherer/cdm/ArgumentControl.java
===================================================================
--- /gli/trunk/src/org/greenstone/gatherer/cdm/ArgumentControl.java	(revision 14782)
+++ /gli/trunk/src/org/greenstone/gatherer/cdm/ArgumentControl.java	(revision 14783)
@@ -26,545 +26,556 @@
 /** This class encapsulates all the technical difficulty of creating a specific control based on an Argument. */
 public class ArgumentControl
-    extends JPanel {
-
-    static protected Dimension LABEL_SIZE = new Dimension(175, 25);
-    static protected Dimension ROW_SIZE = new Dimension(400, 30);
-    /** The Argument this control will be based on. */
-    private Argument argument = null;
-
-    /** A checkbox to allow enabling or diabling of this Argument. */
-    private JCheckBox enabled = null;
-    /** Some form of editor component, such as a JComboBox or JTextField, used to set parameters to an Argument. */
-    private JComponent value_control = null;
-	
-    /** Constructor.
-     */
-    public ArgumentControl(Argument argument, boolean is_enabled, String preset_value) {
-	this.argument = argument;
-
-	String tip = "<html>" + argument.getName()+": "+argument.getDescription() + "</html>";
-	tip = Utility.formatHTMLWidth(tip, 80);
-
-	setBackground(Configuration.getColor("coloring.collection_tree_background", false));
-	setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
-	setLayout(new BorderLayout());
-	setPreferredSize(ROW_SIZE);
-
-	if (argument.isRequired()) {
-	    JLabel label = new JLabel(argument.getName());
-	    label.setOpaque(false);
-	    label.setPreferredSize(LABEL_SIZE);
-	    label.setToolTipText(tip);
-	    add(label, BorderLayout.WEST);
-	} else {
-	    enabled = new JCheckBox(argument.getName());
-	    enabled.setOpaque(false);
-	    enabled.setPreferredSize(LABEL_SIZE);
-	    enabled.setToolTipText(tip);
-	    add(enabled, BorderLayout.WEST);
-	}
-	
-	String initial_value;
-	if (preset_value != null && !preset_value.equals("")) {
-	    initial_value = preset_value;
-	}
-	else {
-	    initial_value = argument.getValue();
-	}
-	if (initial_value == null || initial_value.equals("")) {
-	    initial_value = argument.getDefaultValue();
-	}
-	if (initial_value == null) {
-	    initial_value = "";
-	}
-	
-	switch(argument.getType()) {
-	case Argument.ENUM:
-	    ArrayList option_list = argument.getOptions();
-	    value_control = new GComboBox(option_list.toArray(), false, false);
-	    selectValue((JComboBox)value_control, initial_value); // also sets the tooltip
-	    ((JComboBox)value_control).addActionListener(new ToolTipUpdater());
-	    break;
-	    
-	case Argument.FLAG:
-	    // Only need the check box.
-	    break;
-
-	case Argument.INTEGER:
-	    // Build a spinner
-	    int initial_int=0;
-	    // If there was an original value, set it.
-	    try {
-		initial_int = Integer.parseInt(initial_value);
-	    } catch (Exception error) {
-		DebugStream.println("ArgumentControl Error: "+error);
-	    }
-	    if (initial_int < argument.getMinimum()) {
-		initial_int = argument.getMinimum();
-	    } else if (initial_int > argument.getMaximum()) {
-		initial_int = argument.getMaximum();
-	    }
-	    
-	    JSpinner spinner = new JSpinner(new SpinnerNumberModel(initial_int, argument.getMinimum(), argument.getMaximum(), 1));
-
-	    // And remember it
-	    value_control = spinner;
-	    break;
-
-	case Argument.REGEXP:
-	case Argument.STRING:
-	    value_control = new JTextField(initial_value);
-		break;
+extends JPanel {
+
+	static protected Dimension LABEL_SIZE = new Dimension(175, 25);
+	static protected Dimension ROW_SIZE = new Dimension(400, 30);
+	/** The Argument this control will be based on. */
+	private Argument argument = null;
+
+	/** A checkbox to allow enabling or diabling of this Argument. */
+	private JCheckBox enabled = null;
+	/** Some form of editor component, such as a JComboBox or JTextField, used to set parameters to an Argument. */
+	private JComponent value_control = null;
+
+	/** Constructor.
+	 */
+	public ArgumentControl(Argument argument, boolean is_enabled, String preset_value) {
+		this.argument = argument;
+
+		String tip = "<html>" + argument.getName()+": "+argument.getDescription() + "</html>";
+		tip = Utility.formatHTMLWidth(tip, 80);
+
+		setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+		setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+		setLayout(new BorderLayout());
+		setPreferredSize(ROW_SIZE);
 		
-	case Argument.LANGUAGE:
-	    value_control = new GComboBox(CollectionDesignManager.language_manager.getLanguageCodes().toArray(), false);
-	    // we want to display the language name not the code
-	    ((JComboBox)value_control).setRenderer(new LanguageListCellRenderer());
-	    // Now ensure we have the existing value or default value selected if either exist in our known languages
-	    String lang_name = CollectionDesignManager.language_manager.getLanguageName(initial_value);
-	    if (lang_name != null) {
-		((JComboBox)value_control).setSelectedItem(initial_value);
-	    }
-	    break;
-
-	case Argument.METADATUM:
-	case Argument.METADATA:
-	    value_control = new GComboBox(MetadataSetManager.getEveryMetadataSetElement(), false);
-
-	    // Editable for advanced modes (allows things like dc.Title,ex.Title)
-	    if (Configuration.getMode() > Configuration.ASSISTANT_MODE) {
-		((JComboBox) value_control).setEditable(true);
-	    }
-	    // Now ensure we have the existing value or default value selected if either exist.
-	    String existing_value = preset_value;
-	    if (existing_value == null || existing_value.length() == 0) {
-		existing_value = argument.getValue();
-	    }
-	    if (existing_value != null && existing_value.length() > 0) {
-		boolean found = selectValue((JComboBox) value_control, existing_value);
-		// It's possible that this is a custom value and so doesn't exist in the combobox
-		if (!found) {
-		    // If so, add it then select it
-		    ((JComboBox) value_control).addItem(existing_value);
-		    ((JComboBox) value_control).setSelectedItem(existing_value);
-		}
-	    }
-	    else {
-		String default_value = argument.getDefaultValue();
-		if (default_value != null) {
-		    // if no namespace for default value, add ex.
-		    // won't work if we want to set a non-metadata value
-		    if (MetadataTools.getMetadataSetNamespace(default_value).equals("")) {
-			default_value = StaticStrings.EXTRACTED_NAMESPACE+default_value;
-		    }
-		    selectValue((JComboBox) value_control, default_value);
-		}
-	    }
-	    break;
-
-	case Argument.METADATA_SET_NAMESPACE:
-	    value_control = new JComboBox();
-	    // !! Hack for exploding metadata databases: add the (empty) exploded metadata set
-	    File exploded_metadata_set_file = new File(Gatherer.getGLIMetadataDirectoryPath() + "exp" + StaticStrings.METADATA_SET_EXTENSION);
-	    MetadataSet exploded_metadata_set = new MetadataSet(exploded_metadata_set_file);
-	    Gatherer.c_man.importMetadataSet(exploded_metadata_set);
-
-	    // All the loaded metadata sets except the extracted metadata set are applicable
-	    ArrayList metadata_sets = MetadataSetManager.getMetadataSets();
-	    for (int i = metadata_sets.size() - 1; i >= 0; i--) {
-		MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i);
-		if (!(metadata_set.getNamespace().equals(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE))) {
-		    ((JComboBox)value_control).addItem(metadata_set);
-		}
-	    }
-
-	    selectValue((JComboBox) value_control, initial_value);
-
-	} // end of switch
-
-	// Enable or disable as necessary.
-	if(argument.isRequired() || argument.isAssigned() || is_enabled) {
-	    if (enabled != null) {
+		// display the name set in the disp option if there is one
+		// otherwise display name option value instead
+		String dispName = argument.getDisplayName();
+		if(dispName.equals("")){
+			dispName = argument.getName();
+		}
+
+		if (argument.isRequired()) {		
+			//JLabel label = new JLabel(argument.getName());
+			JLabel label = new JLabel(dispName);
+
+			label.setOpaque(false);
+			label.setPreferredSize(LABEL_SIZE);
+			label.setToolTipText(tip);
+			add(label, BorderLayout.WEST);
+		} else {
+			//enabled = new JCheckBox(argument.getName());
+			enabled = new JCheckBox(dispName);
+
+			enabled.setOpaque(false);
+			enabled.setPreferredSize(LABEL_SIZE);
+			enabled.setToolTipText(tip);
+			add(enabled, BorderLayout.WEST);
+		}
+
+		String initial_value;
+		if (preset_value != null && !preset_value.equals("")) {
+			initial_value = preset_value;
+		}
+		else {
+			initial_value = argument.getValue();
+		}
+		if (initial_value == null || initial_value.equals("")) {
+			initial_value = argument.getDefaultValue();
+		}
+		if (initial_value == null) {
+			initial_value = "";
+		}
+
+		switch(argument.getType()) {
+		case Argument.ENUM:
+			ArrayList option_list = argument.getOptions();
+			value_control = new GComboBox(option_list.toArray(), false, false);
+			selectValue((JComboBox)value_control, initial_value); // also sets the tooltip
+			((JComboBox)value_control).addActionListener(new ToolTipUpdater());
+			break;
+
+		case Argument.FLAG:
+			// Only need the check box.
+			break;
+
+		case Argument.INTEGER:
+			// Build a spinner
+			int initial_int=0;
+			// If there was an original value, set it.
+			try {
+				initial_int = Integer.parseInt(initial_value);
+			} catch (Exception error) {
+				DebugStream.println("ArgumentControl Error: "+error);
+			}
+			if (initial_int < argument.getMinimum()) {
+				initial_int = argument.getMinimum();
+			} else if (initial_int > argument.getMaximum()) {
+				initial_int = argument.getMaximum();
+			}
+
+			JSpinner spinner = new JSpinner(new SpinnerNumberModel(initial_int, argument.getMinimum(), argument.getMaximum(), 1));
+
+			// And remember it
+			value_control = spinner;
+			break;
+
+		case Argument.REGEXP:
+		case Argument.STRING:
+			value_control = new JTextField(initial_value);
+			break;
+
+		case Argument.LANGUAGE:
+			value_control = new GComboBox(CollectionDesignManager.language_manager.getLanguageCodes().toArray(), false);
+			// we want to display the language name not the code
+			((JComboBox)value_control).setRenderer(new LanguageListCellRenderer());
+			// Now ensure we have the existing value or default value selected if either exist in our known languages
+			String lang_name = CollectionDesignManager.language_manager.getLanguageName(initial_value);
+			if (lang_name != null) {
+				((JComboBox)value_control).setSelectedItem(initial_value);
+			}
+			break;
+
+		case Argument.METADATUM:
+		case Argument.METADATA:
+			value_control = new GComboBox(MetadataSetManager.getEveryMetadataSetElement(), false);
+
+			// Editable for advanced modes (allows things like dc.Title,ex.Title)
+			if (Configuration.getMode() > Configuration.ASSISTANT_MODE) {
+				((JComboBox) value_control).setEditable(true);
+			}
+			// Now ensure we have the existing value or default value selected if either exist.
+			String existing_value = preset_value;
+			if (existing_value == null || existing_value.length() == 0) {
+				existing_value = argument.getValue();
+			}
+			if (existing_value != null && existing_value.length() > 0) {
+				boolean found = selectValue((JComboBox) value_control, existing_value);
+				// It's possible that this is a custom value and so doesn't exist in the combobox
+				if (!found) {
+					// If so, add it then select it
+					((JComboBox) value_control).addItem(existing_value);
+					((JComboBox) value_control).setSelectedItem(existing_value);
+				}
+			}
+			else {
+				String default_value = argument.getDefaultValue();
+				if (default_value != null) {
+					// if no namespace for default value, add ex.
+					// won't work if we want to set a non-metadata value
+					if (MetadataTools.getMetadataSetNamespace(default_value).equals("")) {
+						default_value = StaticStrings.EXTRACTED_NAMESPACE+default_value;
+					}
+					selectValue((JComboBox) value_control, default_value);
+				}
+			}
+			break;
+
+		case Argument.METADATA_SET_NAMESPACE:
+			value_control = new JComboBox();
+			// !! Hack for exploding metadata databases: add the (empty) exploded metadata set
+			File exploded_metadata_set_file = new File(Gatherer.getGLIMetadataDirectoryPath() + "exp" + StaticStrings.METADATA_SET_EXTENSION);
+			MetadataSet exploded_metadata_set = new MetadataSet(exploded_metadata_set_file);
+			Gatherer.c_man.importMetadataSet(exploded_metadata_set);
+
+			// All the loaded metadata sets except the extracted metadata set are applicable
+			ArrayList metadata_sets = MetadataSetManager.getMetadataSets();
+			for (int i = metadata_sets.size() - 1; i >= 0; i--) {
+				MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i);
+				if (!(metadata_set.getNamespace().equals(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE))) {
+					((JComboBox)value_control).addItem(metadata_set);
+				}
+			}
+
+			selectValue((JComboBox) value_control, initial_value);
+
+		} // end of switch
+
+		// Enable or disable as necessary.
+		if(argument.isRequired() || argument.isAssigned() || is_enabled) {
+			if (enabled != null) {
+				enabled.setSelected(true);
+			}
+			if(value_control != null) {
+				value_control.setOpaque(true);
+				value_control.setBackground(Color.white);
+				value_control.setEnabled(true);
+				if(value_control instanceof JSpinner) {
+					// Set enabled
+					JComponent c = ((JSpinner)value_control).getEditor();
+					if ( c instanceof JSpinner.DefaultEditor ) {
+						JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
+						JFormattedTextField field = editor.getTextField();
+						field.setEditable(true);
+						field.setBackground(Color.white);
+					}
+				}
+			}
+		}
+		else {
+			if (enabled != null) {
+				enabled.setSelected(false);
+			}
+			if(value_control != null) {
+				value_control.setOpaque(true);
+				value_control.setBackground(Color.lightGray);
+				value_control.setEnabled(false);
+				if(value_control instanceof JSpinner) {
+					// Set enabled
+					JComponent c = ((JSpinner)value_control).getEditor();
+					if ( c instanceof JSpinner.DefaultEditor ) {
+						JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
+						JFormattedTextField field = editor.getTextField();
+						field.setEditable(false);
+						field.setBackground(Color.lightGray);
+					}
+				}
+			}
+		}
+
+		// Listener
+		if(value_control != null) {
+			if (argument.getType() != Argument.ENUM) {
+				// enums have already set tooltips based on option value
+				value_control.setToolTipText(tip);
+			}
+			add(value_control, BorderLayout.CENTER);
+			if (!argument.isRequired()) {
+				enabled.addActionListener(new EnabledListener(value_control));
+			}
+		}
+	}
+
+	public Argument getArgument() {
+		return argument;
+	}
+
+	public String getArgumentName() {
+		return argument.getName();
+	}
+
+	public String getValue() {
+		if(value_control == null) {
+			return null;
+		}
+		if (value_control instanceof JSpinner) {
+			return ((JSpinner)value_control).getValue().toString();
+		}
+		if(value_control instanceof JComboBox) {
+			Object selected_item = ((JComboBox)value_control).getSelectedItem();
+			if (selected_item != null) {
+				if (argument.getType() == Argument.METADATA_SET_NAMESPACE) {
+					return ((MetadataSet) selected_item).getNamespace();
+				}
+				if (selected_item instanceof Argument.ArgumentOption) {
+					return ((Argument.ArgumentOption)selected_item).name;
+				}
+				if (selected_item instanceof MetadataElement) {
+					return ((MetadataElement) selected_item).getFullName();
+				}
+				return selected_item.toString();
+			}    
+			return null;
+		}
+		if(value_control instanceof JTextField) {
+			return ((JTextField)value_control).getText();
+		}
+		return null;
+	}
+	/** Retrieve the control used for storing values.
+	 * @return JComponent
+	 */
+	public JComponent getValueControl() {
+		return value_control;
+	}
+
+	public boolean isEnabled() {
+		if (enabled == null) {
+			return true; // always enabled
+		} 
+		return enabled.isSelected();
+	}
+
+
+	/** Identifies this control by returning the name of the Argument it is based on.
+	 * @return The name of the Argument as a <strong>String</strong>.
+	 * @see org.greenstone.gatherer.cdm.Argument
+	 */
+	public String toString() {
+		return argument.getName();
+	}
+	/** Updates the enwrapped Argument using the values provided by the controls.
+	 * @return <i>true</i> if the update was successful, <i>false</i> otherwise.
+	 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.Argument.ArgumentOption
+	 * @see org.greenstone.gatherer.cdm.Language
+	 */
+	public boolean updateArgument() {
+		if(argument.isRequired() || enabled.isSelected() ) {
+			argument.setAssigned(false);
+			String result = null;
+			switch(argument.getType()) {
+			case Argument.ENUM:
+				Argument.ArgumentOption option = (Argument.ArgumentOption)((JComboBox)value_control).getSelectedItem();
+				if(option != null && option.name.length() > 0) {
+					argument.setValue(option.name);
+				}
+				else {
+					String args[] = new String[1];
+					args[0] = argument.getName();
+					if(argument.isRequired()) {
+						JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+					}
+					// They've left the field blank
+					else {
+						JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+						argument.setValue(null);
+					}
+					args = null;
+					return false;
+				}
+				argument.setAssigned(true);
+				return true;
+			case Argument.FLAG:
+				// Should have already been handled above.
+				argument.setAssigned(true);
+				return true;
+			case Argument.INTEGER:
+				result = ((JSpinner)value_control).getValue().toString();
+				if(result.length() > 0) {
+					// Test if the value entered is a valid int.
+					try {
+						int x = Integer.parseInt(result);
+					}
+					catch(NumberFormatException nfe) {
+						String args[] = new String[2];
+						args[0] = argument.getName();
+						args[1] = result;
+						JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Bad_Integer", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+						args = null;
+						return false;
+					}
+					argument.setValue(result);
+				}
+				else {
+					String args[] = new String[1];
+					args[0] = argument.getName();
+					if(argument.isRequired()) {
+						JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+					}
+					// They've left the field blank
+					else {
+						JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+						argument.setValue(null);
+					}
+					args = null;
+					return false;
+				}
+				argument.setAssigned(true);
+				return true;
+			case Argument.LANGUAGE:
+				String language = (((JComboBox)value_control).getSelectedItem()).toString();
+				argument.setValue(language);
+				// Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
+				argument.setAssigned(true);
+				return true;
+			case Argument.METADATUM:
+			case Argument.METADATA:
+				Object new_value_raw = ((JComboBox) value_control).getSelectedItem();
+				if (new_value_raw instanceof MetadataElement) {
+					argument.setValue(((MetadataElement) new_value_raw).getFullName());
+				}
+				else {
+					// But we have to be careful as an arbitary string object could be zero length
+					String new_value = new_value_raw.toString();
+					///ystem.err.println("The current value is: " + new_value);
+					if(new_value.length() > 0) {
+						argument.setValue(new_value);
+					}
+					else {
+						String args[] = new String[1];
+						args[0] = argument.getName();
+						if(argument.isRequired()) {
+							JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+						}
+						// They've left the field blank
+						else {
+							JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+							argument.setValue(null);
+						}
+						args = null;
+						return false;
+					}
+				}
+				argument.setAssigned(true);
+				return true;
+			case Argument.REGEXP:
+			case Argument.STRING:
+				result = ((JTextField)value_control).getText();
+				if(result.length() > 0) {
+					argument.setValue(result);
+				}
+				else {
+					String args[] = new String[1];
+					args[0] = argument.getName();
+					if(argument.isRequired()) {
+						JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+					}
+					// They've left the field blank
+					else {
+						JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+						argument.setValue(null);
+					}
+					args = null;
+					return false;
+				}
+				argument.setAssigned(true);
+				return true;
+			}
+			return false;
+		}
+		else {
+			argument.setAssigned(false);
+			return true;
+		}
+	}
+
+
+	public boolean updateArgument(boolean checkRequired) {
+
+
+		if (checkRequired){
+			return updateArgument();
+		}
+		else{
+			if (argument.getType() == Argument.STRING){
+				String result = ((JTextField)value_control).getText();
+
+				if(result.length() > 0) {
+					argument.setValue(result);
+					argument.setAssigned(true);                    
+				}
+			}	
+		}
+
+		return true;
+
+	}
+
+
+
+	/** Method to ensure that a certain value is selected, if it exists within that combobox to begin with.
+	 * @param combobox The <strong>JComboBox</strong> whose selection we are trying to preset.
+	 * @param target The desired value of the selection as a <strong>String</strong>.
+	 * @return true if the item was found and selected, false otherwise
+	 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.Argument.ArgumentOption
+	 */
+	public static boolean selectValue(JComboBox combobox, String target)
+	{
+		for (int i = 0; i < combobox.getItemCount(); i++) {
+			Object object = combobox.getItemAt(i);
+
+			if (object instanceof Argument.ArgumentOption) {
+				Argument.ArgumentOption opt = (Argument.ArgumentOption) object;
+				if (opt.name.startsWith(target)) {
+					combobox.setSelectedIndex(i);
+					combobox.setToolTipText(opt.getToolTip());
+					return true;
+				}
+			}
+			else if (object instanceof MetadataElement) {
+				if(((MetadataElement)object).getFullName().equals(target)) {
+					combobox.setSelectedIndex(i);
+					return true;
+				}
+			}
+			else if (object.toString().equals(target)) {
+				combobox.setSelectedIndex(i);
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+
+	/** Forces the control into an 'enabled' mode. */
+	public void setEnabled() {
 		enabled.setSelected(true);
-	    }
-	    if(value_control != null) {
-		value_control.setOpaque(true);
-		value_control.setBackground(Color.white);
-		value_control.setEnabled(true);
-		if(value_control instanceof JSpinner) {
-		    // Set enabled
-		    JComponent c = ((JSpinner)value_control).getEditor();
-		    if ( c instanceof JSpinner.DefaultEditor ) {
-			JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
-			JFormattedTextField field = editor.getTextField();
-			field.setEditable(true);
-			field.setBackground(Color.white);
-		    }
-		}
-	    }
-	}
-	else {
-	    if (enabled != null) {
-		enabled.setSelected(false);
-	    }
-	    if(value_control != null) {
-		value_control.setOpaque(true);
-		value_control.setBackground(Color.lightGray);
-		value_control.setEnabled(false);
-		if(value_control instanceof JSpinner) {
-		    // Set enabled
-		    JComponent c = ((JSpinner)value_control).getEditor();
-		    if ( c instanceof JSpinner.DefaultEditor ) {
-			JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
-			JFormattedTextField field = editor.getTextField();
-			field.setEditable(false);
-			field.setBackground(Color.lightGray);
-		    }
-		}
-	    }
-	}
-	
-	// Listener
-	if(value_control != null) {
-	    if (argument.getType() != Argument.ENUM) {
-		// enums have already set tooltips based on option value
-		value_control.setToolTipText(tip);
-	    }
-	    add(value_control, BorderLayout.CENTER);
-	    if (!argument.isRequired()) {
-		enabled.addActionListener(new EnabledListener(value_control));
-	    }
-	}
-    }
-    
-    public Argument getArgument() {
-	return argument;
-    }
-
-    public String getArgumentName() {
-	return argument.getName();
-    }
-
-    public String getValue() {
-	if(value_control == null) {
-	    return null;
-	}
-	if (value_control instanceof JSpinner) {
-	    return ((JSpinner)value_control).getValue().toString();
-	}
-	if(value_control instanceof JComboBox) {
-	    Object selected_item = ((JComboBox)value_control).getSelectedItem();
-	    if (selected_item != null) {
-		if (argument.getType() == Argument.METADATA_SET_NAMESPACE) {
-		    return ((MetadataSet) selected_item).getNamespace();
-		}
-		if (selected_item instanceof Argument.ArgumentOption) {
-		    return ((Argument.ArgumentOption)selected_item).name;
-		}
-		if (selected_item instanceof MetadataElement) {
-		    return ((MetadataElement) selected_item).getFullName();
-		}
-		return selected_item.toString();
-	    }    
-	    return null;
-	}
-	if(value_control instanceof JTextField) {
-	    return ((JTextField)value_control).getText();
-	}
-	return null;
-    }
-    /** Retrieve the control used for storing values.
-     * @return JComponent
-     */
-    public JComponent getValueControl() {
-	return value_control;
-    }
-
-    public boolean isEnabled() {
-	if (enabled == null) {
-	    return true; // always enabled
-	} 
-	return enabled.isSelected();
-    }
-
-
-    /** Identifies this control by returning the name of the Argument it is based on.
-     * @return The name of the Argument as a <strong>String</strong>.
-     * @see org.greenstone.gatherer.cdm.Argument
-     */
-    public String toString() {
-	return argument.getName();
-    }
-    /** Updates the enwrapped Argument using the values provided by the controls.
-     * @return <i>true</i> if the update was successful, <i>false</i> otherwise.
-     * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.Argument.ArgumentOption
-     * @see org.greenstone.gatherer.cdm.Language
-     */
-    public boolean updateArgument() {
-	if(argument.isRequired() || enabled.isSelected() ) {
-	    argument.setAssigned(false);
-	    String result = null;
-	    switch(argument.getType()) {
-	    case Argument.ENUM:
-		Argument.ArgumentOption option = (Argument.ArgumentOption)((JComboBox)value_control).getSelectedItem();
-		if(option != null && option.name.length() > 0) {
-		    argument.setValue(option.name);
-		}
-		else {
-		    String args[] = new String[1];
-		    args[0] = argument.getName();
-		    if(argument.isRequired()) {
-			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
-		    }
-		    // They've left the field blank
-		    else {
-			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
-			argument.setValue(null);
-		    }
-		    args = null;
-		    return false;
-		}
-		argument.setAssigned(true);
-		return true;
-	    case Argument.FLAG:
-		// Should have already been handled above.
-		argument.setAssigned(true);
-		return true;
-	    case Argument.INTEGER:
-		result = ((JSpinner)value_control).getValue().toString();
-		if(result.length() > 0) {
-		    // Test if the value entered is a valid int.
-		    try {
-			int x = Integer.parseInt(result);
-		    }
-		    catch(NumberFormatException nfe) {
-			String args[] = new String[2];
-			args[0] = argument.getName();
-			args[1] = result;
-			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Bad_Integer", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
-			args = null;
-			return false;
-		    }
-		    argument.setValue(result);
-		}
-		else {
-		    String args[] = new String[1];
-		    args[0] = argument.getName();
-		    if(argument.isRequired()) {
-			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
-		    }
-		    // They've left the field blank
-		    else {
-			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
-			argument.setValue(null);
-		    }
-		    args = null;
-		    return false;
-		}
-		argument.setAssigned(true);
-		return true;
-	    case Argument.LANGUAGE:
-		String language = (((JComboBox)value_control).getSelectedItem()).toString();
-		argument.setValue(language);
-		// Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
-		argument.setAssigned(true);
-		return true;
-	    case Argument.METADATUM:
-	    case Argument.METADATA:
-		Object new_value_raw = ((JComboBox) value_control).getSelectedItem();
-		if (new_value_raw instanceof MetadataElement) {
-		    argument.setValue(((MetadataElement) new_value_raw).getFullName());
-		}
-		else {
-		    // But we have to be careful as an arbitary string object could be zero length
-		    String new_value = new_value_raw.toString();
-		    ///ystem.err.println("The current value is: " + new_value);
-		    if(new_value.length() > 0) {
-			argument.setValue(new_value);
-		    }
-		    else {
-			String args[] = new String[1];
-			args[0] = argument.getName();
-			if(argument.isRequired()) {
-			    JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
-			}
-			// They've left the field blank
+	}
+	/** Explicitly sets the value of a JTextField type control to the given String.
+	 * @param value_str The new value of the control as a <strong>String</strong>.
+	 */
+	public void setValue(String value_str) {
+		((JTextField)value_control).setText(value_str);
+	}
+
+	/** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */
+	private class EnabledListener
+	implements ActionListener {
+		/** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */
+		private JComponent target = null;
+
+		/** Constructor. */
+		public EnabledListener(JComponent target) {
+			this.target = target;
+		}
+
+		/** Any implementation of ActionListener must include this method so that we can be informed when an action has been performed on or registered check box, prompting us to change the state of the other controls as per the users request.
+		 * @param event An <strong>ActionEvent</strong> containing information about the click.
+		 */
+		public void actionPerformed(ActionEvent event) {
+			if (this.target == null) {
+				return;
+			}
+			JCheckBox source = (JCheckBox)event.getSource();
+			if(source.isSelected()) {
+				target.setBackground(Color.white);
+				target.setEnabled(true);
+			}
 			else {
-			    JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
-			    argument.setValue(null);
-			}
-			args = null;
-			return false;
-		    }
-		}
-		argument.setAssigned(true);
-		return true;
-	    case Argument.REGEXP:
-	    case Argument.STRING:
-		result = ((JTextField)value_control).getText();
-		if(result.length() > 0) {
-		    argument.setValue(result);
-		}
-		else {
-		    String args[] = new String[1];
-		    args[0] = argument.getName();
-		    if(argument.isRequired()) {
-			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
-		    }
-		    // They've left the field blank
-		    else {
-			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
-			argument.setValue(null);
-		    }
-		    args = null;
-		    return false;
-		}
-		argument.setAssigned(true);
-		return true;
-	    }
-	    return false;
-	}
-	else {
-	    argument.setAssigned(false);
-	    return true;
-	}
-    }
-
-    
-    public boolean updateArgument(boolean checkRequired) {
-
-      
-	if (checkRequired){
-	    return updateArgument();
-	}
-	else{
-	    if (argument.getType() == Argument.STRING){
-		String result = ((JTextField)value_control).getText();
-               
-		if(result.length() > 0) {
-		    argument.setValue(result);
-                    argument.setAssigned(true);                    
-		}
-	    }	
-	}
-
-	return true;
-	
-    }
-      
-    
-
-    /** Method to ensure that a certain value is selected, if it exists within that combobox to begin with.
-     * @param combobox The <strong>JComboBox</strong> whose selection we are trying to preset.
-     * @param target The desired value of the selection as a <strong>String</strong>.
-     * @return true if the item was found and selected, false otherwise
-     * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.Argument.ArgumentOption
-     */
-    public static boolean selectValue(JComboBox combobox, String target)
-    {
-	for (int i = 0; i < combobox.getItemCount(); i++) {
-	    Object object = combobox.getItemAt(i);
-
-	    if (object instanceof Argument.ArgumentOption) {
-		Argument.ArgumentOption opt = (Argument.ArgumentOption) object;
-		if (opt.name.startsWith(target)) {
-		    combobox.setSelectedIndex(i);
-		    combobox.setToolTipText(opt.getToolTip());
-		    return true;
-		}
-	    }
-	    else if (object instanceof MetadataElement) {
-		if(((MetadataElement)object).getFullName().equals(target)) {
-		    combobox.setSelectedIndex(i);
-		    return true;
-		}
-	    }
-	    else if (object.toString().equals(target)) {
-		combobox.setSelectedIndex(i);
-		return true;
-	    }
-	}
-
-	return false;
-    }
-
-
-    /** Forces the control into an 'enabled' mode. */
-    public void setEnabled() {
-	enabled.setSelected(true);
-    }
-    /** Explicitly sets the value of a JTextField type control to the given String.
-     * @param value_str The new value of the control as a <strong>String</strong>.
-     */
-    public void setValue(String value_str) {
-	((JTextField)value_control).setText(value_str);
-    }
-
-    /** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */
-    private class EnabledListener
+				target.setBackground(Color.lightGray);
+				target.setEnabled(false);
+			}
+			// Special case of stupid JSpinners who don't let their backgrounds change properly.
+			if(target instanceof JSpinner) {
+				JSpinner spinner = (JSpinner) target;
+				JComponent c = spinner.getEditor();
+				if ( c instanceof JSpinner.DefaultEditor ) {
+					JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
+					JFormattedTextField field = editor.getTextField();
+					field.setEditable(source.isSelected());
+					if(source.isSelected()) {
+						field.setBackground(Color.white);
+					}
+					else {
+						field.setBackground(Color.lightGray);
+					}
+				}
+			}
+		}
+	}
+
+
+	/** Listener that sets the tooltip associated to a combobox to the tooltip relevant to the selected item. */
+	private class ToolTipUpdater
 	implements ActionListener {
-	/** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */
-	private JComponent target = null;
-	
-	/** Constructor. */
-	public EnabledListener(JComponent target) {
-	    this.target = target;
-	}
-	
-	/** Any implementation of ActionListener must include this method so that we can be informed when an action has been performed on or registered check box, prompting us to change the state of the other controls as per the users request.
-	 * @param event An <strong>ActionEvent</strong> containing information about the click.
-	 */
-	public void actionPerformed(ActionEvent event) {
-	    if (this.target == null) {
-		return;
-	    }
-	    JCheckBox source = (JCheckBox)event.getSource();
-	    if(source.isSelected()) {
-		target.setBackground(Color.white);
-		target.setEnabled(true);
-	    }
-	    else {
-		target.setBackground(Color.lightGray);
-		target.setEnabled(false);
-	    }
-	    // Special case of stupid JSpinners who don't let their backgrounds change properly.
-	    if(target instanceof JSpinner) {
-		JSpinner spinner = (JSpinner) target;
-		JComponent c = spinner.getEditor();
-		if ( c instanceof JSpinner.DefaultEditor ) {
-		    JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
-		    JFormattedTextField field = editor.getTextField();
-		    field.setEditable(source.isSelected());
-		    if(source.isSelected()) {
-			field.setBackground(Color.white);
-		    }
-		    else {
-			field.setBackground(Color.lightGray);
-		    }
-		}
-	    }
-	}
-    }
-    
-
-    /** Listener that sets the tooltip associated to a combobox to the tooltip relevant to the selected item. */
-    private class ToolTipUpdater
-	implements ActionListener {
-	/** Any implementation of an ActionListener must include this method so that we can be informed when the selection in a combobox has changed and update the tooltip accordingly.
-	 * @param event An <strong>ActionEvent</strong> containing information about the action that fired this call.
-	 */
-	public void actionPerformed(ActionEvent event) {
-	    JComboBox source = (JComboBox)event.getSource();
-	    Object object = source.getSelectedItem();
-	    if(object instanceof Argument.ArgumentOption) {
-		Argument.ArgumentOption opt = (Argument.ArgumentOption)object;
-		if(opt != null) {
-		    source.setToolTipText(opt.getToolTip());
-		}
-		else {
-		    source.setToolTipText(StaticStrings.EMPTY_STR);
-		}
-	    }
-	}
-    }
+		/** Any implementation of an ActionListener must include this method so that we can be informed when the selection in a combobox has changed and update the tooltip accordingly.
+		 * @param event An <strong>ActionEvent</strong> containing information about the action that fired this call.
+		 */
+		public void actionPerformed(ActionEvent event) {
+			JComboBox source = (JComboBox)event.getSource();
+			Object object = source.getSelectedItem();
+			if(object instanceof Argument.ArgumentOption) {
+				Argument.ArgumentOption opt = (Argument.ArgumentOption)object;
+				if(opt != null) {
+					source.setToolTipText(opt.getToolTip());
+				}
+				else {
+					source.setToolTipText(StaticStrings.EMPTY_STR);
+				}
+			}
+		}
+	}
 }
