Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/Argument.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/Argument.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/Argument.java	(revision 18352)
@@ -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.setDisplayName(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 setDisplayName(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")) {
+				setDisplayName(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/branches/rtl-gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java	(revision 18352)
@@ -211,6 +211,9 @@
 	int current_mode = Configuration.getMode();
 
-	String previous_owner = ((Argument) arguments.get(0)).getOwner();
-	addHeader(previous_owner, colour_two);
+	String previous_owner = "";
+	if(arguments.size() > 0) {
+	    previous_owner = ((Argument) arguments.get(0)).getOwner();
+	    addHeader(previous_owner, colour_two);
+	}
 
 	for(int i = 0; i < arguments.size(); i++) {
Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/ArgumentContainer.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/ArgumentContainer.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/ArgumentContainer.java	(revision 18352)
@@ -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.setDisplayName(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/branches/rtl-gli/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java	(revision 18352)
@@ -293,5 +293,6 @@
                 value = tokenizer.nextToken ();
                 // Test if the value is actually a name, and if so add the name by itself, then put value into name so that it is parsed correctly during the next loop.
-                if(value.startsWith (StaticStrings.MINUS_CHARACTER)) {
+		// The value is not a name if it contains a space character: it's a quoted value
+                if (value.startsWith(StaticStrings.MINUS_CHARACTER) && value.indexOf(StaticStrings.SPACE_CHARACTER) == -1) {
                     arguments.put (name, null);
                     name = value;
@@ -439,11 +440,11 @@
         int option_elements_length = option_elements.getLength ();
         for(int j = 0; j < option_elements_length; j++) {
-            Element option_element = (Element) option_elements.item (j);
+	  Element option_element = (Element) option_elements.item (j);
             if(option_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-                text.append (StaticStrings.SPACE_CHARACTER);
-                text.append (StaticStrings.MINUS_CHARACTER);
-                text.append (option_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-                String value_str = XMLTools.getValue (option_element);
-                
+	      text.append (StaticStrings.SPACE_CHARACTER);
+	      text.append (StaticStrings.MINUS_CHARACTER);
+	      text.append (option_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+	      String value_str = XMLTools.getValue (option_element);
+              
                 // Convert metadata element names to internal names, and remove extracted metadata namespaces
                 if (value_str.length () > 0) {
@@ -1330,4 +1331,5 @@
                 // The next token is the type
                 String type = tokenizer.nextToken ();
+		type = ensureNewPluginName(type);
                 command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, type);
                 // Now we parse out the remaining arguments into a hashmapping from name to value
@@ -1372,4 +1374,10 @@
         }
         catch(Exception exception) {
+	    // This catch clause had been left empty.  If this is deliberate then
+	    // we should have a comment here explaining why there is no need to
+	    // print anything out.  Am assuming this is mistake for now, and
+	    // have added in a call to printStackTrace()
+	    System.err.println("Malformed plugin statement");
+	    exception.printStackTrace();
         }
         return command_element;
@@ -1420,18 +1428,20 @@
                     command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, StaticStrings.INCLUDE_STR);
                 }
-                StringTokenizer pattern_tokenizer = new StringTokenizer (full_pattern_str, StaticStrings.SEPARATOR_CHARACTER);
-                if(pattern_tokenizer.countTokens () >= 2) {
-                    String content_str = pattern_tokenizer.nextToken ();
+
+                // Let's make sure it is a valid Greenstone configuration line
+                String[] results = full_pattern_str.split("\\" + StaticStrings.SEPARATOR_CHARACTER, 3);
+
+                if (results.length >= 2) {
+                    String content_str = results[0];
                     // Since the contents of indexes have to be certain keywords, or metadata elements, if the content isn't a keyword and doesn't yet have a namespace, append the extracted metadata namespace.
-                    if(!content_str.equals (StaticStrings.FILENAME_STR) && content_str.indexOf (StaticStrings.NS_SEP) == -1) {
+                    if (!content_str.equals (StaticStrings.FILENAME_STR) && content_str.indexOf (StaticStrings.NS_SEP) == -1) {
                         content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
                     }
                     command_element.setAttribute (StaticStrings.CONTENT_ATTRIBUTE, content_str);
-                    XMLTools.setValue (command_element, pattern_tokenizer.nextToken ());
-                    if(pattern_tokenizer.hasMoreTokens ()) {
-                        command_element.setAttribute (StaticStrings.OPTIONS_ATTRIBUTE, pattern_tokenizer.nextToken ());
-                    }
-                }
-                pattern_tokenizer = null;
+                    XMLTools.setValue (command_element, results[1]);
+                    if (results.length >= 3) {
+                        command_element.setAttribute (StaticStrings.OPTIONS_ATTRIBUTE, results[2]);
+                    }
+                }
             }
         }
@@ -1521,43 +1531,68 @@
     
     static private String pluginToString (Element command_element, boolean show_extracted_namespace) {
-        StringBuffer text = new StringBuffer ();
-        if(!command_element.getAttribute (StaticStrings.SEPARATOR_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-            text.append (StaticStrings.PLUGIN_STR);
-            text.append (StaticStrings.TAB_CHARACTER);
-            text.append (StaticStrings.TAB_CHARACTER);
-            text.append (command_element.getAttribute (StaticStrings.TYPE_ATTRIBUTE));
-            // Retrieve, and output, the arguments
-            NodeList option_elements = command_element.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
-            int option_elements_length = option_elements.getLength ();
-            if(option_elements_length > 0) {
-                for(int j = 0; j < option_elements_length; j++) {
-                    Element option_element = (Element) option_elements.item (j);
-                    if(option_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-                        text.append (StaticStrings.SPACE_CHARACTER);
-                        text.append (StaticStrings.MINUS_CHARACTER);
-                        text.append (option_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-                        String value_str = XMLTools.getValue (option_element);
-                        if(!show_extracted_namespace && value_str.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
-                            value_str = value_str.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
-                        }
-                        if(value_str.length () > 0) {
-                            text.append (StaticStrings.SPACE_CHARACTER);
-                            if(value_str.indexOf (StaticStrings.SPACE_CHARACTER) == -1) {
-                                text.append (value_str);
-                            }
-                            else {
-                                text.append (StaticStrings.SPEECH_CHARACTER);
-                                text.append (value_str);
-                                text.append (StaticStrings.SPEECH_CHARACTER);
-                            }
-                        }
-                        value_str = null;
-                    }
-                    option_element = null;
-                }
-            }
-            option_elements = null;
-        }
-        return text.toString ();
+        if(command_element.getAttribute (StaticStrings.SEPARATOR_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) { 
+	  return "";
+	}
+        StringBuffer text = new StringBuffer (StaticStrings.PLUGIN_STR);
+	text.append (StaticStrings.TAB_CHARACTER);
+	text.append (command_element.getAttribute (StaticStrings.TYPE_ATTRIBUTE));
+	// Retrieve, and output, the arguments
+	NodeList option_elements = command_element.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
+	int option_elements_length = option_elements.getLength ();
+	if(option_elements_length > 0) {
+	  for(int j = 0; j < option_elements_length; j++) {
+	    Element option_element = (Element) option_elements.item (j);
+	    if(option_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
+	      text.append (StaticStrings.SPACE_CHARACTER);
+	      text.append (StaticStrings.MINUS_CHARACTER);
+	      text.append (option_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+	      String value_str = XMLTools.getValue (option_element);
+
+	      
+	      // Convert metadata element names to internal names, and remove extracted metadata namespaces
+	      if (value_str.length () > 0) {
+		StringTokenizer string_tokenizer = new StringTokenizer (value_str, ",");
+		StringBuffer value_buffer = new StringBuffer ();
+		while (string_tokenizer.hasMoreElements ()) {
+		  String raw_token = (String) string_tokenizer.nextElement ();
+		  String token = raw_token.trim ();
+		  MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName (token);
+		  if (metadata_element != null) {
+		    token = metadata_element.getFullName ();
+		  }
+                        
+		  if (token.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
+		    token = token.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
+		  }
+		  value_buffer.append (token);
+		  if (string_tokenizer.hasMoreElements ()) {
+		    value_buffer.append (",");
+		  }
+		}
+		value_str = value_buffer.toString ();
+	      }
+
+	      // if(!show_extracted_namespace && value_str.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
+	      //            value_str = value_str.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
+	      //        }
+	      if(value_str.length () > 0) {
+		text.append (StaticStrings.SPACE_CHARACTER);
+		if(value_str.indexOf (StaticStrings.SPACE_CHARACTER) == -1) {
+		  text.append (value_str);
+		}
+		else {
+		  text.append (StaticStrings.SPEECH_CHARACTER);
+		  text.append (value_str);
+		  text.append (StaticStrings.SPEECH_CHARACTER);
+		}
+	      }
+	      value_str = null;
+	    }
+	    option_element = null;
+	  }
+	}
+	option_elements = null;
+	
+	return text.toString ();
     }
     
@@ -1719,5 +1754,4 @@
             e.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
             XMLTools.setNodeText (e, text);
-            
             display_item_list.add (e);
         }
@@ -1873,5 +1907,5 @@
             Element e = (Element)index_children.item (i);
             String index_str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            String index_str_display = index_str;//for creating collectionmetadata for this index
+            String index_str_display = index_str;//for creating collectionmetadata for this index 
             
             // Handling 'index' element
@@ -2047,4 +2081,5 @@
             Element e = (Element)plugin_children.item (i);
             String str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+	    str = ensureNewPluginName(str);
             Element plugin_element = to.createElement (StaticStrings.PLUGIN_ELEMENT);
             plugin_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, str);
@@ -2197,6 +2232,6 @@
             }
             if (format != null) {
-                String gsf_text = XMLTools.xmlNodeToStringWithoutNewline(format);
-                
+                String gsf_text = XMLTools.xmlNodeToStringWithoutIndenting(format);
+               
                 if (gsf_text.startsWith("<") && (gsf_text.indexOf("<") != gsf_text.lastIndexOf("<"))) {
                     gsf_text = gsf_text.substring(gsf_text.indexOf("<gsf"),
@@ -3090,11 +3125,4 @@
             StaticStrings.NAME_ATTRIBUTE, index_value);
             
-            if (collectionmetadata_list == null) {
-                //try adding the "." prefix
-                index_value = StaticStrings.DOT_CHARACTER + index_value;
-                collectionmetadata_list = XMLTools.getNamedElementList (source,
-                StaticStrings.COLLECTIONMETADATA_ELEMENT,
-                StaticStrings.NAME_ATTRIBUTE, index_value);
-            }
             if (collectionmetadata_list != null) {
                 
@@ -3149,11 +3177,4 @@
             StaticStrings.NAME_ATTRIBUTE, name_str);
             
-            if (collectionmetadata_list == null) {
-                //try adding the "." prefix
-                name_str = StaticStrings.DOT_CHARACTER + name_str;
-                collectionmetadata_list = XMLTools.getNamedElementList (source,
-                StaticStrings.COLLECTIONMETADATA_ELEMENT,
-                StaticStrings.NAME_ATTRIBUTE, name_str);
-            }
             if (collectionmetadata_list != null) {
                 
@@ -3291,27 +3312,15 @@
             StaticStrings.NAME_ATTRIBUTE, temp_str);
             
-            if (collectionmetadata_list == null) {
-                //try adding the "." prefix
-                String with_dot_str = StaticStrings.DOT_CHARACTER + temp_str;
-                collectionmetadata_list = XMLTools.getNamedElementList (source,
-                StaticStrings.COLLECTIONMETADATA_ELEMENT,
-                StaticStrings.NAME_ATTRIBUTE, with_dot_str);
-                
-                if (collectionmetadata_list == null) {
-                    //try the full name, i.e. with 'ex.'
-                    if (mg_indexer == true) {
-                        full_index_name = level_str+StaticStrings.COLON_CHARACTER+full_index_name;
-                    }
-                    collectionmetadata_list = XMLTools.getNamedElementList (source,
-                    StaticStrings.COLLECTIONMETADATA_ELEMENT,
-                    StaticStrings.NAME_ATTRIBUTE, full_index_name);
-                }
-                if (collectionmetadata_list == null) {
-                    with_dot_str = StaticStrings.DOT_CHARACTER + full_index_name;
-                    collectionmetadata_list = XMLTools.getNamedElementList (source,
-                    StaticStrings.COLLECTIONMETADATA_ELEMENT,
-                    StaticStrings.NAME_ATTRIBUTE, with_dot_str);
-                }
-            }
+	    if (collectionmetadata_list == null) {
+	      //try the full name, i.e. with 'ex.'
+	      if (mg_indexer == true) {
+		// but first append level info if we are mg
+		full_index_name = level_str+StaticStrings.COLON_CHARACTER+full_index_name;
+	      }
+	      collectionmetadata_list = XMLTools.getNamedElementList (source,
+			     StaticStrings.COLLECTIONMETADATA_ELEMENT,
+			     StaticStrings.NAME_ATTRIBUTE, full_index_name);
+	    }
+	
             if (collectionmetadata_list != null) {
                 
@@ -3368,11 +3377,4 @@
             StaticStrings.NAME_ATTRIBUTE, name_str);
             
-            if (collectionmetadata_list == null) {
-                //try adding the "." prefix
-                name_str = StaticStrings.DOT_CHARACTER + name_str;
-                collectionmetadata_list = XMLTools.getNamedElementList (source,
-                StaticStrings.COLLECTIONMETADATA_ELEMENT,
-                StaticStrings.NAME_ATTRIBUTE, name_str);
-            }
             if (collectionmetadata_list != null) {
                 
@@ -3732,5 +3734,5 @@
         // If we're using a remote Greenstone server, upload the new 'collectionConfig.xml' file
         if (Gatherer.isGsdlRemote) {
-            RemoteGreenstoneServer.uploadCollectionFile (collection_name, collect_cfg_file);
+            Gatherer.remoteGreenstoneServer.uploadCollectionFile (collection_name, collect_cfg_file);
         }
         
@@ -3824,5 +3826,5 @@
             // If we're using a remote Greenstone server, upload the new collect.cfg file
             if (Gatherer.isGsdlRemote) {
-                RemoteGreenstoneServer.uploadCollectionFile (collection_name, collect_cfg_file);
+                Gatherer.remoteGreenstoneServer.uploadCollectionFile (collection_name, collect_cfg_file);
             }
         }
@@ -3886,4 +3888,38 @@
         return skeleton;
     }
+
+  static private HashMap plugin_map = null;
+  
+  private void setUpPluginNameMap() {
+    plugin_map = new HashMap();
+    plugin_map.put("GAPlug", "GreenstoneXMLPlugin");
+    plugin_map.put("RecPlug", "DirectoryPlugin");
+    plugin_map.put("ArcPlug","ArchivesInfPlugin");
+    plugin_map.put("TEXTPlug","TextPlugin");
+    plugin_map.put("XMLPlug","ReadXMLFile");
+    plugin_map.put("EMAILPlug","EmailPlugin");
+    plugin_map.put("SRCPlug","SourceCodePlugin");
+    plugin_map.put("NULPlug","NulPlugin");
+    plugin_map.put("W3ImgPlug","HTMLImagePlugin");
+    plugin_map.put("PagedImgPlug","PagedImagePlugin");
+    plugin_map.put("METSPlug", "GreenstoneMETSPlugin");
+    plugin_map.put("DBPlug", "DatabasePlugin");
+    plugin_map.put("PPTPlug", "PowerPointPlugin");
+    plugin_map.put("PSPlug", "PostScriptPlugin");
+  }
+
+  private String ensureNewPluginName(String plugin) {
+    if (plugin.endsWith("Plugin")) return plugin;
+    if (plugin_map == null) {
+      setUpPluginNameMap();
+    }
+    String new_name = (String)plugin_map.get(plugin);
+    if (new_name != null) return new_name;
+    new_name = plugin.replaceAll("Plug", "Plugin");
+    return new_name;
+  }
+   
+
     ///*********************************************************************************************************///
 }
+
Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java	(revision 18352)
@@ -78,4 +78,6 @@
     /** The text translation manager. */
     static public TranslationView translation_manager;
+    /** A manager of configuring depositor metadata */ 
+    static public DepositorMetadataManager depositormetadata_manager;
     /** These mark what needs to happen when building a collection where ONLY design options have been changed.
         The build requirements of the higher numbers must include doing everything from the lower numbers. */
@@ -128,4 +130,5 @@
 	supercollection_manager = new SuperCollectionManager(collect_config.getSuperCollection());
 	searchmetadata_manager = new SearchMetadataManager();
+	depositormetadata_manager = new DepositorMetadataManager();
 	translation_manager = new TranslationView();
     if (Gatherer.GS3) {
@@ -160,4 +163,6 @@
 	supercollection_manager.destroy();
 	supercollection_manager = null;
+	depositormetadata_manager.destroy();
+	depositormetadata_manager = null;
 	translation_manager.destroy();
 	translation_manager = null;
@@ -178,4 +183,5 @@
 	language_manager.modeChanged(mode);
 	searchmetadata_manager.modeChanged(mode);
+	depositormetadata_manager.modeChanged(mode);
     }
 
Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/DepositorMetadataManager.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/DepositorMetadataManager.java	(revision 18352)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/DepositorMetadataManager.java	(revision 18352)
@@ -0,0 +1,527 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.ArrayList;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataSet;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.util.Utility;
+
+/**
+ * This manager implements the "Depositor Metadata" section in GLI Format Panel, where 
+ * users can customize which metadata elements will be used to describe an item when deposited in the Depositor.
+ *      
+ * @author Anna Huang, Greenstone Digital Library, University of Waikato
+ * @version 1.0
+ */
+public class DepositorMetadataManager {
+    /** Display controls of the element */
+    static private Dimension LABEL_SIZE = new Dimension(150, 15);
+    static private Dimension ROW_SIZE = new Dimension(400, 20);
+    
+    /** Available types, corresponds to the HTML input types */ 
+    static private String[] TYPEOPTIONS = new String[]{"text", "textarea"};
+    /** Default elements to be used in Depositor */
+    static private String DEFAULT_METADATA_ELEMENTS = "dc.Title, dc.Creator, dc.Description";
+    /** Definition attribute of a metadata element */ 
+    static private String DEFINITION = "definition";
+    
+    /** Display controls */
+    private Control controls;	
+    /** List of MetadataElementEntry objects, each represents a metadata element */
+    private ArrayList metadata_checklist_model = null;	
+    /** Collection configuration file manager */ 
+    private CollectionMetaManager collmeta_manager = CollectionDesignManager.collectionmeta_manager;
+    
+    public DepositorMetadataManager() {
+    }
+    
+    /** Destructor. */
+    public void destroy() {
+	if (controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+	if(metadata_checklist_model != null) {
+	    metadata_checklist_model.clear();
+	    metadata_checklist_model = null;
+	}
+    }
+		
+    public Control getControls() {
+	if (controls == null) {
+	    controls = new DepositorControl();
+	}
+	return controls;
+    }
+	
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+    }
+	
+    /**
+     * The implementation of this display control is similar to the <code>ArgumentConfiguration</code>, 
+     * where each component in the central panel is another JPanel component consists of a checkbox and a drop down list. 
+     */
+    private class DepositorControl
+	extends JPanel
+	implements Control {		
+		
+	private JPanel central_pane = null;
+
+	public DepositorControl() {
+	    super();
+
+	    JPanel header_panel = new DesignPaneHeader("CDM.GUI.DepositorMetadata", "depositormetadatasettings");
+			
+	    // load all possible metadata sets, and existing configuration
+	    buildModel();
+	    
+	    central_pane = new JPanel();
+	    central_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    central_pane.setLayout(new BoxLayout(central_pane, BoxLayout.Y_AXIS));	
+									
+	    // build the central pane, ie. create gui component for each metadata element 
+	    buildPane();		
+
+	    JPanel collection_checklist_pane = new JPanel();
+	    collection_checklist_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    collection_checklist_pane.setLayout(new BorderLayout());
+	    collection_checklist_pane.add(new JScrollPane(central_pane), BorderLayout.CENTER);
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(header_panel, BorderLayout.NORTH);
+	    add(collection_checklist_pane, BorderLayout.CENTER);
+	}
+		
+	public void destroy() {
+	}
+
+	public void gainFocus() {
+	}
+		
+	public void loseFocus() {			
+	    StringBuffer converted_javascript = new StringBuffer();
+			
+	    // get currently selected metadata elements and create the javascript associative array variable
+	    if (metadata_checklist_model != null) {
+		int size = metadata_checklist_model.size();
+		for(int i = 0; i < size; i++) {				
+		    MetadataElementEntry entry = (MetadataElementEntry) metadata_checklist_model.get(i);
+					
+		    if (entry.isSelected()) {					
+			StringBuffer element = new StringBuffer();
+			element.append("{\"name\":\"").append(entry.name).append("\",");
+			element.append("\"label\":\"").append(entry.label).append("\",");
+			element.append("\"tooltip\":\"").append(entry.name).append(": ").append(entry.tooltip).append("\",");
+			element.append("\"type\":\"").append(entry.getType()).append("\"}");
+			if(converted_javascript.length() != 0) {
+			    converted_javascript.append(", ");
+			}
+			converted_javascript.append(element);
+			element = null;
+		    }				
+		}
+				
+		// if none of the elements were selected, use the default setting				
+		if (converted_javascript.length() == 0) {
+		    System.err.println("Error: DepositorMetadataMananger should have at least one selected metadata element.");
+		}
+
+		// save to the configuration file
+		CollectionMeta depositor_metadata_meta = collmeta_manager.getMetadatum("depositormetadata", true);
+		depositor_metadata_meta.setValue(converted_javascript.toString());			
+	    }		
+	}
+		
+	private void buildModel()
+	{
+	    metadata_checklist_model = new ArrayList();
+	    String current_coll_name = CollectionManager.getLoadedCollectionName();
+			
+	    // get the elements that have already been used in depositor
+	    // add the "depositormetadata" meta if not found in the configuration file
+	    CollectionMeta depositor_metadata_meta = collmeta_manager.getMetadatum("depositormetadata", true);			
+	    String selected_metadata_javascript = depositor_metadata_meta.getValue(true);
+			
+	    // load all MDSets in the collection, ie. .mds files in the collection's metadata directory
+	    String file_name = Gatherer.getCollectDirectoryPath() + File.separator + current_coll_name + File.separator + "metadata";
+	    ArrayList metadata_sets = MetadataSetManager.listMetadataSets(new File(file_name));
+	    
+	    // if the collection doesn't have a metadata directory, load all the MDSets in the global GLI/metadata directory 
+	    if (metadata_sets == null) {
+		file_name = org.greenstone.gatherer.gems.MetadataSetManager.getGLIMetadataDirectoryPath();
+		metadata_sets = MetadataSetManager.listMetadataSets(new File(file_name));
+	    } 
+			
+	    // always load the dc mds
+	    boolean found = false;
+	    for (int i = 0, j = metadata_sets.size(); i < j; i++) {
+		if (((MetadataSet) metadata_sets.get(i)).getNamespace().equals("dc")) {
+		    found = true;
+		    break;
+		}					
+	    }
+	    if (found == false) {
+		file_name = org.greenstone.gatherer.gems.MetadataSetManager.getGLIMetadataDirectoryPath();
+		file_name += "dublin.mds";
+		File dublin_mds_file = new File(file_name);
+		if (dublin_mds_file.exists()) {
+		    MetadataSetManager.loadMetadataSet(dublin_mds_file);					
+		    metadata_sets = MetadataSetManager.getMetadataSets();
+		}
+	    }			
+
+	    // unload the ex mds
+	    for (int i = 0, j = metadata_sets.size(); i < j; i++) {
+		if (((MetadataSet) metadata_sets.get(i)).getNamespace().equals("ex")) {
+		    metadata_sets.remove(i);
+		    break;
+		}
+	    }
+			
+	    if (metadata_sets == null) {
+		System.err.println("Error: DepositorMetadataMananger can't find any valid metadata set files.");
+		return;
+	    }			
+			
+	    // load all the metadata elements
+	    for (int i = 0, j = metadata_sets.size(); i < j; i++) {
+		MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i);				
+		ArrayList elements = metadata_set.getMetadataSetElements(); 
+		
+		for (int k = 0; elements != null && k < elements.size(); k++) {
+		    MetadataElement element = (MetadataElement) elements.get(k);
+		    // all names are language independent at the moment. 
+		    MetadataElementEntry entry = new MetadataElementEntry (element.getFullName(), element.getName(), false);
+		    entry.setToolTip(element.getAttribute(DEFINITION, "en"));
+		    metadata_checklist_model.add(entry);
+		}
+	    }	
+	    
+	    if (!selected_metadata_javascript.equals("")) {
+		for (int i = 0, j = metadata_checklist_model.size(); i < j; i++) {
+		    MetadataElementEntry entry = (MetadataElementEntry) metadata_checklist_model.get(i);
+		    
+		    String temp = "\"name\":\"" + entry.name + "\"";
+		    if (selected_metadata_javascript.indexOf(temp) != -1) {
+			entry.setSelected(true);
+			entry.type = getValueFromJSAssociatedArray(selected_metadata_javascript, entry.name, "type");						
+		    }
+		    temp = null;
+		}	
+	    } else {				
+		// use default elements				
+		for (int i = 0, j = metadata_checklist_model.size(); i < j; i++) {
+		    MetadataElementEntry entry = (MetadataElementEntry) metadata_checklist_model.get(i);
+		    if (DEFAULT_METADATA_ELEMENTS.indexOf(entry.name) != -1) {
+			entry.setSelected(true);
+			entry.type = TYPEOPTIONS[0];
+		    }
+		}
+	    }					
+	}	
+	
+	private void buildPane() {
+	    // use different background color for two adjacent metadata sets
+	    String current_namespace = null;
+	    String current_bgcolor_name = null;
+	    for (int i = 0, j = metadata_checklist_model.size(); i < j; i++) {
+		MetadataElementEntry entry = (MetadataElementEntry) metadata_checklist_model.get(i);
+		
+		if (current_namespace == null) {
+		    current_namespace = entry.namespace;
+		    current_bgcolor_name = "coloring.collection_tree_background";
+		} else {
+		    if (!entry.namespace.equals(current_namespace)) {
+			current_namespace = entry.namespace;
+			current_bgcolor_name = (current_bgcolor_name == "coloring.collection_tree_background") ? "coloring.collection_heading_background" : "coloring.collection_tree_background";
+		    }
+		}			
+		
+		if (entry.getGUIControl() == null) {
+		    MetadataElementControl element_control = entry.initGUIControl(current_bgcolor_name);					
+		    central_pane.add(element_control, BorderLayout.NORTH);
+		}				
+	    }
+	    
+	}
+		
+	/**
+	 * Retrieve the value for the specified element in the given javascript associative array expression
+	 *  
+	 * @param text
+	 * @param identifier
+	 * @param elem_name
+	 * @return
+	 */
+	private String getValueFromJSAssociatedArray(String text, String identifier, String elem_name) {
+	    int p = text.indexOf(elem_name, text.indexOf(identifier));
+	    if (p == -1) {
+		return null;
+	    }
+	    p = text.indexOf("\":\"", p);
+	    if (p == -1) {
+		return null;
+	    }
+	    p += 3;
+			
+	    return text.substring(p, text.indexOf("\"", p));			
+	}
+    }
+	
+    private class MetadataElementControl extends JPanel {
+	
+	private JCheckBox enabled = null;
+	private JComponent value_control = null;		
+		
+	public MetadataElementControl (MetadataElementEntry entry, String background_color_name) {
+						
+	    String tip = "<html>" + entry.tooltip + "</html>";
+	    tip = Utility.formatHTMLWidth(tip, 80);
+	    
+	    setBackground(Configuration.getColor(background_color_name, false));
+	    setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
+	    setLayout(new BorderLayout());
+	    setPreferredSize(ROW_SIZE);
+			
+	    // the checkbox component
+	    enabled = new JCheckBox(entry.name);
+	    enabled.setSelected(entry.selected);
+	    enabled.setOpaque(false);
+	    enabled.setPreferredSize(LABEL_SIZE);
+	    enabled.setToolTipText(entry.tooltip);
+	    add(enabled, BorderLayout.WEST);
+			
+	    // the drop down list component
+	    ArrayList option_list = new ArrayList();
+	    for (int i = 0; i < TYPEOPTIONS.length; i++) {
+		option_list.add(TYPEOPTIONS[i]);
+	    }
+	    value_control = new GComboBox(option_list.toArray(), false, false);
+	    selectValue((JComboBox)value_control, entry.type); 
+	    value_control.setOpaque(true);			
+	    if (entry.selected) { 
+		value_control.setBackground(Color.white);
+		value_control.setEnabled(true);
+	    } else {
+		value_control.setBackground(Color.lightGray);
+		value_control.setEnabled(false);
+		value_control.setVisible(false);
+	    }							
+	    add(value_control, BorderLayout.CENTER);
+	    
+	    enabled.addActionListener(new EnabledListener(value_control));
+	}
+				
+	private boolean selectValue(JComboBox combobox, String target) {
+	    if (target == null) {
+		combobox.setSelectedIndex(0);
+		return false;
+	    }
+			
+	    for (int i = 0; i < combobox.getItemCount(); i++) {				
+		if (combobox.getItemAt(i).toString().equals(target)) {
+		    combobox.setSelectedIndex(i);
+		    return true;
+		}
+	    }
+	    return false;
+	}
+		
+	private class EnabledListener
+	    implements ActionListener {			
+	    private JComponent target = null;
+	    
+	    public EnabledListener(JComponent target) {
+		this.target = target;
+	    }
+	    
+	    public void actionPerformed(ActionEvent event) {
+		JCheckBox source = (JCheckBox)event.getSource();
+		
+		// check at least one of the elements should be ticked
+		checkTickedElements(source);
+				
+		// update the status of the drop-down list component associated with the current checkbox 
+		if (this.target == null) {
+		    return;
+		}				
+				
+		if(source.isSelected()) {
+		    target.setBackground(Color.white);
+		    target.setEnabled(true);
+		    target.setVisible(true);
+		}
+		else {
+		    target.setBackground(Color.lightGray);
+		    target.setEnabled(false);
+		    target.setVisible(false);
+		}				
+	    }
+			
+	    private void checkTickedElements(JCheckBox source) {
+		if (source.isSelected()) {
+		    return;
+		}
+				
+		boolean b = false;
+		for (int i = 0, j = metadata_checklist_model.size(); i < j; i++) {
+		    if (((MetadataElementEntry) metadata_checklist_model.get(i)).gui_object.enabled.isSelected()) {
+			b = true;
+			break;
+		    }
+		}
+				
+		// there must be at least one element selected in the list 
+		if (b == false) {
+		    Object[] options = {Dictionary.get("General.OK")};
+		    JOptionPane.showOptionDialog(Gatherer.g_man, Dictionary.get("CDM.DepositorMetadataManager.Warning"), Dictionary.get("General.Warning"), JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]);
+		    
+		    source.setSelected(true);
+		}
+	    }
+	}
+	
+    }
+	
+    private class MetadataElementEntry implements Comparable {
+	/** namespace, used to distinguish different metadata sets and use different colors when displaying */
+	String namespace = null;
+	/** identifier, with namespace */
+	String name = null;
+	/** language independent label, without namespace, used for display in the depositor web page, eg. Title */
+	String label = null;	
+	/** type of the element: text or textarea */
+	String type = null;
+	/** description of the element, used in web page */
+	String tooltip = null;		
+	/** whether current element is selected or not */
+	boolean selected ;
+	/** GUI component object associated with this element */ 
+	MetadataElementControl gui_object = null;
+		
+	/**
+	 * Constructor
+	 * @param name Language independent identifier of the element with namespace, eg. dc.Title
+	 * @param label Language independent label of the element, without namespace, eg. Title 
+	 * @param selected Whether the current element has been selected as depositor metadata element 
+	 */
+	public MetadataElementEntry(String name, String label, boolean selected) {
+	    this.name = name;
+	    this.label = label;
+	    this.selected = selected;
+	    
+	    if (name.indexOf(".") != -1) {
+		namespace = name.substring(0, name.indexOf("."));
+	    }
+	}
+		
+	/**
+	 * Initiate the <code>MetadataElementControl<code> GUI component object associated with this element, with the specified background color  
+	 * @param background_color_name System configured color name for the background, eg. "coloring.collection_heading_background", or "coloring.collection_tree_background"
+	 * @return the initialized component object
+	 */
+	public MetadataElementControl initGUIControl (String background_color_name) {
+	    gui_object = new MetadataElementControl(this, background_color_name);
+	    return gui_object;
+	}
+	
+	/**
+	 * Get the associated GUI component
+	 * @return
+	 */
+	public MetadataElementControl getGUIControl() {
+	    return gui_object;
+	}
+		
+	/**
+	 * Set selected
+	 * @param b
+	 */
+	public void setSelected(boolean b) {
+	    this.selected = b;
+	}
+		
+	public boolean isSelected() {
+	    return gui_object.enabled.isSelected();
+	}
+		
+	/**
+	 * Get the selected type for the element
+	 * @return type
+	 */
+	public String getType() {
+	    return ((JComboBox) gui_object.value_control).getSelectedItem().toString();
+	}
+		
+	public void setToolTip (String tip) {
+	    if (tip == null) {
+		tooltip = "";
+		return;
+	    }
+	    this.tooltip = tip;
+	}
+
+	public int compareTo(Object obj) {
+	    return compareTo((MetadataElementEntry) obj);
+	}
+		
+	public int compareTo(MetadataElementEntry obj) {
+	    return this.name.compareTo(obj.name);
+	}
+	
+    }
+    
+}
Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/Format.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/Format.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/Format.java	(revision 18352)
@@ -42,5 +42,5 @@
 
     /** The default features (not all of these are in the Greenstone Developer's Guide). */
-    static final public String DEFAULT_FEATURES[] = { "", "AllowExtendedOptions", "Document", "DocumentArrowsBottom", "DocumentArrowsTop","DocumentSearchResultLinks", "DocumentButtons", "DocumentContents", "DocumentHeading", "DocumentImages", "DocumentText", "DocumentTitles", "DocumentUseHTML", "RelatedDocuments", "Search", "SearchTypes" };
+    static final public String DEFAULT_FEATURES[] = { "", "AllowExtendedOptions", "Document", "DocumentArrowsBottom", "DocumentArrowsTop","DocumentSearchResultLinks", "DocumentButtons", "DocumentContents", "DocumentHeading", "DocumentImages", "DocumentText", "DocumentTitles", "DocumentUseHTML", "NavigationBar", "RelatedDocuments", "Search", "SearchTypes" };
     /** The list of known feature parts. */
     static final public String DEFAULT_PARTS[] = { "", "DateList", "HList", "VList" };
Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/FormatManager.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/FormatManager.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/FormatManager.java	(revision 18352)
@@ -77,4 +77,7 @@
   static final private String SEARCHTYPES_DEFAULT_FORMAT = "plain,form";
   
+  static final private String NAVBAR = "NavigationBar";
+  static final private String NAVBAR_OPTION = "pulldown";
+
   static private HashMap default_format_map = null;
   
@@ -98,4 +101,5 @@
     default_format_map.put(DOCUMENTBUTTONS, DOCUMENTBUTTONS_DEFAULT_FORMAT);
     default_format_map.put(SEARCHTYPES, SEARCHTYPES_DEFAULT_FORMAT);
+    default_format_map.put(NAVBAR, NAVBAR_OPTION);
     default_format_map.put("", "");
     
Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/GeneralManager.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/GeneralManager.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/GeneralManager.java	(revision 18352)
@@ -299,8 +299,4 @@
 	    String creator_email_str = creator_emailfield.getText();
 	    creator_collectionmeta.setValue(creator_email_str);
-		// If the email is currently empty, store this email
-	    if(Configuration.getEmail() == null) {
-		Configuration.setEmail(creator_email_str); // Store the email address in the configuration
-	    }
 	    collection_extra_collectionmeta.setValue(description_textarea.getText());
 	    icon_collection_collectionmeta.setValue(icon_textfield.getText());
@@ -348,5 +344,6 @@
 			    // If we're using a remote Greenstone server, upload the image
 			    if (Gatherer.isGsdlRemote) {
-				RemoteGreenstoneServer.uploadCollectionFile(CollectionManager.getLoadedCollectionName(), collection_image_file);
+				Gatherer.remoteGreenstoneServer.uploadCollectionFile(
+                                   CollectionManager.getLoadedCollectionName(), collection_image_file);
 			    }
 			}
Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/IndexOptionManager.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/IndexOptionManager.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/IndexOptionManager.java	(revision 18352)
@@ -190,5 +190,6 @@
 	private JCheckBox casefold_checkbox = new JCheckBox();
 	private JCheckBox accentfold_checkbox = new JCheckBox();
-
+	private JCheckBox separate_cjk_checkbox =new JCheckBox();
+	
 	public StemmingControl()
 	{
@@ -197,20 +198,37 @@
 	    
 	    stem_checkbox.setText(Dictionary.get("CDM.IndexingManager.Stem"));
+	    stem_checkbox.setToolTipText(Dictionary.get("CDM.IndexingManager.Stem_Tooltip"));
 	    stem_checkbox.setActionCommand(StaticStrings.STEM_OPTION_STR);
 	    
 	    casefold_checkbox.setText(Dictionary.get("CDM.IndexingManager.Casefold"));
+	    casefold_checkbox.setToolTipText(Dictionary.get("CDM.IndexingManager.Casefold_Tooltip"));
 	    casefold_checkbox.setActionCommand(StaticStrings.CASEFOLD_OPTION_STR);
 	    
 	    accentfold_checkbox.setText(Dictionary.get("CDM.IndexingManager.Accent_fold"));
+	    accentfold_checkbox.setToolTipText(Dictionary.get("CDM.IndexingManager.Accent_fold_Tooltip"));
 	    accentfold_checkbox.setActionCommand(StaticStrings.ACCENTFOLD_OPTION_STR);
 	    // Accent-folding is currently not available for MG
 	    accentfold_checkbox.setEnabled(!build_type.equals(BuildTypeManager.BUILD_TYPE_MG));
-	    
+	
+	    separate_cjk_checkbox.setText(Dictionary.get("CDM.IndexingManager.Separate_cjk"));
+	    separate_cjk_checkbox.setToolTipText(Dictionary.get("CDM.IndexingManager.Separate_cjk_Tooltip"));
+	    separate_cjk_checkbox.setActionCommand(StaticStrings.SEPARATE_CJK_OPTION_STR);
+
 	    JPanel checkbox_panel = new JPanel();
-	    checkbox_panel.setLayout(new GridLayout(1, 3));
-	    checkbox_panel.add(stem_checkbox);
-	    checkbox_panel.add(casefold_checkbox);
-	    checkbox_panel.add(accentfold_checkbox);
-	    
+	    checkbox_panel.setLayout(new GridLayout(2, 1));
+	    
+	    JPanel stem_panel = new JPanel();
+	    stem_panel.setLayout(new GridLayout(1,3));
+	    stem_panel.add(stem_checkbox);
+	    stem_panel.add(casefold_checkbox);
+	    stem_panel.add(accentfold_checkbox);
+	    
+	    JPanel other_panel = new JPanel();
+	    other_panel.setLayout(new GridLayout(1,1));
+	    other_panel.add(separate_cjk_checkbox);
+
+	    checkbox_panel.add(stem_panel);
+	    checkbox_panel.add(other_panel);
+
 	    add(new JLabel(Dictionary.get("CDM.IndexingManager.Options")), BorderLayout.WEST);
 	    add(checkbox_panel, BorderLayout.CENTER);
@@ -227,4 +245,5 @@
 		    stem_model.addOption(StaticStrings.ACCENTFOLD_OPTION_STR);
 		}
+		separate_cjk_checkbox.setSelected(false);
 	    } 
 	    else {
@@ -238,4 +257,8 @@
 		    accentfold_checkbox.setSelected(true);
 		}
+		if (stem_model.getOption(StaticStrings.SEPARATE_CJK_OPTION_STR) != null) {
+		    separate_cjk_checkbox.setSelected(true);
+		}
+		
 		
 	    }
@@ -245,10 +268,11 @@
 	    casefold_checkbox.addActionListener(cbl);
  	    accentfold_checkbox.addActionListener(cbl);
-
+	    separate_cjk_checkbox.addActionListener(cbl);
+	    
 	    // changing stem indexes changes build settings
 	    stem_checkbox.addActionListener(CollectionDesignManager.buildcol_change_listener);
 	    casefold_checkbox.addActionListener(CollectionDesignManager.buildcol_change_listener);
  	    accentfold_checkbox.addActionListener(CollectionDesignManager.buildcol_change_listener);
-
+	    separate_cjk_checkbox.addActionListener(CollectionDesignManager.buildcol_change_listener);
 	    
 	}
@@ -258,4 +282,5 @@
 	    if (new_build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
 		//changing to MG
+		accentfold_checkbox.setSelected(false);
 		accentfold_checkbox.setEnabled(false);
 		if (accentfold_checkbox.isSelected()) {
@@ -307,4 +332,5 @@
 	    document_checkbox = new JCheckBox();
 	    document_checkbox.setText(Dictionary.get("CDM.LevelManager.Document"));
+	    document_checkbox.setActionCommand(StaticStrings.DOCUMENT_STR);
 	    document_default_radio = new JRadioButton();
 	    document_default_radio.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
@@ -316,4 +342,5 @@
 	    section_checkbox = new JCheckBox();
 	    section_checkbox.setText(Dictionary.get("CDM.LevelManager.Section"));
+	    section_checkbox.setActionCommand(StaticStrings.SECTION_STR);
 	    section_default_radio = new JRadioButton();
 	    section_default_radio.setOpaque(true);
Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/MacrosManager.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/MacrosManager.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/MacrosManager.java	(revision 18352)
@@ -217,5 +217,5 @@
 		// Users need to wait until the upload has finished before pressing Preview Collection!
 		if (Gatherer.isGsdlRemote) {
-		    RemoteGreenstoneServer.uploadCollectionFile(CollectionManager.getLoadedCollectionName(), extra_dm_file);
+		    Gatherer.remoteGreenstoneServer.uploadCollectionFile(CollectionManager.getLoadedCollectionName(), extra_dm_file);
 		}
 	    }
Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/Plugin.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/Plugin.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/Plugin.java	(revision 18352)
@@ -42,7 +42,9 @@
     private String default_process_expression = "";
     private boolean does_explode_metadata_databases = false; 
-    private boolean loading_options_failed = false;
-
-    
+    private boolean does_replace_srcdocs_with_html = false; // to work with replace_srcdoc_with_html.pl
+    /** Plugins are loaded as needed. This variable indicates 1. whether a plugin has been loaded already; 2. whether a 
+     * plugin has been successfully loaded. When both are true, has_loaded_options will be true. */
+    private boolean has_loaded_options = false;
+
     /** Constructor used in DOMProxyListModel initializations, and Library Level. Used for Base plugins (those in the list of available plugins, not ones that are in the DOMProxyList)
      */
@@ -84,7 +86,7 @@
 
 
-    public boolean didLoadingOptionsFail()
-    {
-	return loading_options_failed;
+    public boolean hasLoadedOptions()
+    {
+	return has_loaded_options;
     }
 
@@ -100,4 +102,15 @@
     }
 
+    /** Checks whether the plugin this instance is based on processes source documents that can be replaced with their Greenstone generated html variants. 
+     * This method works with replace_srcdoc_with_html.pl */
+    public boolean doesReplaceSrcDocsWithHtml()
+    {
+	//return does_replace_srcdocs_with_html;
+	Plugin base_plugin = Plugins.getPlugin(getName(), false);
+	if (base_plugin == null) {
+	  return false;
+	}
+	return base_plugin.does_replace_srcdocs_with_html;
+    }
 
     /** Checks whether this plugin instance will process the specified file (given its block_exp). */
@@ -211,8 +224,13 @@
     }
 
-
-    public void setLoadingOptionsFailed()
-    {
-	this.loading_options_failed = true;
+    // To work with replace_srcdoc_with_html.pl
+    public void setDoesReplaceSrcDocsWithHtml(boolean does_replace_srcdocs_with_html)
+    {
+	this.does_replace_srcdocs_with_html = does_replace_srcdocs_with_html;
+    }
+
+    public void setHasLoadedOptions(boolean hasLoadedOptions)
+    {
+	this.has_loaded_options = hasLoadedOptions;
     }
 }
Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/PluginManager.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/PluginManager.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/PluginManager.java	(revision 18352)
@@ -70,4 +70,7 @@
     private JPanel separator;
     private Plugin separator_plugin;
+
+  /** The number of plugins that are fixed 'below the line' */
+  private static int NUM_FIXED_PLUGINS = 3; 
     /** Constructor.
      */
@@ -93,5 +96,5 @@
     private void ensureMetadataXMLPlugIsLoaded() {
 
-	Plugin metaxmlplug = Plugins.getPlugin("MetadataXMLPlug", false);
+	Plugin metaxmlplug = Plugins.getPlugin(StaticStrings.METADATAXMLPLUG_STR, false);
 	if (metaxmlplug!= null) {
 	    if (!contains(metaxmlplug)) {
@@ -117,6 +120,6 @@
 	    if (!plugin.isAbstract()) {
 		String plugin_name = plugin.getName();
-		if (!plugin_name.equals(StaticStrings.ARCPLUG_STR) && !plugin_name.equals(StaticStrings.RECPLUG_STR)) {
-		    available.add(plugin);
+		if (!plugin_name.equals(StaticStrings.ARCPLUG_STR) && !plugin_name.equals(StaticStrings.RECPLUG_STR) && !plugin_name.equals(StaticStrings.METADATAXMLPLUG_STR)) {
+		  available.add(plugin);
 		}
 	    }
@@ -148,5 +151,4 @@
 	return exploder_plugins;	
     }
-
     
     public boolean isFileExplodable(File file)
@@ -163,4 +165,33 @@
     }
 
+    // Works with replace_srcdoc_with_html.pl
+    public ArrayList getSrcReplacerPlugins(File file)
+    {
+	ArrayList srcreplacer_plugins = new ArrayList();
+	ArrayList plugins_list = Plugins.getPluginsList();
+	for (int i = 0; i < plugins_list.size(); i++) {
+	    Plugin plugin = (Plugin) plugins_list.get(i);
+	    if (plugin.doesReplaceSrcDocsWithHtml() == true && plugin.doesProcessFile(file)) {
+		srcreplacer_plugins.add(plugin);
+	    }
+	}
+
+	return srcreplacer_plugins;	
+    }	
+
+    // Works with replace_srcdoc_with_html.pl
+    public boolean isFileSrcReplaceable(File file)
+    {
+	ArrayList plugins_list = Plugins.getPluginsList();
+	for (int i = 0; i < plugins_list.size(); i++) {
+	    Plugin plugin = (Plugin) plugins_list.get(i);
+	   
+	    if (plugin.doesReplaceSrcDocsWithHtml() == true && plugin.doesProcessFile(file) == true) { 
+		return true;
+	    }
+	}
+
+	return false;
+    }	
 
     /** Method to assign a plugin
@@ -168,5 +199,5 @@
      */
     private void assignPlugin(Plugin plugin) {
-	if(plugin.getName().equals(StaticStrings.RECPLUG_STR) || plugin.getName().equals(StaticStrings.ARCPLUG_STR)) {
+      if(plugin.getName().equals(StaticStrings.RECPLUG_STR) || plugin.getName().equals(StaticStrings.ARCPLUG_STR) || plugin.getName().equals(StaticStrings.METADATAXMLPLUG_STR)) {
 	    addAfter(plugin, separator_plugin); // Adds after separator
 	} else {
@@ -245,5 +276,5 @@
 	int result = super.getSize();
 	if(modify_row_count) {
-	    result = result-3;
+	  result = result-(NUM_FIXED_PLUGINS+1);
 	}
 	return result;
@@ -267,9 +298,9 @@
     private void movePlugin(Plugin plugin, boolean direction, boolean all) {
 	// Can't ever move RecPlug or ArcPlug
-	if(super.getSize() < 4) {
+      if(super.getSize() < (NUM_FIXED_PLUGINS+2)) {
 	    //DebugStream.println("Not enough plugins to allow moving.");
 	    return;
 	}
-	if(plugin.getName().equals(StaticStrings.ARCPLUG_STR) || plugin.getName().equals(StaticStrings.RECPLUG_STR)) {
+	if(plugin.getName().equals(StaticStrings.ARCPLUG_STR) || plugin.getName().equals(StaticStrings.RECPLUG_STR) || plugin.getName().equals(StaticStrings.METADATAXMLPLUG_STR)) {
 	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.Fixed"), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
 	    return;
@@ -336,5 +367,5 @@
 		Plugin plugin = (Plugin) getElementAt(index);
 		String name = plugin.getName();
-		if(name.equals(StaticStrings.RECPLUG_STR) || name.equals(StaticStrings.ARCPLUG_STR)) {
+		if(name.equals(StaticStrings.RECPLUG_STR) || name.equals(StaticStrings.ARCPLUG_STR) || name.equals(StaticStrings.METADATAXMLPLUG_STR)) {
 		    found_fixed = true;
 		    index--;
@@ -370,6 +401,6 @@
 
 
-    /** Inform the model to hide/show the last three lines on the list.
-     * @param modify_row_count true to hide the last three lines, false otherwise
+    /** Inform the model to hide/show the last four lines on the list.
+     * @param modify_row_count true to hide the last four lines, false otherwise
      */
     private void setHideLines(boolean modify_row_count) {
@@ -377,8 +408,8 @@
 	int original_size = super.getSize();
 	if(modify_row_count) {
-	    fireIntervalRemoved(this, original_size - 4, original_size - 1);
+	  fireIntervalRemoved(this, original_size - (NUM_FIXED_PLUGINS+2), original_size - 1);
 	}
 	else {
-	    fireIntervalAdded(this, original_size - 4, original_size - 1);
+	  fireIntervalAdded(this, original_size - (NUM_FIXED_PLUGINS+2), original_size - 1);
 	}
     }
@@ -696,14 +727,12 @@
             String plugin_name = selected_plugin.getName();
             // Some buttons are only available for plugins other than ArcPlug and RecPlug
-            if(plugin_name.equals(StaticStrings.ARCPLUG_STR) || plugin_name.equals(StaticStrings.RECPLUG_STR) ) {
+            if(plugin_name.equals(StaticStrings.ARCPLUG_STR) || plugin_name.equals(StaticStrings.RECPLUG_STR) || plugin_name.equals(StaticStrings.METADATAXMLPLUG_STR)) {
               move_up_button.setEnabled(false);
               move_down_button.setEnabled(false);
               remove.setEnabled(false);
-            } else if (plugin_name.equals(StaticStrings.METADATAXMLPLUG_STR)) {
-              remove.setEnabled(false);
-            }
+            } 
             
             else {
-              // don't let people remove special plugins such GAPlug an METSPlug,
+              // don't let people remove special plugins such GreenstoneXMLPlug and GreenstoneMETSPlug,
               // unless they are in systems mode or above
               int mode = Configuration.getMode();
Index: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/SearchMetadataManager.java
===================================================================
--- gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/SearchMetadataManager.java	(revision 18351)
+++ gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/SearchMetadataManager.java	(revision 18352)
@@ -33,4 +33,5 @@
 import org.greenstone.gatherer.Configuration;
 import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
 import org.greenstone.gatherer.gui.DesignPaneHeader;
 import org.greenstone.gatherer.util.StaticStrings;
@@ -182,5 +183,10 @@
 	
 	public String getMetaID() {
-	    return StaticStrings.STOP_CHARACTER+id;
+	  if (Gatherer.GS3) {
+	    // we don't use any dots in gs3
+	    return id;
+	  }
+	  return StaticStrings.STOP_CHARACTER+id;
+	  
 	}
 	public String getValue() {
