Index: /gli/trunk/src/org/greenstone/gatherer/cdm/CollectCfgReadWrite.java
===================================================================
--- /gli/trunk/src/org/greenstone/gatherer/cdm/CollectCfgReadWrite.java	(revision 20447)
+++ /gli/trunk/src/org/greenstone/gatherer/cdm/CollectCfgReadWrite.java	(revision 20447)
@@ -0,0 +1,1422 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *
+ * Methods to read collect.cfg files into internal XML form, and write 
+ * them back out again.
+ *
+ * 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.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataTools;
+import org.greenstone.gatherer.util.Codec;
+import org.greenstone.gatherer.util.XMLTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+import org.w3c.dom.*;
+
+public class CollectCfgReadWrite {
+
+  
+  static public String toString (Element command_element) {
+    String command_element_name = command_element.getNodeName ();
+    if(command_element_name.equals (StaticStrings.CLASSIFY_ELEMENT)) {
+      return classifyToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.FORMAT_ELEMENT)) {
+      return formatToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.INDEXES_ELEMENT)) {
+      return indexesToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.INDEX_DEFAULT_ELEMENT)) {
+      return indexDefaultToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.LANGUAGES_ELEMENT)) {
+      return languagesToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.LANGUAGE_DEFAULT_ELEMENT)) {
+      return languageDefaultToString (command_element);
+    }
+    else if (command_element_name.equals (StaticStrings.LANGUAGE_METADATA_ELEMENT)) {
+      return languageMetadataToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.INDEXOPTIONS_ELEMENT)) {
+      return indexOptionsToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT)) {
+      return indexOptionDefaultToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
+      return metadataToString (command_element); 
+    }
+    else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT)) {
+      return metadataToString (command_element); 
+    }
+    else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT)) {
+      return metadataToString (command_element); 
+    }
+    else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT)) {
+      return metadataToString (command_element); 
+    }
+    else if (command_element_name.equals (StaticStrings.BUILDTYPE_ELEMENT)) {
+      return metadataToString (command_element); 
+    }
+    else if(command_element_name.equals (StaticStrings.PLUGIN_ELEMENT)) {
+      return pluginToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.SUBCOLLECTION_ELEMENT)) {
+      return subcollectionToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT)) {
+      return subcollectionDefaultIndexToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT)) {
+      return subcollectionIndexesToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.SUPERCOLLECTION_ELEMENT)) {
+      return supercollectionToString (command_element);
+    }
+    else if(command_element_name.equals (StaticStrings.UNKNOWN_ELEMENT)) {
+      return unknownToString (command_element);
+    }
+    return "";
+  }
+
+  static private String classifyToString (Element command_element) {
+    StringBuffer text = new StringBuffer (StaticStrings.CLASSIFY_STR);
+    text.append (StaticStrings.TAB_CHARACTER);
+    text.append (command_element.getAttribute (StaticStrings.TYPE_ATTRIBUTE));
+    NodeList option_elements = command_element.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
+    int option_elements_length = option_elements.getLength ();
+    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);
+	
+	//	      value_str = modifyMetadataArgumentValue(value_str);
+	if (value_str.length () > 0) {
+	  text.append (StaticStrings.SPACE_CHARACTER);
+	  if(value_str.indexOf (StaticStrings.SPACE_CHARACTER) != -1) {
+	    // enclose in quotes
+	    text.append(StaticStrings.SPEECH_CHARACTER);
+	    text.append(value_str);
+	    text.append(StaticStrings.SPEECH_CHARACTER);
+	  } else {
+		    
+	    text.append(value_str);
+	  }
+	}
+              
+	value_str = null;
+      }
+      option_element = null;
+    }
+    option_elements = null;
+    return text.toString ();
+  }
+    
+  static private String formatToString (Element command_element) {
+    StringBuffer text = new StringBuffer (StaticStrings.FORMAT_STR);
+    text.append (StaticStrings.SPACE_CHARACTER);
+    text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+    text.append (StaticStrings.SPACE_CHARACTER);
+    String value_str = command_element.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
+    if(value_str.length () != 0) {
+      text.append (value_str);
+    }
+    else {
+      // Remember to encode format string to Greenstone specification
+      value_str = Codec.transform (XMLTools.getValue (command_element), Codec.DOM_TO_GREENSTONE);
+      text.append (StaticStrings.SPEECH_CHARACTER);
+      text.append (value_str);
+      text.append (StaticStrings.SPEECH_CHARACTER);
+    }
+    value_str = null;
+    return text.toString ();
+  }
+  
+  static private String indexesToString (Element command_element) {
+    boolean comment_only = false;
+    StringBuffer text = new StringBuffer ("");
+    if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+      text.append ("#");
+      comment_only = true;
+    }
+    text.append (StaticStrings.INDEX_STR);
+    text.append (StaticStrings.TAB_CHARACTER);
+    if(!comment_only) {
+      text.append (StaticStrings.TAB_CHARACTER);
+    }
+    NodeList index_elements = command_element.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
+    if (index_elements.getLength () == 0) { // no indexes
+      return "";
+    }
+    // For each index, write its level, a colon, then concatenate its child content elements into a single comma separated list
+    int index_elements_length = index_elements.getLength ();
+    for(int j = 0; j < index_elements_length; j++) {
+      Element index_element = (Element) index_elements.item (j);
+      String level_str = index_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE);
+      if(level_str.length () > 0) {
+	text.append (level_str);
+	text.append (StaticStrings.COLON_CHARACTER);
+      }
+      NodeList content_elements = index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
+      int content_elements_length = content_elements.getLength ();
+      // Don't output anything if no indexes are set
+      if(content_elements_length == 0) {
+	return null;
+      }
+      for(int k = 0; k < content_elements_length; k++) {
+	Element content_element = (Element) content_elements.item (k);
+	String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+	text.append (name_str);
+	name_str = null;
+	if(k < content_elements_length - 1) {
+	  text.append (StaticStrings.COMMA_CHARACTER);
+	}
+	content_element = null;
+      }
+      if(j < index_elements_length - 1) {
+	text.append (StaticStrings.SPACE_CHARACTER);
+      }
+      content_elements = null;
+      index_element = null;
+    }
+    index_elements = null;
+    return text.toString ();
+  }
+    
+  static private String indexDefaultToString (Element command_element) {
+    StringBuffer text = new StringBuffer ("");
+    if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+      text.append ("#");
+    }
+    text.append (StaticStrings.INDEX_DEFAULT_STR);
+    text.append (StaticStrings.TAB_CHARACTER);
+    if (!command_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE).equals ("")) {
+      text.append (command_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE));
+      text.append (StaticStrings.COLON_CHARACTER);
+    }
+    NodeList content_elements = command_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
+    int content_elements_length = content_elements.getLength ();
+    for(int j = 0; j < content_elements_length; j++) {
+      Element content_element = (Element) content_elements.item (j);
+      String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      text.append (name_str);
+      name_str = null;
+      if(j < content_elements_length - 1) {
+	text.append (StaticStrings.COMMA_CHARACTER);
+      }
+      content_element = null;
+    }
+    content_elements = null;
+    return text.toString ();
+  }
+    
+  static private String languagesToString (Element command_element) {
+    StringBuffer text = new StringBuffer (StaticStrings.LANGUAGES_STR);
+    text.append (StaticStrings.TAB_CHARACTER);
+    // Retrieve all the languages and write them out in a space separated list
+    NodeList language_elements = command_element.getElementsByTagName (StaticStrings.LANGUAGE_ELEMENT);
+    int language_elements_length = language_elements.getLength ();
+    if(language_elements_length == 0) {
+      return null;
+    }
+    for(int j = 0; j < language_elements_length; j++) {
+      Element language_element = (Element) language_elements.item (j);
+      text.append (language_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+      if(j < language_elements_length - 1) {
+	text.append (StaticStrings.SPACE_CHARACTER);
+      }
+    }
+    return text.toString ();
+  }
+    
+  static private String languageDefaultToString (Element command_element) {
+    StringBuffer text = new StringBuffer (StaticStrings.LANGUAGE_DEFAULT_STR);
+    text.append (StaticStrings.TAB_CHARACTER);
+    text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+    return text.toString ();
+  }
+    
+  static private String languageMetadataToString (Element command_element) {
+    if (!command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
+      return "";
+    }
+    StringBuffer text = new StringBuffer (StaticStrings.LANGUAGE_METADATA_STR);
+    text.append (StaticStrings.TAB_CHARACTER);
+    String name_str = command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+    text.append (name_str);
+    return text.toString ();
+  }
+    
+  static private String indexOptionsToString (Element command_element) {
+    StringBuffer text = new StringBuffer ("");
+    if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+      text.append ("#");
+    }
+    text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+    text.append (StaticStrings.TAB_CHARACTER);
+    NodeList content_elements = command_element.getElementsByTagName (StaticStrings.INDEXOPTION_ELEMENT);
+    int content_elements_length = content_elements.getLength ();
+    // Don't output anything if no options are set.
+    if(content_elements_length == 0) {
+      return null;
+    }
+    for(int i = 0; i < content_elements_length; i++) {
+      Element content_element = (Element) content_elements.item (i);
+      text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+      text.append (StaticStrings.SPACE_CHARACTER);
+    }
+    return text.substring (0, text.length () - 1);
+  }
+    
+  static private String indexOptionDefaultToString (Element command_element) {
+    // Don't bother if there is no value
+    if (command_element.getAttribute (StaticStrings.VALUE_ATTRIBUTE).equals ("")) {
+      return "";
+    }
+    StringBuffer text = new StringBuffer ("");
+    if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+      text.append ("#");
+    }
+    text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+    text.append (StaticStrings.TAB_CHARACTER);
+    text.append (command_element.getAttribute (StaticStrings.VALUE_ATTRIBUTE));
+    return text.toString ();
+  }
+    
+  static private String metadataToString (Element command_element) {
+    // lets first check the value - if its empty, don't bother sticking it in the config file
+    String value_str = XMLTools.getValue (command_element);
+    if (value_str.equals ("")) {
+      return "";
+    }
+    boolean special = false;
+        
+    StringBuffer text = new StringBuffer ("");
+    String name_str = command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+    // If the name is one of the special four, we don't write the collectionmeta first. Note maintainer and buildtype are singled out for 'prittying' reasons.
+    if(name_str.equals (StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR)|| name_str.equals (StaticStrings.BUILDTYPE_STR) ) {
+      text.append (name_str);
+      text.append (StaticStrings.TAB_CHARACTER);
+      special = true;
+    }
+    else if (name_str.equals (StaticStrings.COLLECTIONMETADATA_CREATOR_STR) || name_str.equals (StaticStrings.COLLECTIONMETADATA_PUBLIC_STR) ) {
+      text.append (name_str);
+      text.append (StaticStrings.TAB_CHARACTER);
+      text.append (StaticStrings.TAB_CHARACTER);
+      special = true;
+    }
+    else {
+      text.append (StaticStrings.COLLECTIONMETADATA_STR);
+      text.append (StaticStrings.TAB_CHARACTER);
+      text.append (name_str);
+      text.append (StaticStrings.SPACE_CHARACTER);
+      String language_str = command_element.getAttribute (StaticStrings.LANGUAGE_ATTRIBUTE);
+      text.append (StaticStrings.LBRACKET_CHARACTER);
+      text.append (StaticStrings.LANGUAGE_ARGUMENT);
+      text.append (language_str);
+      text.append (StaticStrings.RBRACKET_CHARACTER);
+      text.append (StaticStrings.SPACE_CHARACTER);
+    }
+    name_str = null;
+        
+    // decode the value from XML to a form for config file
+    value_str = Codec.transform (value_str, Codec.DOM_TO_GREENSTONE);
+        
+    // We don't wrap the email addresses in quotes, nor the other special metadata
+    if(special) {
+      text.append (value_str);
+    }
+    else {
+      text.append (StaticStrings.SPEECH_CHARACTER);
+      text.append (value_str);
+      text.append (StaticStrings.SPEECH_CHARACTER);
+    }
+    value_str = null;
+    return text.toString ();
+  }
+    
+  static private String searchtypeToString (Element command_element) {
+    if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
+      StringBuffer text = new StringBuffer (StaticStrings.SEARCHTYPE_STR);
+      text.append (StaticStrings.TAB_CHARACTER);
+      NodeList search_elements = command_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
+      int search_elements_length = search_elements.getLength ();
+      for(int i = 0; i < search_elements_length; i++) {
+	Element search_element = (Element) search_elements.item (i);
+	text.append (search_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+	text.append (StaticStrings.SPACE_CHARACTER);
+      }
+      return text.substring (0, text.length () - 1);
+    }
+    else {
+      return null;
+    }
+  }
+    
+  static private String subcollectionToString (Element command_element) {
+    StringBuffer text = new StringBuffer (StaticStrings.SUBCOLLECTION_STR);
+    text.append (StaticStrings.SPACE_CHARACTER);
+    text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+    text.append (StaticStrings.SPACE_CHARACTER);
+    text.append (StaticStrings.TAB_CHARACTER);
+    text.append (StaticStrings.SPEECH_CHARACTER);
+    if(command_element.getAttribute (StaticStrings.TYPE_ATTRIBUTE).equals (StaticStrings.EXCLUDE_STR)) {
+      text.append (StaticStrings.EXCLAMATION_CHARACTER);
+    }
+    text.append (command_element.getAttribute (StaticStrings.CONTENT_ATTRIBUTE));
+    text.append (StaticStrings.SEPARATOR_CHARACTER);
+    text.append (XMLTools.getValue (command_element));
+    text.append (StaticStrings.SEPARATOR_CHARACTER);
+    String options_str = command_element.getAttribute (StaticStrings.OPTIONS_ATTRIBUTE);
+    if(options_str.length () > 0) {
+      text.append (options_str);
+    }
+    options_str = null;
+    text.append (StaticStrings.SPEECH_CHARACTER);
+    return text.toString ();
+  }
+    
+  static private String subcollectionDefaultIndexToString (Element command_element) {
+    StringBuffer text = new StringBuffer (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_STR);
+    text.append (StaticStrings.TAB_CHARACTER);
+    NodeList content_elements = command_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
+    int content_elements_length = content_elements.getLength ();
+    for(int j = 0; j < content_elements_length; j++) {
+      Element content_element = (Element) content_elements.item (j);
+      text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+      if(j < content_elements_length - 1) {
+	text.append (StaticStrings.COMMA_CHARACTER);
+      }
+    }
+    return text.toString ();
+  }
+    
+  static private String subcollectionIndexesToString (Element command_element) {
+    StringBuffer text = new StringBuffer (StaticStrings.SUBCOLLECTION_INDEX_STR);
+    text.append (StaticStrings.TAB_CHARACTER);
+    // Retrieve all of the subcollection index partitions
+    NodeList subcollectionindex_elements = command_element.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
+    int subcollectionindex_elements_length = subcollectionindex_elements.getLength ();
+    if(subcollectionindex_elements_length == 0) {
+      return null;
+    }
+    for(int j = 0; j < subcollectionindex_elements_length; j++) {
+      Element subcollectionindex_element = (Element) subcollectionindex_elements.item (j);
+      NodeList content_elements = subcollectionindex_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
+      int content_elements_length = content_elements.getLength ();
+      for(int k = 0; k < content_elements_length; k++) {
+	Element content_element = (Element) content_elements.item (k);
+	text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+	if(k < content_elements_length - 1) {
+	  text.append (StaticStrings.COMMA_CHARACTER);
+	}
+      }
+      if(j < subcollectionindex_elements_length - 1) {
+	text.append (StaticStrings.SPACE_CHARACTER);
+      }
+    }
+    return text.toString ();
+  }
+    
+  static private String supercollectionToString (Element command_element) {
+    NodeList content_elements = command_element.getElementsByTagName (StaticStrings.COLLECTION_ELEMENT);
+    int content_elements_length = content_elements.getLength ();
+    if(content_elements_length > 1) {
+      StringBuffer text = new StringBuffer (StaticStrings.SUPERCOLLECTION_STR);
+      text.append (StaticStrings.TAB_CHARACTER);
+      for(int j = 0; j < content_elements_length; j++) {
+	Element content_element = (Element) content_elements.item (j);
+	text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
+	if(j < content_elements_length - 1) {
+	  text.append (StaticStrings.SPACE_CHARACTER);
+	}
+      }
+      return text.toString ();
+    }
+    return null;
+  }
+    
+  static private String unknownToString (Element command_element) {
+    return XMLTools.getValue (command_element);
+  }
+    
+
+  /** Parse a collect.cfg into a DOM model representation.
+   * note we are ignoring 2.39 compatibility now. */
+  static public String parse (File collect_cfg_file, Document document) {
+    // hack for pre 2.71 compatibility - we need to add in a
+    // build type if there is not one there
+    boolean search_types_parsed = false;
+    boolean build_types_parsed = false;
+    try {
+      StringBuffer saved_collect_cfg_string_buffer = new StringBuffer ();
+            
+      Element collect_cfg_element = document.getDocumentElement ();
+      // Read in the file one command at a time.
+      InputStream istream = new FileInputStream (collect_cfg_file);
+      Reader in_reader = new InputStreamReader (istream, CollectionConfiguration.ENCODING);
+      BufferedReader in = new BufferedReader (in_reader);
+      String command_str = null;
+      while((command_str = in.readLine ()) != null) {
+	saved_collect_cfg_string_buffer.append (command_str + "\n");
+                
+	boolean append_element = true;
+	Element command_element = null;
+	// A command may be broken over several lines.
+	command_str = command_str.trim ();
+	boolean eof = false;
+	while(!eof && command_str.endsWith (StaticStrings.NEWLINE_CHARACTER)) {
+	  String next_line = in.readLine ();
+	  if(next_line != null) {
+	    next_line = next_line.trim ();
+	    if(next_line.length () > 0) {
+	      // Remove the new line character
+	      command_str = command_str.substring (0, command_str.lastIndexOf (StaticStrings.NEWLINE_CHARACTER));
+	      // And append the next line, which due to the test above must be non-zero length
+	      command_str = command_str + next_line;
+	    }
+	    next_line = null;
+	  }
+	  // If we've reached the end of the file theres nothing more we can do
+	  else {
+	    eof = true;
+	  }
+	}
+	// If there is still a new line character, then we remove it and hope for the best
+	if(command_str.endsWith (StaticStrings.NEWLINE_CHARACTER)) {
+	  command_str = command_str.substring (0, command_str.lastIndexOf (StaticStrings.NEWLINE_CHARACTER));
+	}
+	// Now we've either got a command to parse...
+	if(command_str.length () != 0) {
+	  // Start trying to figure out what it is
+	  //StringTokenizer tokenizer = new StringTokenizer(command_str);
+	  // Instead of a standard string tokenizer I'm going to use the new version of CommandTokenizer, which is not only smart enough to correctly notice speech marks and correctly parse them out, but now also takes the input stream so it can rebuild tokens that stretch over several lines.
+	  CommandTokenizer tokenizer = new CommandTokenizer (command_str, in);
+	  String command_type = tokenizer.nextToken ().toLowerCase ();
+	  // Why can't you switch on strings eh? We pass it to the various subparsers who each have a bash at parsing the command. If none can parse the command, an unknown element is created
+	  if(command_element == null && command_type.equals (StaticStrings.CLASSIFY_STR)) {
+	    command_element = parseClassify (command_str, document); 
+	  }
+	  if(command_element == null && command_type.equals (StaticStrings.FORMAT_STR)) {
+	    command_element = parseFormat (tokenizer, document); // Revised to handle multiple lines
+	  }
+	  if(command_element == null && (command_type.equals (StaticStrings.INDEX_STR)  || command_type.equals (StaticStrings.COMMENTED_INDEXES_STR))) {
+	    command_element = parseIndex (command_str, document);
+	  }
+	  if(command_element == null && (command_type.equals (StaticStrings.INDEX_DEFAULT_STR) || command_type.equals (StaticStrings.COMMENTED_INDEX_DEFAULT_STR))) {
+                        
+	    command_element = parseIndexDefault (command_str, document);
+	  }
+	  if(command_element == null && command_type.equals (StaticStrings.LANGUAGES_STR)) {
+	    command_element = parseLanguage (command_str, document);
+	  }
+	  if(command_element == null && command_type.equals (StaticStrings.LANGUAGE_DEFAULT_STR)) {
+	    command_element = parseLanguageDefault (command_str, document);
+	  }
+	  if (command_element == null && command_type.equals (StaticStrings.LANGUAGE_METADATA_STR)) {
+	    command_element = parseLanguageMetadata (command_str, document);
+	  }
+	  if(command_element == null && command_type.equals (StaticStrings.LEVELS_STR)) {
+	    command_element = parseIndexOptions (command_str, document, StaticStrings.LEVELS_STR, true);
+	  }
+	  if (command_element == null && command_type.equals (StaticStrings.COMMENTED_LEVELS_STR)) {
+	    command_element = parseIndexOptions (command_str, document, StaticStrings.LEVELS_STR, false);
+	  }
+	  if(command_element == null && command_type.equals (StaticStrings.LEVEL_DEFAULT_STR)) {
+	    command_element = parseIndexOptionDefault (command_str, document, StaticStrings.LEVEL_DEFAULT_STR, true);
+	  }
+	  if(command_element == null && command_type.equals (StaticStrings.COMMENTED_LEVEL_DEFAULT_STR)) {
+	    command_element = parseIndexOptionDefault (command_str, document, StaticStrings.LEVEL_DEFAULT_STR, false);
+	  }
+	  if (command_element == null && command_type.equals (StaticStrings.INDEXOPTIONS_STR)) {
+	    command_element = parseIndexOptions (command_str, document, StaticStrings.INDEXOPTIONS_STR, true);
+	  }
+	  if (command_element == null && command_type.equals (StaticStrings.COMMENTED_INDEXOPTIONS_STR)) {
+	    command_element = parseIndexOptions (command_str, document, StaticStrings.INDEXOPTIONS_STR, false);
+	  }
+	  if(command_element == null && command_type.equals (StaticStrings.COLLECTIONMETADATA_STR)) {
+	    command_element = parseMetadata (tokenizer, document); // Revised to handle multiple lines
+	  }
+	  if(command_element == null && (command_type.equals (StaticStrings.COLLECTIONMETADATA_PUBLIC_STR) || command_type.equals (StaticStrings.COLLECTIONMETADATA_CREATOR_STR) || command_type.equals (StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR) || command_type.equals (StaticStrings.BUILDTYPE_STR))) {
+	    command_element = parseMetadataSpecial (command_str, document);
+	    // pre 2.71 hack
+	    if (command_type.equals (StaticStrings.BUILDTYPE_STR)) {
+	      build_types_parsed = true;
+	    }
+	  }
+	  if(command_element == null && command_type.equals (StaticStrings.PLUGIN_STR)) {
+	    command_element = parsePlugin (command_str, document);
+	  }
+	  // leave here for backwards compatibility
+	  if(command_element == null && command_type.equals (StaticStrings.SEARCHTYPE_STR)) {
+	    command_element = parseSearchType (command_str, document);
+	    // pre 2.71 hack
+	    search_types_parsed = true;
+                        
+	  }
+	  if(command_element == null && command_type.equals (StaticStrings.SUBCOLLECTION_STR)) {
+	    command_element = parseSubCollection (command_str, document);
+	  }
+	  if(command_element == null && command_type.equals (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_STR)) {
+	    command_element = parseSubCollectionDefaultIndex (command_str, document);
+	  }
+	  if(command_element == null && command_type.equals (StaticStrings.SUBCOLLECTION_INDEX_STR)) {
+	    command_element = parseSubCollectionIndex (command_str, document);
+	  }
+	  if(command_element == null && (command_type.equals (StaticStrings.SUPERCOLLECTION_STR) || command_type.equals (StaticStrings.CCS_STR))) {
+	    command_element = parseSuperCollection (command_str, document);
+	  }
+	  // Doesn't match any known type
+	  command_type = null;
+	  if(command_element == null) {
+	    // No-one knows what to do with this command, so we create an Unknown command element
+	    command_element = document.createElement (StaticStrings.UNKNOWN_ELEMENT);
+	    XMLTools.setValue (command_element, command_str);
+	  }
+	}
+	// Or an empty line to remember for later
+	else {
+	  command_element = document.createElement (CollectionConfiguration.NEWLINE_ELEMENT);
+	}
+	// Now command element shouldn't be null so we append it to the collection config DOM, but only if we haven't been told not to add it
+	//if(append_element) {
+	collect_cfg_element.appendChild (command_element);
+	//}
+      }
+      if (!build_types_parsed) {
+	String buildtype_type = BuildTypeManager.BUILD_TYPE_MG;
+	if (search_types_parsed) {
+	  buildtype_type = BuildTypeManager.BUILD_TYPE_MGPP;
+	}
+	Element command_element = parseMetadataSpecial (StaticStrings.BUILDTYPE_STR+"  "+buildtype_type, document);
+	Node target_node = CollectionConfiguration.findInsertionPoint (command_element);
+	if(target_node != null) {
+	  collect_cfg_element.insertBefore (command_element, target_node);
+	}
+	else {
+	  collect_cfg_element.appendChild (command_element);
+	}
+                
+      }
+      return saved_collect_cfg_string_buffer.toString();
+    }
+    catch(Exception exception) {
+      DebugStream.println ("Error in CollectionConfiguration.parse(java.io.File): " + exception);
+      DebugStream.printStackTrace (exception);
+    }
+
+    return null;
+  }
+    
+    
+  /** Parses arguments from a tokenizer and returns a HashMap of mappings. The tricky bit here is that not all entries in the HashMap are name->value pairs, as some arguments are boolean and are turned on by their presence. Arguments are denoted by a '-' prefix.
+   * @param tokenizer a CommandTokenizer based on the unconsumed portion of a command string
+   * @return a HashMap containing the arguments parsed
+   */
+  static public HashMap parseArguments (CommandTokenizer tokenizer) {
+    HashMap arguments = new HashMap ();
+    String name = null;
+    String value = null;
+    while(tokenizer.hasMoreTokens () || name != null) {
+      // First we retrieve a name if we need one.
+      if(name == null) {
+	name = tokenizer.nextToken ();
+      }
+      // Now we attempt to retrieve a value
+      if(tokenizer.hasMoreTokens ()) {
+	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.
+	// 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;
+	}
+	// Otherwise we have a typical name->value pair ready to go
+	else {
+	  arguments.put (name, value);
+	  name = null;
+	}
+      }
+      // Otherwise its a binary flag
+      else {
+	arguments.put (name, null);
+	name = null;
+      }
+    }
+    return arguments;
+  }
+    
+  static private Element parseClassify (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      CommandTokenizer tokenizer = new CommandTokenizer (command_str);
+      // Check the token count. The token count from a command tokenizer isn't guarenteed to be correct, but it does give the maximum number of available tokens according to the underlying StringTokenizer (some of which may actually be append together by the CommandTokenizer as being a single argument).
+      if(tokenizer.countTokens () >= 2) {  // Must support "classify Phind" (no args)
+	command_element = document.createElement (StaticStrings.CLASSIFY_ELEMENT);
+	// First token is classify
+	tokenizer.nextToken ();
+	// The next token is the classifier type
+	command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, tokenizer.nextToken ());
+	// Now we parse out the remaining arguments into a hashmapping from name to value
+	HashMap arguments = parseArguments (tokenizer);
+	// Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
+	Iterator names = arguments.keySet ().iterator ();
+	while(names.hasNext ()) {
+	  String name = (String) names.next ();
+	  String value = (String) arguments.get (name); // Can be null
+	  // The metadata argument gets added as the content attribute
+	  /*                   if (name.equals (StaticStrings.METADATA_ARGUMENT) && value != null) {
+	  // Add the extracted namespace onto un-namespaced metadata names
+	  StringTokenizer string_tokenizer = new StringTokenizer (value, ",");
+	  value = "";
+	  while (string_tokenizer.hasMoreElements ()) {
+	  String token = (String) string_tokenizer.nextElement ();
+                            
+	  if (token.indexOf (StaticStrings.NS_SEP) == -1) {
+	  token = StaticStrings.EXTRACTED_NAMESPACE + token;
+	  }
+	  else {
+	  MetadataElement metadata_element = MetadataTools.getMetadataElementWithName (token);
+	  if (metadata_element != null) {
+	  token = metadata_element.getDisplayName ();
+	  }
+	  }
+                            
+	  if (!value.equals ("")) {
+	  value = value + ",";
+	  }
+	  value = value + token;
+	  }
+	  }*/
+	  // Everything else is an Option Element
+	  Element option_element = document.createElement (StaticStrings.OPTION_ELEMENT);
+	  option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name.substring (1));
+	  if(value != null) {
+	    // Remove any speech marks appended in strings containing whitespace
+	    if(value.startsWith (StaticStrings.SPEECH_CHARACTER) && value.endsWith (StaticStrings.SPEECH_CHARACTER)) {
+	      value = value.substring (1, value.length () - 1);
+	    }
+	    XMLTools.setValue (option_element, value);
+	  }
+	  option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	  command_element.appendChild (option_element);
+	  option_element = null;
+	  name = null;
+	  value = null;
+	}
+	names = null;
+	arguments = null;
+      }
+      tokenizer = null;
+    }
+    catch(Exception error) {
+    }
+    return command_element;
+  }
+    
+  static private Element parseFormat (CommandTokenizer tokenizer, Document document) {
+    Element command_element = null;
+    try {
+      command_element = document.createElement (StaticStrings.FORMAT_ELEMENT);
+      String name_str = tokenizer.nextToken ();
+      String value_str = tokenizer.nextToken ();
+      if(name_str != null && value_str != null) {
+	command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+	// If the value is true or false we add it as an attribute
+	if(value_str.equalsIgnoreCase (StaticStrings.TRUE_STR) || value_str.equalsIgnoreCase (StaticStrings.FALSE_STR)) {
+	  command_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, value_str.toLowerCase ());
+	}
+	// Otherwise it gets added as a text node
+	else {
+	  // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
+	  value_str = Codec.transform (value_str, Codec.GREENSTONE_TO_DOM);
+	  XMLTools.setValue (command_element, value_str);
+	}
+      }
+      else {
+	command_element = null;
+      }
+      name_str = null;
+      value_str = null;
+    }
+    catch (Exception exception) {
+      DebugStream.printStackTrace (exception);
+      command_element = null;
+    }
+    return command_element;
+  }
+    
+  static private Element parseIndex (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      String command = tokenizer.nextToken ();
+      command_element = document.createElement (StaticStrings.INDEXES_ELEMENT);
+      command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, (command.equals (StaticStrings.INDEX_STR) ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+      command = null;
+      if(!tokenizer.hasMoreTokens ()) {
+                
+	// there are no indexes
+	command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+	command_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR); // for now
+	tokenizer = null;
+	return command_element;
+      }
+            
+      while(tokenizer.hasMoreTokens ()) {
+	Element index_element = document.createElement (StaticStrings.INDEX_ELEMENT);
+	String index_str = tokenizer.nextToken ();
+	// There are two types of index we have to consider. Old G2.38 and earlier use level:source tuplets while G2.39+ have just a single, non-comma separated list where order is important.
+	boolean old_index;
+	if(index_str.indexOf (StaticStrings.COLON_CHARACTER) != -1) {
+	  old_index = true;
+	  index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE, index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER)));
+	  index_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
+	  command_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
+	}
+	else {
+	  command_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
+	  old_index = false;
+	}
+	StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
+	while(content_tokenizer.hasMoreTokens ()) {
+	  Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
+	  String content_str = content_tokenizer.nextToken ();
+	  // 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.indexOf (StaticStrings.NS_SEP) == -1) {
+	    if(content_str.equals (StaticStrings.TEXT_STR) || (!old_index && content_str.equals (StaticStrings.ALLFIELDS_STR))) {
+	      // Our special strings are OK.
+	    }
+	    else {
+	      content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
+	    }
+	  }
+	  content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
+	  index_element.appendChild (content_element);
+	  content_element = null;
+	}
+	content_tokenizer = null;
+	index_str = null;
+	command_element.appendChild (index_element);
+	index_element = null;
+      }
+      tokenizer = null;
+    }
+    catch (Exception exception) {
+      exception.printStackTrace ();
+    }
+    return command_element;
+  }
+    
+  static private Element parseIndexDefault (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      if(tokenizer.countTokens () >= 2) {
+	command_element = document.createElement (StaticStrings.INDEX_DEFAULT_ELEMENT);
+	command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken ()).equals (StaticStrings.INDEX_DEFAULT_STR) ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	String index_str = tokenizer.nextToken ();
+	String level="";
+	if (index_str.indexOf (StaticStrings.COLON_CHARACTER) !=-1) {
+	  level =  index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER));
+	}
+                
+	command_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE,level);
+                
+	String content_str = index_str;
+                
+	if (index_str.indexOf (StaticStrings.COLON_CHARACTER) !=-1) {
+	  content_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
+	}
+                
+	StringTokenizer content_tokenizer = new StringTokenizer (content_str, StaticStrings.COMMA_CHARACTER);
+	while(content_tokenizer.hasMoreTokens ()) {
+	  Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
+	  content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken ());
+	  command_element.appendChild (content_element);
+	  content_element = null;
+	}
+	content_tokenizer = null;
+	content_str = null;
+	content_str = null;
+	index_str = null;
+      }
+      tokenizer = null;
+    }
+    catch (Exception exception) {
+    }
+    return command_element;
+  }
+    
+  static private Element parseLanguage (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      tokenizer.nextToken ();
+      if(tokenizer.hasMoreTokens ()) {
+	command_element = document.createElement (StaticStrings.LANGUAGES_ELEMENT);
+	while(tokenizer.hasMoreTokens ()) {
+	  Element language_element = document.createElement (StaticStrings.LANGUAGE_ELEMENT);
+	  language_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
+	  command_element.appendChild (language_element);
+	  language_element = null;
+	}
+      }
+      tokenizer = null;
+    }
+    catch (Exception exception) {
+    }
+    return command_element;
+  }
+    
+  static private Element parseLanguageDefault (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      if(tokenizer.countTokens () >= 2) {
+	command_element = document.createElement (StaticStrings.LANGUAGE_DEFAULT_ELEMENT);
+	tokenizer.nextToken ();
+	String default_language_str = tokenizer.nextToken ();
+	command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, default_language_str);
+	command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	default_language_str = null;
+      }
+      tokenizer = null;
+    }
+    catch (Exception exception) {
+    }
+    return command_element;
+  }
+    
+  static private Element parseLanguageMetadata (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      if(tokenizer.countTokens () >= 2) {
+	command_element = document.createElement (StaticStrings.LANGUAGE_METADATA_ELEMENT);
+	tokenizer.nextToken ();
+	String language_metadata_str = tokenizer.nextToken ();
+	if (language_metadata_str.indexOf (StaticStrings.NS_SEP) == -1) {
+	  language_metadata_str = StaticStrings.EXTRACTED_NAMESPACE + language_metadata_str;
+	}
+	command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, language_metadata_str);
+	command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	language_metadata_str = null;
+      }
+      tokenizer = null;
+            
+    }
+    catch (Exception exception) {
+    }
+    return command_element;
+  }
+    
+  static private Element parseIndexOptions (String command_str, Document document, String type, boolean assigned) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      // First token is command type
+      String command = tokenizer.nextToken ();
+      if(tokenizer.hasMoreTokens ()) {
+	command_element = document.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
+	command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE,type);
+	command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	while(tokenizer.hasMoreTokens ()) {
+	  Element option_element = document.createElement (StaticStrings.INDEXOPTION_ELEMENT);
+	  option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
+	  command_element.appendChild (option_element);
+	  option_element = null;
+	}
+      }
+      command = null;
+    }
+    catch(Exception exception) {
+    }
+    return command_element;
+  }
+    
+  static private Element parseIndexOptionDefault (String command_str, Document document, String type, boolean assigned) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      // First token is command type
+      String command = tokenizer.nextToken ();
+      if(tokenizer.hasMoreTokens ()) {
+	command_element = document.createElement (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT);
+	command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR)); // is it commented out or not?
+	command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, type);
+	command_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, tokenizer.nextToken ());
+      }
+            
+      tokenizer = null;
+    }
+    catch (Exception exception) {
+    }
+    return command_element;
+  }
+    
+  static private Element parseMetadata (CommandTokenizer tokenizer, Document document) {
+    Element command_element = null;
+    try {
+      command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
+      String name_str = tokenizer.nextToken ();
+      String value_str = tokenizer.nextToken ();
+      if(name_str != null && value_str != null) {
+	String language_str = Configuration.getLanguage ();
+	// Check if the value string is actually a language string
+	if(value_str.startsWith (StaticStrings.LBRACKET_CHARACTER) && value_str.endsWith (StaticStrings.RBRACKET_CHARACTER)) {
+	  language_str = value_str.substring (value_str.indexOf (StaticStrings.LANGUAGE_ARGUMENT) + 2, value_str.length () - 1);
+	  value_str = tokenizer.nextToken ();
+	}
+	if(value_str != null) {
+	  // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
+	  value_str = Codec.transform (value_str, Codec.GREENSTONE_TO_DOM);
+	  command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+	  command_element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, language_str);
+	  command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	  XMLTools.setValue (command_element, value_str);
+	}
+	else {
+	  command_element = null;
+	}
+	language_str = null;
+      }
+      else {
+	command_element = null;
+      }
+      name_str = null;
+      value_str = null;
+    }
+    catch (Exception exception) {
+      DebugStream.printStackTrace (exception);
+      command_element = null;
+    }
+    return command_element;
+  }
+    
+  static private Element parseMetadataSpecial (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      if(tokenizer.countTokens () >= 2) {
+	String name_str = tokenizer.nextToken ();
+	String value_str = tokenizer.nextToken ();
+	if (name_str.equals (StaticStrings.COLLECTIONMETADATA_CREATOR_STR)) {
+	  command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT);
+	}
+	else if(name_str.equals (StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR)) {
+	  command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT);
+	}
+	else if(name_str.equals (StaticStrings.COLLECTIONMETADATA_PUBLIC_STR)) {
+	  command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT);
+	}
+	else if (name_str.equals (StaticStrings.BUILDTYPE_STR)) {
+	  command_element = document.createElement (StaticStrings.BUILDTYPE_ELEMENT);
+	}
+	if(command_element != null) {
+	  command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+	  command_element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
+	  command_element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+	  command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	  if(value_str.startsWith (StaticStrings.SPEECH_CHARACTER) && value_str.endsWith (StaticStrings.SPEECH_CHARACTER)) {
+	    value_str = value_str.substring (1, value_str.length () - 1);
+	  }
+	  XMLTools.setValue (command_element, value_str);
+	}
+	value_str = null;
+	name_str = null;
+      }
+      tokenizer = null;
+    }
+    catch (Exception exception) {
+    }
+    return command_element;
+  }
+    
+  static private Element parsePlugin (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      CommandTokenizer tokenizer = new CommandTokenizer (command_str);
+      // Check the token count. The token count from a command tokenizer isn't guarenteed to be correct, but it does give the maximum number of available tokens according to the underlying StringTokenizer (some of which may actually be append together by the CommandTokenizer as being a single argument).
+      if(tokenizer.countTokens () >= 2) {
+	command_element = document.createElement (StaticStrings.PLUGIN_ELEMENT);
+	// First token is plugin
+	tokenizer.nextToken ();
+	// The next token is the type
+	String type = tokenizer.nextToken ();
+	type = Utility.ensureNewPluginName(type);
+	command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, type);
+	// Now we parse out the remaining arguments into a hashmapping from name to value
+	HashMap arguments = parseArguments (tokenizer);
+	// Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
+	// also watch out for the deprecated -use_metadata_files option to RecPlug and remove it
+	Iterator names = arguments.keySet ().iterator ();
+	while(names.hasNext ()) {
+	  String name = (String) names.next ();
+	  String value = (String) arguments.get (name); // Can be null
+                    
+	  if(type.equals (StaticStrings.RECPLUG_STR) && name.substring (1).equals (StaticStrings.USE_METADATA_FILES_ARGUMENT)) {
+	    continue; // ignore this option
+	  }
+	  Element option_element = document.createElement (StaticStrings.OPTION_ELEMENT);
+	  option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name.substring (1));
+	  option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	  if(value != null) {
+	    // Remove any speech marks appended in strings containing whitespace
+	    if(value.startsWith (StaticStrings.SPEECH_CHARACTER) && value.endsWith (StaticStrings.SPEECH_CHARACTER)) {
+	      value = value.substring (1, value.length () - 1);
+	    }
+	    if(name.equals (StaticStrings.METADATA_ARGUMENT)) {
+	      // The metadata argument must be the fully qualified name of a metadata element, so if it doesn't yet have a namespace, append the extracted metadata namespace.
+	      if(value.indexOf (StaticStrings.NS_SEP) == -1) {
+		value = StaticStrings.EXTRACTED_NAMESPACE + value;
+	      }
+	    }
+	    XMLTools.setValue (option_element, value);
+	  }
+	  command_element.appendChild (option_element);
+	  option_element = null;
+	  name = null;
+	  value = null;
+	}
+                
+	type = null;
+	names = null;
+	arguments = null;
+      }
+      tokenizer = null;
+    }
+    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;
+  }
+    
+  /* search types are now handled as formats - leave this here to convert in case we have an old config file */
+  static private Element parseSearchType (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      // First token is command type (searchtype)
+      tokenizer.nextToken ();
+      if(tokenizer.hasMoreTokens ()) {
+	command_element = document.createElement (StaticStrings.FORMAT_ELEMENT);
+	command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, "SearchTypes");
+	String value = tokenizer.nextToken ();
+	while(tokenizer.hasMoreTokens ()) {
+	  value += ","+tokenizer.nextToken ();
+	}
+	value = Codec.transform (value, Codec.GREENSTONE_TO_DOM);
+	XMLTools.setValue (command_element, value);
+      }
+    }
+    catch(Exception exception) {
+    }
+    return command_element;
+  }
+    
+  static private Element parseSubCollection (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      CommandTokenizer tokenizer = new CommandTokenizer (command_str);
+      if(tokenizer.countTokens () >= 3) {
+	command_element = document.createElement (StaticStrings.SUBCOLLECTION_ELEMENT);
+	// First token is command type
+	tokenizer.nextToken ();
+	// Then subcollection identifier
+	command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
+	// Then finally the pattern used to build the subcollection partition
+	String full_pattern_str = tokenizer.nextToken ();
+	// Set inclusion/exclusion flag and remove any exclamation mark
+	boolean exclusion = full_pattern_str.startsWith (StaticStrings.EXCLAMATION_CHARACTER);
+	if (exclusion) {
+	  full_pattern_str = full_pattern_str.substring (1, full_pattern_str.length ());
+	  command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, StaticStrings.EXCLUDE_STR);
+	}
+	else {
+	  command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, StaticStrings.INCLUDE_STR);
+	}
+
+	// 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) {
+	    content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
+	  }
+	  command_element.setAttribute (StaticStrings.CONTENT_ATTRIBUTE, content_str);
+	  XMLTools.setValue (command_element, results[1]);
+	  if (results.length >= 3) {
+	    command_element.setAttribute (StaticStrings.OPTIONS_ATTRIBUTE, results[2]);
+	  }
+	}
+      }
+    }
+    catch(Exception exception) {
+      exception.printStackTrace ();
+    }
+    return command_element;
+  }
+    
+  static private Element parseSubCollectionDefaultIndex (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      if(tokenizer.countTokens () == 2) {
+	command_element = document.createElement (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
+	tokenizer.nextToken ();
+	//command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
+	String content_str = tokenizer.nextToken ();
+	StringTokenizer content_tokenizer = new StringTokenizer (content_str, StaticStrings.COMMA_CHARACTER);
+	while(content_tokenizer.hasMoreTokens ()) {
+	  Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
+	  content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken ());
+	  command_element.appendChild (content_element);
+	  content_element = null;
+	}
+	content_tokenizer = null;
+	content_str = null;
+      }
+      tokenizer = null;
+    }
+    catch(Exception exception) {
+    }
+    return command_element;
+  }
+    
+  static private Element parseSubCollectionIndex (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      tokenizer.nextToken ();
+      if(tokenizer.hasMoreTokens ()) {
+	command_element = document.createElement (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT);
+      }
+      while(tokenizer.hasMoreTokens ()) {
+	Element subcollectionindex_element = document.createElement (StaticStrings.INDEX_ELEMENT);
+	//command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
+	String content_str = tokenizer.nextToken ();
+	StringTokenizer content_tokenizer = new StringTokenizer (content_str, StaticStrings.COMMA_CHARACTER);
+	while(content_tokenizer.hasMoreTokens ()) {
+	  Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
+	  content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken ());
+	  subcollectionindex_element.appendChild (content_element);
+	  content_element = null;
+	}
+	content_tokenizer = null;
+	content_str = null;
+	command_element.appendChild (subcollectionindex_element);
+	subcollectionindex_element = null;
+      }
+      tokenizer = null;
+    }
+    catch (Exception exception) {
+    }
+    return command_element;
+  }
+    
+  static private Element parseSuperCollection (String command_str, Document document) {
+    Element command_element = null;
+    try {
+      StringTokenizer tokenizer = new StringTokenizer (command_str);
+      if(tokenizer.countTokens () >= 3) {
+	command_element = document.createElement (StaticStrings.SUPERCOLLECTION_ELEMENT);
+	tokenizer.nextToken ();
+	while(tokenizer.hasMoreTokens ()) {
+	  Element collection_element = document.createElement (StaticStrings.COLLECTION_ELEMENT);
+	  collection_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
+	  command_element.appendChild (collection_element);
+	  collection_element = null;
+	}
+      }
+      tokenizer = null;
+    }
+    catch(Exception exception) {
+    }
+    return command_element;
+  }
+    
+  static private String pluginToString (Element command_element) {
+    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);
+	  // turn display name into proper name
+	  //value_str = modifyMetadataArgumentValue(value_str);
+	  if (value_str.length () > 0) {
+	    text.append (StaticStrings.SPACE_CHARACTER);
+	    if(value_str.indexOf (StaticStrings.SPACE_CHARACTER) != -1) {
+	      // enclose in quotes
+	      text.append(StaticStrings.SPEECH_CHARACTER);
+	      text.append(value_str);
+	      text.append(StaticStrings.SPEECH_CHARACTER);
+	    } else {
+		    
+	      text.append(value_str);
+	    }
+	  }
+	      
+	  value_str = null;
+	}
+	option_element = null;
+      }
+    }
+    option_elements = null;
+	
+    return text.toString ();
+  }
+
+  // Convert metadata element names to internal names, and remove extracted metadata namespaces
+  /*  static private String modifyMetadataArgumentValue(String value_str) {
+      if (value_str.length () == 0) {
+      return value_str;
+      }
+    
+      // final true arg to return delims as tokens
+      StringTokenizer string_tokenizer = new StringTokenizer (value_str, ",;", true);
+      StringBuffer value_buffer = new StringBuffer ();
+      while (string_tokenizer.hasMoreElements ()) {
+      String raw_token = (String) string_tokenizer.nextElement ();
+      String token = raw_token.trim ();
+      boolean modified_token = false;
+      // not a delimiter token
+      if (!raw_token.equals(",") && !raw_token.equals(";")) {
+      //MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName (token);
+      //if (metadata_element != null) {
+      //token = metadata_element.getFullName ();
+      //modified_token = true;
+      //}
+	
+      //	if (token.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
+      // token = token.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
+      // modified_token = true;
+      //}
+      }
+      if (modified_token) {
+      value_buffer.append (token);
+      } else {
+      // we may have had whitespace etc that was part of the string
+      value_buffer.append (raw_token);
+      }
+      }
+    
+    
+      if(value_buffer.length () == 0) {
+      return "";
+      }
+      if(value_str.indexOf (StaticStrings.SPACE_CHARACTER) == -1) {
+      return value_buffer.toString();
+      }
+    
+      // it must contain a space, so we surround the value with quotes
+      value_buffer.insert(0, StaticStrings.SPEECH_CHARACTER);
+      value_buffer.append(StaticStrings.SPEECH_CHARACTER);
+      return value_buffer.toString();
+
+      }*/
+   
+
+  static public String generateStringVersion(Document document) {
+
+    StringBuffer collect_cfg_string_buffer = new StringBuffer ();
+    NodeList command_elements = document.getDocumentElement ().getChildNodes ();
+    boolean just_wrote_blank_line = false;  // Prevent two or more blank lines in a row
+    for (int i = 0; i < command_elements.getLength (); i++) {
+      Node command_node = command_elements.item (i);
+      if (!(command_node instanceof Element)) {
+	// We're only interested in Elements
+	continue;
+      }
+      Element command_element = (Element) command_node;
+            
+      // Handle NewLine elements (blank lines)
+      if (command_element.getNodeName ().equals (CollectionConfiguration.NEWLINE_ELEMENT) && !just_wrote_blank_line) {
+	collect_cfg_string_buffer.append ("\n");
+	just_wrote_blank_line = true;
+      }
+            
+      // Anything else we write to file, but only if it has been assigned, except for index and level commands
+      // (which just get commented out if unassigned -- a side effect of MG & MGPP compatibility)
+      else if (!command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR) || command_element.getNodeName ().equals (StaticStrings.INDEXES_ELEMENT) || command_element.getNodeName ().equals (StaticStrings.INDEX_DEFAULT_ELEMENT) || command_element.getNodeName ().equals (StaticStrings.INDEXOPTIONS_ELEMENT) || command_element.getNodeName ().equals (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT)) {
+	String command = toString(command_element);
+	//                 if (command_element.getNodeName ().equals (StaticStrings.FORMAT_ELEMENT)) {
+	//                     // Format statements we write out with ex. still present
+	// 		  command = toString (command_element); //, true);
+	//                 }
+	//                 else {
+	// 		  command = toString (command_element);//, false);
+	//                 }
+                
+	if (command != null && command.length ()> 0 ) {
+	  collect_cfg_string_buffer.append (command + "\n");
+	  just_wrote_blank_line = false;
+	}
+      }
+    }
+        
+    return collect_cfg_string_buffer.toString ();
+  }
+
+   
+}
Index: /gli/trunk/src/org/greenstone/gatherer/cdm/CollectionConfigXMLReadWrite.java
===================================================================
--- /gli/trunk/src/org/greenstone/gatherer/cdm/CollectionConfigXMLReadWrite.java	(revision 20447)
+++ /gli/trunk/src/org/greenstone/gatherer/cdm/CollectionConfigXMLReadWrite.java	(revision 20447)
@@ -0,0 +1,2067 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *
+ * Methods to read collectionConfig.xml files into internal XML form, and write 
+ * them back out again.
+ *
+ * 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.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataTools;
+import org.greenstone.gatherer.util.XMLTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+import org.w3c.dom.*;
+
+public class CollectionConfigXMLReadWrite {
+
+  static final private String PLUGOUT_ELEMENT = "plugout";//used by building flax collections
+
+  /** ********************************************************************************************************
+      The code from this point below are used for greenstone 3 collection configuration, i.e., read ColletionConfig.xml
+      * into the internal DOM tree, and convert the internal DOM tree back to CollectionConfig.xml.
+      *
+      Methods named 'doXXXX' are for convert collectionConfig.xml into the internal configuration xml structure;
+      Methods named 'convertXXXX' are for convert the internal configuration xml structure back to collectionConfig.xml.
+      ************************************************************************************************************ */
+    
+  /**Arguments:  metadataListNode->the 'displayItemList' element in collectionConfig.xml
+     name_value->the value of the 'name' attribute of 'index' element;
+     att_value->the value of the 'name' attribute of 'displayItem' element
+     return:     an ArrayList of the contructed 'CollectionMetadata' elements
+  */
+  static private ArrayList doDisplayItemList (Document to, Node displayListNode, String att_value, String name_value) {
+    Element toElement = to.getDocumentElement ();
+    ArrayList display_item_list = new ArrayList ();
+    ArrayList item_list = XMLTools.getNamedElementList ((Element)displayListNode,
+							StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, att_value);
+    if (item_list == null) {
+      return null;
+    }
+        
+    for (int i=0; i<item_list.size (); i++) {
+      Element item = (Element)item_list.get (i);
+      String text = XMLTools.getNodeText (item);
+            
+      //If there is nothing to display, don't bother creating the element
+      if (text == "") {
+	continue;
+      }
+      //get the value in 'lang=value'
+      String lang = item.getAttribute (StaticStrings.LANG_STR);
+            
+      Element e = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
+      e.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+      e.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_value);
+      e.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
+      XMLTools.setNodeText (e, text);
+      display_item_list.add (e);
+    }
+    return display_item_list;
+  }
+    
+  static private ArrayList doMetadataList (Document to, Node metadataListNode, String ele_name, String att_value) {
+    Element toElement = to.getDocumentElement ();
+    ArrayList metadata_list = new ArrayList ();
+        
+    ArrayList item_list = XMLTools.getNamedElementList ((Element)metadataListNode,
+							StaticStrings.METADATA_STR, StaticStrings.NAME_ATTRIBUTE, att_value);
+    if (item_list == null) {
+      return null;
+    }
+        
+    for (int i=0; i<item_list.size (); i++) {
+      Element item = (Element)item_list.get (i);
+      String text = XMLTools.getNodeText (item);
+            
+      //If there is nothing to display, don't bother creating the element
+      if (text == "") {
+	continue;
+      }
+      //get the value in 'lang=value'
+      String lang = item.getAttribute (StaticStrings.LANG_STR);
+            
+      Element element = to.createElement (ele_name);
+      element.setAttribute (StaticStrings.NAME_ATTRIBUTE, att_value);
+      element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
+      element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+      element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+      XMLTools.setNodeText (element, text);
+            
+      metadata_list.add (element);
+    }
+    return metadata_list;
+  }
+  // 'to' is the internal structure
+  static private void doMGIndexes (Document to, Node searchNode) {
+    Element toElement = to.getDocumentElement ();
+    Element indexes_element = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
+    indexes_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+    indexes_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
+        
+    NodeList index_children = ((Element)searchNode).getElementsByTagName (StaticStrings.INDEX_LOW_STR);//index
+    int num_nodes = index_children.getLength ();
+        
+    for (int i=0; i<num_nodes; i++) {
+      Element e = (Element)index_children.item (i);
+      String index_str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      String index_str_display = index_str;//used for creating collectionmetadata for this index
+      Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
+            
+      // For mg, it's the 'Old G2.38 and earlier' that use level:source tuplets, but we double check it anyway
+      boolean old_index = true;
+      if(index_str.indexOf (StaticStrings.COLON_CHARACTER) == -1) {
+	// It doesn't contain ':' character
+	System.err.println ("Something is wrong! the index should be level:source tuplets.");
+	old_index = false;
+      }
+      else {
+	// Handling 'index' element
+	index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE,
+				    index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER)));
+	index_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
+                
+	//Each index may have a list of comma-separated strings.
+	//split them into 'content' elements in the internal structure
+	StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
+	//index_str = "";
+	while(content_tokenizer.hasMoreTokens ()) {
+	  // Replace index_str to be qualified name, eg. dc.Subject and keywords insread of dc.Subject.
+                    
+                    
+	  Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
+	  String content_str = content_tokenizer.nextToken ();
+	  // 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.indexOf (StaticStrings.NS_SEP) == -1) {
+	    if(content_str.equals (StaticStrings.TEXT_STR) ||
+	       (!old_index && content_str.equals (StaticStrings.ALLFIELDS_STR))) {
+	      // in this case, do nothing
+	    }
+	    else {
+	      content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
+	    }
+	  }
+                    
+	  content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
+	  index_element.appendChild (content_element);
+	  content_element = null;
+	} 	// while ends
+                
+	indexes_element.appendChild (index_element);
+                
+	// Handling 'displayItem' elements and Constructing 'collectionmetadata' elements
+	// Use the fully qualified index names
+	ArrayList collectionmetadata_list = doDisplayItemList (to, e, StaticStrings.NAME_ATTRIBUTE, index_str_display);
+	appendArrayList (toElement, collectionmetadata_list);
+      } //else ends
+    } //for loop ends
+    appendProperly (toElement, indexes_element);
+        
+    //***//
+    // create another set of <indexes> which will be used when user switches to MGPP/LUCENE
+    // i.e. we build a default index set for a start
+        
+    String []index_strs =
+      {StaticStrings.TEXT_STR,
+       StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.TITLE_ELEMENT,
+       StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.SOURCE_ELEMENT};
+         
+    Element mgpp_indexes = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
+    mgpp_indexes.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+    mgpp_indexes.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
+    for (int i=0; i<index_strs.length; i++) {
+      Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
+      Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
+      content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_strs[i]);
+      index_element.appendChild (content_element);
+      mgpp_indexes.appendChild (index_element);
+             
+      // Contructing 'collectionmetadata' elements for 'mgpp' indexes
+      Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
+      collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+      collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_strs[i]);
+      collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
+      if (index_strs[i].indexOf (StaticStrings.NS_SEP) != -1) {
+	index_strs[i] = index_strs[i].substring (index_strs[i].indexOf (StaticStrings.NS_SEP) + 1);
+      }
+      XMLTools.setNodeText (collectionmetadata, index_strs[i]);
+             
+      appendProperly (toElement, collectionmetadata);
+             
+    }
+    appendProperly (toElement, mgpp_indexes);
+  }
+    
+  //This is actually doing indexes for both mgpp and lucene
+  static private void doMGPPIndexes (Document to, Node searchNode) {
+    Element toElement = to.getDocumentElement ();
+    Element indexes_element = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
+    indexes_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+    indexes_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
+        
+    NodeList index_children = ((Element)searchNode).getElementsByTagName (StaticStrings.INDEX_LOW_STR);//index
+    int num_nodes = index_children.getLength ();
+        
+    for (int i=0; i<num_nodes; i++) {
+            
+      Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
+      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 
+            
+      // Handling 'index' element
+      // Double check to make sure it's not colon separated style index.
+      boolean old_index = false;
+      if(index_str.indexOf (StaticStrings.COLON_CHARACTER) != -1) {
+	System.err.println ("Something is wrong! the index should NOT be level:source tuplets style.");
+	old_index = true;
+      }
+      //Each index may have a list of comma-separated strings.
+      //split them into 'content' elements in the internal structure
+      StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
+      //index_str = "";
+      while(content_tokenizer.hasMoreTokens ()) {
+	// Replace index_str to be qualified name, eg. dc.Subject and keywords insread of dc.Subject.             
+                
+	Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
+	String content_str = content_tokenizer.nextToken ();
+	// 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.indexOf (StaticStrings.NS_SEP) == -1) {
+	  if(content_str.equals (StaticStrings.TEXT_STR)) {
+	    // in this case, do nothing
+	  }
+	  else {
+	    content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
+	  }
+	}
+	content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
+	index_element.appendChild (content_element);
+	content_element = null;
+      } //while ends
+            
+      indexes_element.appendChild (index_element);
+            
+            
+      index_element = null;
+            
+      // Handling 'displayItem' element of this 'index' element
+      // 'e' is the parent element 'index' of 'displayItem' element
+      ArrayList collectionmetadata_list = doDisplayItemList (to, e, StaticStrings.NAME_ATTRIBUTE, index_str_display);
+      appendArrayList (toElement, collectionmetadata_list);
+            
+            
+    } // for loop ends
+    toElement.appendChild (indexes_element);
+        
+    // create another set of <indexes> which will be used when user switches to MG
+    // i.e. we build a default index set for a start
+    Element mg_indexes = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
+    mg_indexes.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+    mg_indexes.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
+        
+    //put the namespace '.ex' as prefix to the indexes
+    String []index_strs =
+      {StaticStrings.TEXT_STR,
+       StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.TITLE_ELEMENT,
+       StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.SOURCE_ELEMENT};
+    for (int i=0; i<index_strs.length; i++) {
+      Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
+      index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE, StaticStrings.DOCUMENT_STR);
+      Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
+      content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_strs[i]);
+      index_element.appendChild (content_element);
+             
+      mg_indexes.appendChild (index_element);
+             
+      // Contructing 'collectionmetadata' elements for 'mg' indexes
+      Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
+      collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+      String temp = StaticStrings.DOCUMENT_STR.concat (StaticStrings.COLON_CHARACTER).concat (index_strs[i]);
+      collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, temp);
+      collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
+      if (index_strs[i].indexOf (StaticStrings.NS_SEP) != -1) {
+	index_strs[i] = index_strs[i].substring (index_strs[i].indexOf (StaticStrings.NS_SEP) + 1);
+      }
+      XMLTools.setNodeText (collectionmetadata, index_strs[i]);
+             
+      appendProperly (toElement, collectionmetadata);
+             
+    }
+    toElement.appendChild (mg_indexes);
+         
+  }
+    
+  static private void doDisplayFormat (Document to, Element from) {
+    //display element in the xml file
+    Element de = (Element)XMLTools.getChildByTagName (from, StaticStrings.DISPLAY_STR);
+    if (de == null) {
+      return;
+    }
+    //format element in the display element
+    Element fe = (Element)XMLTools.getChildByTagName (de, StaticStrings.FORMAT_STR);
+
+    to.getDocumentElement ().appendChild (doFormat(to, fe, StaticStrings.DISPLAY_STR));
+  }
+
+  //construct 'DefaultIndex' element in the internal structure from collectionConfig.xml
+  static private void doDefaultIndex (Document to, Node searchNode) {
+    Element toElement = to.getDocumentElement ();
+    Element default_index_element = to.createElement (StaticStrings.INDEX_DEFAULT_ELEMENT);
+    default_index_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+        
+    Element e = (Element)XMLTools.getChildByTagName (searchNode, StaticStrings.INDEX_DEFAULT_ELEMENT_LOWERCASE);//defaultIndex
+    if (e == null) {
+      return;
+    }
+    String index_str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+        
+    boolean old_index = false;
+    if(index_str.indexOf (StaticStrings.COLON_CHARACTER) != -1) {
+      //The index is 'level:source tuplets' which is for mg. Take out 'level'
+      old_index = true;
+      default_index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE,
+					  index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER)));
+      index_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
+    } else {
+      default_index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE, "");
+    }
+        
+    //Each index may have a list of comma-separated strings.
+    //split them into 'content' elements in the internal structure
+    StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
+    while(content_tokenizer.hasMoreTokens ()) {
+      Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
+      String content_str = content_tokenizer.nextToken ();
+      // 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.indexOf (StaticStrings.NS_SEP) == -1) {
+	if(content_str.equals (StaticStrings.TEXT_STR) ||
+	   (!old_index && content_str.equals (StaticStrings.ALLFIELDS_STR))) {
+	  // in this case, do nothing
+	}
+	else {
+	  content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
+	}
+      }
+
+      content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
+      default_index_element.appendChild (content_element);
+      content_element = null;
+    }
+    appendProperly (toElement, default_index_element);
+  }
+  // For mg, this method is still called, but make it 'assigned=false'
+  static private void doDefaultLevel (Document to, Node searchNode) {
+    Element toElement = to.getDocumentElement ();
+    Element default_index_option = to.createElement (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT);
+    default_index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.LEVEL_DEFAULT_STR);
+        
+    Element e = (Element)XMLTools.getChildByTagName (searchNode, StaticStrings.LEVEL_DEFAULT_ELEMENT);
+    if (e != null) {
+      default_index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+      String level = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      default_index_option.setAttribute (StaticStrings.VALUE_ATTRIBUTE, level);
+    } else {
+      //In the case of mg, there's no level! build a default one using 'assigned=false value=document'
+      default_index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+      default_index_option.setAttribute (StaticStrings.VALUE_ATTRIBUTE, StaticStrings.DOCUMENT_STR);
+    }
+    appendProperly (toElement, default_index_option);
+  }
+    
+  // Transform plugins (pluginListNode) of collectionConfig.xml into the internal structure (i.e. Document to)
+  static private void doPlugin (Document to, Node pluginListNode) {
+    Element toElement = to.getDocumentElement ();
+    NodeList plugin_children = ((Element)pluginListNode).getElementsByTagName (StaticStrings.PLUGIN_STR);
+    int plugin_nodes = plugin_children.getLength ();
+        
+    if (plugin_nodes < 1) {
+      return;
+    }
+        
+    for (int i=0; i<plugin_nodes; i++) {
+      Element e = (Element)plugin_children.item (i);
+      String str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      str = Utility.ensureNewPluginName(str);
+      Element plugin_element = to.createElement (StaticStrings.PLUGIN_ELEMENT);
+      plugin_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, str);
+            
+            
+      NodeList option_children = e.getElementsByTagName (StaticStrings.OPTION_STR);
+            
+      for (int j=0; j<option_children.getLength (); j++) {
+	Element el = (Element)option_children.item (j);
+	String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+	if (name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
+	  name_str = name_str.substring (1);
+	}
+	String value_str = el.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
+	Element option_element = null;
+                
+	if (name_str.equals ("") && !value_str.equals ("")) {
+	  continue;
+	}
+                
+                
+	option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
+	option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	if(name_str.equals (StaticStrings.RECPLUG_STR) && value_str.equals (StaticStrings.USE_METADATA_FILES_ARGUMENT)) {
+	  continue; // ignore this option
+	}
+                
+	if(value_str != null) {
+	  // Remove any speech marks appended in strings containing whitespace
+	  if(value_str.startsWith (StaticStrings.SPEECH_CHARACTER) && value_str.endsWith (StaticStrings.SPEECH_CHARACTER)) {
+	    value_str = value_str.substring (1, value_str.length () - 1);
+	  }
+	  if(name_str.equals (StaticStrings.METADATA_STR)) {
+	    // The metadata argument must be the fully qualified name of a metadata element, so if it doesn't yet have a namespace, append the extracted metadata namespace.
+	    String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
+	    value_str = "";
+	    for (int k=0; k<=values.length-1; k++) {
+	      if (values[k].indexOf (StaticStrings.NS_SEP) == -1) {
+		values[k] = StaticStrings.EXTRACTED_NAMESPACE + values[k];
+	      }
+
+	      if (k < values.length-1) {
+		value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
+                                
+	      } else {
+		value_str = value_str + values[k];
+	      }
+	    }
+	  }
+	}
+	if (!name_str.equals ("")) {
+	  option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+	}
+	if (!value_str.equals ("")) {
+	  XMLTools.setNodeText (option_element, value_str);
+	}
+	plugin_element.appendChild (option_element);
+                
+      }
+            
+      appendProperly (toElement, plugin_element);
+    }
+        
+  }
+    
+  //Handle classifiers
+  static private void doClassifier (Document to, Node browseNode) {
+    Element toElement = to.getDocumentElement ();
+    NodeList classifier_children = ((Element)browseNode).getElementsByTagName (StaticStrings.CLASSIFIER_STR);
+    int num_nodes = classifier_children.getLength ();
+        
+    if (num_nodes < 1) {
+      return;
+    }
+        
+    for (int i=0; i<num_nodes; i++) {
+      Element e = (Element)classifier_children.item (i);
+      String str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      Element classify_element = to.createElement (StaticStrings.CLASSIFY_ELEMENT);
+      classify_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, str);
+            
+      String options_str = "";
+      NodeList option_children = e.getElementsByTagName (StaticStrings.OPTION_STR);
+      for (int j=0; j<option_children.getLength (); j++) {
+	Element el = (Element)option_children.item (j);
+	String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+	options_str = options_str + ((name_str.equals(""))? "" : (" " + name_str));
+	if (name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
+	  name_str = name_str.substring (1);
+	}
+	String value_str = el.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
+	options_str = options_str + ((name_str.equals(""))? "" : (" " + value_str));
+	Element option_element = null;
+                
+	if (name_str.equals ("") && !value_str.equals ("")) {
+	  continue; //invalid condition
+	}
+                
+	option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
+	option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+                
+	if (!name_str.equals ("")) {
+	  option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+	}
+                
+	if (!value_str.equals ("") && name_str.equals (StaticStrings.METADATA_STR)) {
+	  // The metadata argument must be the fully qualified name of a metadata element, so if it doesn't yet have a namespace, append the extracted metadata namespace.
+	  String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
+	  value_str = "";
+	  for (int k=0; k<=values.length-1; k++) {
+	    if (values[k].indexOf (StaticStrings.NS_SEP) == -1) {
+	      values[k] = StaticStrings.EXTRACTED_NAMESPACE + values[k];
+	    }
+	    else {
+	      MetadataElement metadata_element = MetadataTools.getMetadataElementWithName (values[k]);
+	      if (metadata_element != null) {
+		values[k] = metadata_element.getDisplayName ();
+	      }
+	    }
+	    if (k < values.length-1) {
+	      value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
+	    } else {
+	      value_str = value_str + values[k];
+	    }
+	  }
+	}
+                
+	if (value_str != null && !value_str.equals ("")) {
+	  XMLTools.setNodeText (option_element, value_str);
+	}
+	classify_element.appendChild (option_element);
+      }
+      //format element for this classifier
+      Element format = (Element)XMLTools.getChildByTagName (e, StaticStrings.FORMAT_STR);
+      if(format != null) {
+	classify_element.appendChild (doFormat(to, format, null));
+      }
+      appendProperly (toElement, classify_element);
+    }
+        
+    // default format statement for all classifiers
+    Element default_classifier_format = (Element)XMLTools.getChildByTagName (browseNode, StaticStrings.FORMAT_STR);
+
+    to.getDocumentElement ().appendChild (doFormat(to, default_classifier_format, StaticStrings.BROWSE_STR));
+  }
+  static private Element doFormat(Document to, Element format, String name_str) {
+    Element format_element = to.createElement (StaticStrings.FORMAT_STR);
+    if (name_str != null) {
+      format_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+    }
+    if (format != null) {
+      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"),
+				      gsf_text.indexOf(StaticStrings.FORMAT_END_TAG));
+      }
+                
+      XMLTools.setNodeText(format_element, gsf_text);
+    }
+    return format_element;
+  }
+  // Handling 'subcollection' elements in 'search' element of 'collectionConfig.xml'
+  static private void doSubcollection (Document to, Node searchNode) {
+    Element toElement = to.getDocumentElement ();
+    NodeList sub_children = ((Element)searchNode).getElementsByTagName (StaticStrings.SUBCOLLECTION_STR);
+    int sub_nodes = sub_children.getLength ();
+        
+    // There is no subcollection
+    if (sub_nodes < 1) {
+      return;
+    }
+        
+    for (int i=0; i<sub_nodes; i++) {
+      Element sub_child = (Element)sub_children.item (i);
+      String name_str = sub_child.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      String filter_str = sub_child.getAttribute (StaticStrings.FILTER_ATTRIBUTE);
+            
+      // filter_str is in the form '<! (if set)><metadata>/<metadata value>/<flag (if any)>'
+            
+      int pos = filter_str.indexOf (StaticStrings.SEPARATOR_CHARACTER);
+      String meta_str = "";
+      String meta_value_str = "";
+      String clude_str = "";
+      String flag_str = "";
+      if (pos == -1) {
+                
+	meta_str = meta_value_str = filter_str;
+	clude_str = StaticStrings.INCLUDE_STR;
+      } else {
+	clude_str = StaticStrings.INCLUDE_STR;
+	if (filter_str.startsWith (StaticStrings.EXCLAMATION_CHARACTER)) {
+	  clude_str = StaticStrings.EXCLUDE_STR;
+	  // Peel off "!"
+	  filter_str = filter_str.substring (StaticStrings.EXCLAMATION_CHARACTER.length ());
+	}
+                
+	String[] strs = filter_str.split (StaticStrings.SEPARATOR_CHARACTER);
+	if (strs[0] != null && strs[0] != "") {
+	  meta_str = strs[0];
+	}
+	if(!meta_str.equals (StaticStrings.FILENAME_STR) && meta_str.indexOf (StaticStrings.NS_SEP) == -1) {
+	  meta_str = StaticStrings.EXTRACTED_NAMESPACE + meta_str;
+	}
+                
+	if (strs[1] != null && strs[1] != "") {
+	  meta_value_str = strs[1];
+	}
+	if (strs.length > 2) {
+	  //This means there has been set a flag
+	  if (strs[2] != null && strs[2] != "") {
+	    flag_str = strs[2];
+	  }
+	}
+      }
+      Element subcollection_element = to.createElement (StaticStrings.SUBCOLLECTION_ELEMENT);
+      subcollection_element.setAttribute (StaticStrings.NAME_STR, name_str);
+      subcollection_element.setAttribute (StaticStrings.CONTENT_ATTRIBUTE, meta_str);
+      subcollection_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, clude_str);
+      if (flag_str != "") {
+	subcollection_element.setAttribute (StaticStrings.OPTIONS_ATTRIBUTE, flag_str);
+      }
+      XMLTools.setNodeText (subcollection_element, meta_value_str);
+            
+      toElement.appendChild (subcollection_element);
+    }
+  }
+  //Handle levels (document, section). In the internal structure, the element is called 'IndexOption'
+  static private void doLevel (Document to, Node searchNode) {
+    Element toElement = to.getDocumentElement ();
+    NodeList level_children = ((Element)searchNode).getElementsByTagName (StaticStrings.LEVEL_ATTRIBUTE);
+    int level_nodes = level_children.getLength ();
+        
+    // it's mg, there's no level. So we construct a default 'indexOption' in the internal structure
+    if (level_nodes < 1) {
+      Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
+      index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+      index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.LEVELS_STR);
+            
+      Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
+      option_element.setAttribute (StaticStrings.NAME_STR, StaticStrings.DOCUMENT_STR);
+      index_option.appendChild (option_element);
+            
+      appendProperly (toElement, index_option);
+            
+      return;
+    }
+        
+    Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
+    index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+    index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.LEVELS_STR);
+        
+    for (int i=0; i<level_nodes; i++) {
+      Element level_element = (Element)level_children.item (i);
+      String level_str = level_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
+      option_element.setAttribute (StaticStrings.NAME_STR, level_str);
+      index_option.appendChild (option_element);
+            
+            
+      // Contructing 'collectionmetadata' elements from the 'displayItem' of this 'level' element
+      ArrayList displayItem_list = XMLTools.getNamedElementList (level_element,
+								 StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_STR);
+      if (displayItem_list == null) {
+	return ;
+      }
+      for (int j=0; j<displayItem_list.size (); j++) {
+	Element item = (Element)displayItem_list.get (j);
+	String text = XMLTools.getNodeText (item);
+	String lang = item.getAttribute (StaticStrings.LANG_ATTRIBUTE);
+                
+	//If there is nothing to display, don't bother creating the element
+	if (text == "") {
+	  continue;
+	}
+	Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
+	collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, level_str);
+	collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
+	XMLTools.setNodeText (collectionmetadata, text);
+                
+	appendProperly (toElement, collectionmetadata);
+      }
+    }
+    appendProperly (toElement, index_option);
+  }
+  //Handle 'indexSubcollection' element of collectionConfig.xml,  which is called 'SubcollectionIndexes' in the internal structure. These contain the subcollection indexes (i.e. the filter or filter combinations), and displayed words for the filter names.
+  static private void doIndexSubcollection (Document to, Node searchNode) {
+    Element toElement = to.getDocumentElement ();
+    NodeList index_sub_children = ((Element)searchNode).getElementsByTagName (StaticStrings.SUBCOLLECTION_INDEX_ELEMENT);
+    int num_nodes = index_sub_children.getLength ();
+        
+    // there is no subcollection index
+    if (num_nodes < 1) {
+      return;
+    }
+        
+    Element subcollection_indexes = to.createElement (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT);
+        
+    for (int i=0; i<num_nodes; i++) {
+      Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);
+      Element index_sub_child = (Element)index_sub_children.item (i);
+      String name_str = index_sub_child.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+            
+      // name_str is in the form of comma separated strings, each of which is a subcollection filter name
+      String[] filters = name_str.split (StaticStrings.COMMA_CHARACTER);
+      for (int j=0; j<filters.length; j++) {
+                
+	Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
+	content_element.setAttribute (StaticStrings.NAME_STR, filters[j]);
+	index_element.appendChild (content_element);
+      }
+      subcollection_indexes.appendChild (index_element);
+            
+      // Contructing 'collectionmetadata' elements from the 'displayItem' of this 'indexSubcollection' element
+      ArrayList displayItem_list = XMLTools.getNamedElementList (index_sub_child,
+								 StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_STR);
+      if (displayItem_list == null) {
+	// there is no display item for this element
+	continue;
+      }
+      for (int j=0; j<displayItem_list.size (); j++) {
+	Element item = (Element)displayItem_list.get (j);
+	String text = XMLTools.getNodeText (item);
+	String lang = item.getAttribute (StaticStrings.LANG_ATTRIBUTE);
+                
+	//If there is nothing to display, don't bother creating the element
+	if (text == "") {
+	  continue;
+	}
+	Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
+	collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+	collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
+	XMLTools.setNodeText (collectionmetadata, text);
+                
+	appendProperly (toElement, collectionmetadata);
+      }
+    }
+    appendProperly (toElement, subcollection_indexes);
+  }
+  //Handle 'indexLanguage' element of collectionConfig.xml,  which is called 'Languages' in the internal structure. These contain the language indexes, and displayed words for those language index names.
+  static private void doIndexLanguage (Document to, Node searchNode) {
+    Element toElement = to.getDocumentElement ();
+    NodeList index_sub_children = ((Element)searchNode).getElementsByTagName (StaticStrings.LANGUAGE_INDEX_ELEMENT);
+    int num_nodes = index_sub_children.getLength ();
+        
+    // there is no subcollection index
+    if (num_nodes < 1) {
+      return;
+    }
+        
+    Element language_indexes = to.createElement (StaticStrings.LANGUAGES_ELEMENT);
+        
+    for (int i=0; i<num_nodes; i++) {
+      Element language_element = to.createElement (StaticStrings.LANGUAGE_ELEMENT);
+      Element index_sub_child = (Element)index_sub_children.item (i);
+      String name_str = index_sub_child.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      language_element.setAttribute (StaticStrings.NAME_STR, name_str);
+      language_indexes.appendChild (language_element);
+            
+      // Contructing 'collectionmetadata' elements from the 'displayItem' of this 'indexLanguage' element
+      ArrayList displayItem_list = XMLTools.getNamedElementList (index_sub_child,
+								 StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_STR);
+      if (displayItem_list == null) {
+	// there is no display item for this element
+	continue;
+      }
+      for (int j=0; j<displayItem_list.size (); j++) {
+	Element item = (Element)displayItem_list.get (j);
+	String text = XMLTools.getNodeText (item);
+	String lang = item.getAttribute (StaticStrings.LANG_ATTRIBUTE);
+                
+	//If there is nothing to display, don't bother creating the element
+	if (text == "") {
+	  continue;
+	}
+	Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
+	collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+	collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
+	XMLTools.setNodeText (collectionmetadata, text);
+                
+	appendProperly (toElement, collectionmetadata);
+      }
+    }
+    toElement.appendChild (language_indexes);
+  }
+  // Handling both searchType and search format statement
+  static private void doSearchFormat (Document to, Node searchNode) {
+    //There are two elements called <format> in <search>: one is for searchType; another is for format statement
+    NodeList format_children = ((Element)searchNode).getElementsByTagName (StaticStrings.FORMAT_STR);
+    int format_nodes = format_children.getLength ();
+    if (format_nodes < 1) {
+      return;
+    }
+    Element format = null;
+    Element search_type = null;
+    for(int i=0; i<format_nodes; i++) {
+      Node e = format_children.item (i);
+      if (e.hasAttributes () == false) {
+	//The format element for format statement has no any attribute
+	format = (Element)e;
+      }
+      else if (((Element)e).getAttribute (StaticStrings.NAME_ATTRIBUTE).equals(StaticStrings.SEARCHTYPE_ELEMENT)) {
+	search_type = (Element)e;
+      }
+    }
+    //format statement for search
+    if (format != null) {            
+      (to.getDocumentElement ()).appendChild (doFormat(to, format, StaticStrings.SEARCH_STR));
+    }
+    // searchType in search
+    if(search_type != null) {
+      String searchtype_str = XMLTools.getNodeText(search_type);
+        
+      Element search_type_element = to.createElement (StaticStrings.FORMAT_STR);
+      search_type_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.SEARCHTYPE_ELEMENT);
+      XMLTools.setNodeText(search_type_element, searchtype_str);
+        
+        
+      appendProperly (to.getDocumentElement (), search_type_element);
+    }
+  }
+  // Handling defaultIndexLanguage and languageMetadata in collectionConfig.xml ('elementNameFrom'); in the internal structure, they are called 'DefaultLanguage' and 'LanguageMetadata' ('elementNameTo') respectively.
+  // Converting from collectionConfig.xml to the internal xml structure.
+  static private void doLanguageMetadata (Document to, Node searchNode) {
+    Element toElement = to.getDocumentElement ();
+    String elementNameFrom = StaticStrings.LANGUAGE_METADATA_ELEMENT_STR;
+    String elementNameTo = StaticStrings.LANGUAGE_METADATA_ELEMENT;
+    Node from_element = XMLTools.getChildByTagName (searchNode, elementNameFrom);
+    if (from_element == null) {
+      return; // such an element not found
+    }
+        
+    Element to_element = to.createElement (elementNameTo);
+        
+    String name_str = ((Element)from_element).getAttribute (StaticStrings.NAME_ATTRIBUTE);
+    if (name_str.indexOf (StaticStrings.NS_SEP) == -1) {
+      name_str = StaticStrings.EXTRACTED_NAMESPACE + name_str;
+    }
+    to_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+    to_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+        
+    toElement.appendChild (to_element);
+  }
+  static private void doReplaceListRef (Document to, Element from) {
+    Element toElement = to.getDocumentElement ();
+        
+    Node replace_element = XMLTools.getChildByTagName (from, StaticStrings.REPLACELISTREF_STR);
+    if (replace_element == null) {
+      return; // such an element not found
+    }
+        
+    Element to_element = XMLTools.duplicateElement (to, (Element)replace_element, true);
+    toElement.appendChild (to_element);
+  }
+  static private void convertReplaceListRef (Document from, Document to) {
+    Element toElement = to.getDocumentElement ();
+        
+    Node replace_element = XMLTools.getChildByTagName (from.getDocumentElement (), StaticStrings.REPLACELISTREF_STR);
+    if (replace_element == null) {
+      return; // such an element not found
+    }
+        
+    Element to_element = XMLTools.duplicateElement (to, (Element)replace_element, true);
+    toElement.appendChild (to_element);
+  }
+  static private void doOAIElement (Document to, Element from) {
+    Element toElement = to.getDocumentElement ();
+        
+    Node oai_element = XMLTools.getChildByTagName (from, StaticStrings.OAI_ELEMENT);
+    if (oai_element == null) {
+      return; // such an element not found
+    }
+        
+    Element to_element = XMLTools.duplicateElement (to, (Element)oai_element, true);
+    toElement.appendChild (to_element);
+  }
+  static private void convertOAIElement (Document from, Document to) {
+    Element toElement = to.getDocumentElement ();
+        
+    Node oai_element = XMLTools.getChildByTagName (from.getDocumentElement (), StaticStrings.OAI_ELEMENT);
+    if (oai_element == null) {
+      return; // such an element not found
+    }
+        
+    Element to_element = XMLTools.duplicateElement (to, (Element)oai_element, true);
+    toElement.appendChild (to_element);
+  }
+  static private void doDefaultIndexLanguage (Document to, Node searchNode) {
+    Element toElement = to.getDocumentElement ();
+    String elementNameFrom = StaticStrings.LANGUAGE_DEFAULT_INDEX_ELEMENT;
+    String elementNameTo = StaticStrings.LANGUAGE_DEFAULT_ELEMENT;
+    Node from_element = XMLTools.getChildByTagName (searchNode, elementNameFrom);
+    if (from_element == null) {
+      return; // such an element not found
+    }
+        
+    Element to_element = to.createElement (elementNameTo);
+        
+    String name_str = ((Element)from_element).getAttribute (StaticStrings.NAME_ATTRIBUTE);
+    to_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+    to_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+        
+    toElement.appendChild (to_element);
+  }
+    
+  //Handle 'indexOption' (i.e. casefold, stem etc). In the internal structure, the element is called 'IndexOption'
+  static private void doIndexOption (Document to, Node searchNode) {
+    Element toElement = to.getDocumentElement ();
+    Node index_option_node = XMLTools.getChildByTagName (searchNode, StaticStrings.INDEXOPTION_STR);
+    if (index_option_node == null) {
+      return;
+    }
+    NodeList option_children = ((Element)index_option_node).getElementsByTagName (StaticStrings.OPTION_STR);
+    int option_nodes = option_children.getLength ();
+        
+    // for lucene, there is no 'indexOption'. We build a default 'indexOption' and 'assigned=false' in case the user switches to mg or mgpp
+    if (option_nodes < 1) {
+      Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
+      index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+      index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.INDEXOPTIONS_STR);
+      String[] option_str =
+	{ StaticStrings.CASEFOLD_OPTION_STR, StaticStrings.STEM_OPTION_STR };
+      for (int i=0; i<option_str.length; i++) {
+	Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
+	option_element.setAttribute (StaticStrings.NAME_STR, option_str[i]);
+	index_option.appendChild (option_element);
+      }
+      appendProperly (toElement, index_option);
+      return;
+    }
+        
+    Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
+    index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+    index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.INDEXOPTIONS_STR);
+        
+    for (int i=0; i<option_nodes; i++) {
+      String option_str = ((Element)option_children.item (i)).getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
+      option_element.setAttribute (StaticStrings.NAME_STR, option_str);
+      index_option.appendChild (option_element);
+    }
+    appendProperly (toElement, index_option);
+  }
+    
+  static private Element doBuildType (Document to, String att_value) {
+        
+    //construct 'BuildType' element
+    Element element = to.createElement (StaticStrings.BUILDTYPE_ELEMENT);
+    element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
+    element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
+    element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+    element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+
+    XMLTools.setNodeText (element, att_value);
+        
+    return element;
+  }
+    
+  // Convert 'description', 'smallicon' etc.
+  static private void convertDisplayItemList (Document from, Document to) {
+    Element displayItemList = to.createElement (StaticStrings.DISPLAYITEMLIST_STR);
+    Element destination = to.getDocumentElement ();
+        
+    String []att_values =
+      {StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR,
+       StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR,
+       StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR,
+       StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR};
+         
+    String []map_attrs =
+      {StaticStrings.DESCRIPTION_STR,
+       StaticStrings.SMALLICON_STR,
+       StaticStrings.ICON_STR,
+       StaticStrings.NAME_STR};
+          
+    for (int i=0; i<att_values.length; i++) {
+              
+      //dOc
+      ArrayList e_list = XMLTools.getNamedElementList (from.getDocumentElement (),
+						       StaticStrings.COLLECTIONMETADATA_ELEMENT,
+						       StaticStrings.NAME_ATTRIBUTE, att_values[i]);
+      // if such elements don't exist, don't bother
+      if (e_list == null) {
+	continue;
+      }
+      for (int j=0; j<e_list.size (); j++) {
+	Element e = (Element)e_list.get (j);
+	if (e.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	  continue;
+	}
+	String text = XMLTools.getNodeText (e);
+	String lang = e.getAttribute (StaticStrings.LANGUAGE_ATTRIBUTE);
+                  
+	Element displayItem = constructElement (StaticStrings.DISPLAYITEM_STR, map_attrs[i],
+						StaticStrings.LANG_STR, lang, text, to);
+	displayItemList.appendChild (displayItem);
+      }
+              
+    }
+    destination.appendChild (displayItemList);
+  }
+  // This method creates a DisplayItem element of the type of 'to' by using the ingredients from the element 'e'
+  static private Element constructDisplayItem (Element e, Document to) {
+    String lang_string = e.getAttribute (StaticStrings.LANGUAGE_ATTRIBUTE);
+    String text = XMLTools.getNodeText (e);
+    Element displayItem = to.createElement (StaticStrings.DISPLAYITEM_STR);
+    displayItem.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_ATTRIBUTE);
+    displayItem.setAttribute (StaticStrings.LANG_STR, lang_string);
+    XMLTools.setNodeText (displayItem, text);
+    return displayItem;
+  }
+  static private void convertMetadataList (Document from, Document to) {
+    Element metadataList = to.createElement (StaticStrings.METADATALIST_STR);
+    Element destination = to.getDocumentElement ();
+        
+    String []ele_names =
+      {StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT,
+       StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT,
+       StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT};
+    String []att_names =
+      {StaticStrings.COLLECTIONMETADATA_CREATOR_STR,
+       StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR,
+       StaticStrings.COLLECTIONMETADATA_PUBLIC_STR};
+    for (int i=0; i<ele_names.length; i++) {
+      Element e = XMLTools.getNamedElement (from.getDocumentElement (),
+					    ele_names[i], StaticStrings.NAME_ATTRIBUTE, att_names[i]);
+      if (e == null) {
+	continue;
+      }
+      String text = XMLTools.getNodeText (e);
+      Element metadata = to.createElement (StaticStrings.METADATA_STR);
+      metadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, att_names[i]);
+      metadata.setAttribute (StaticStrings.LANG_STR, StaticStrings.ENGLISH_LANGUAGE_STR);
+      XMLTools.setNodeText (metadata, text);
+      metadataList.appendChild (metadata);
+    }
+
+    destination.appendChild (metadataList);
+  }
+  // This method creates an element with the name 'element_name' of the type of 'to' by using the other three strings
+  static private Element constructElement (String element_name, String name_value, String lang_att, String lang_value, String text, Document to) {
+    Element e = to.createElement (element_name);
+    e.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+    e.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_value);
+    e.setAttribute (lang_att, lang_value);
+    XMLTools.setNodeText (e, text);
+        
+    return e;
+  }
+  // Convert classify in the internal(i.e. Document from) to collectionconfig.xml (i.e. Document to)
+  static private void convertClassifier (Document from, Document to) {
+    Element browse_element = to.createElement (StaticStrings.BROWSE_STR);
+    NodeList children = from.getDocumentElement ().getElementsByTagName (StaticStrings.CLASSIFY_ELEMENT);
+        
+    int num_children = (children == null)? 0 : children.getLength ();
+        
+    if (num_children == 0) {
+      return ;
+    }
+        
+    for (int i=0; i<num_children; i++) {
+            
+      Element child =  (Element)children.item (i);
+      if (child.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	continue;
+      }
+      String str = child.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
+      Element classifier_element = to.createElement (StaticStrings.CLASSIFIER_STR);
+      classifier_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, str);
+            
+      NodeList option_children = child.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
+      for (int j=0; j<option_children.getLength (); j++) {
+	Element el = (Element)option_children.item (j);
+	if (el.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	  continue;
+	}
+	String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+	String value_str = XMLTools.getNodeText (el);
+                
+                
+	if (name_str == null && value_str == null) {
+	  continue;
+	}
+	Element option_element = to.createElement (StaticStrings.OPTION_STR);
+	if (name_str != null && name_str.equals (StaticStrings.METADATA_STR)) {
+                    
+	  // The metadata argument is the fully qualified name of a metadata element, so if it contains a namespace, remove the extracted metadata namespace as the build process doesn't know about it.
+	  String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
+	  value_str = "";
+	  for (int k=0; k<=values.length-1; k++) {
+	    if(values[k].startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
+	      values[k] = values[k].substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
+	    }
+	    else {
+	      MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName (values[k]);
+	      if (metadata_element != null) {
+		values[k] = metadata_element.getFullName ();
+	      }
+	    }
+	    if (k < values.length-1) {
+	      value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
+	    } else {
+	      value_str = value_str + values[k];
+	    }
+	  }
+	}
+                
+	if (!name_str.equals ("")) {
+	  if (!name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
+	    name_str = StaticStrings.MINUS_CHARACTER + name_str;
+	  }
+	  option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+	}
+                
+	if (!value_str.equals ("")) {
+	  option_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, value_str);
+	}
+                
+	classifier_element.appendChild (option_element);
+      }
+            
+      //format element for this classifier
+      Element e = (Element)XMLTools.getChildByTagName (child, StaticStrings.FORMAT_STR);
+            
+      if (e != null) {
+	classifier_element.appendChild (convertFormat(to, e));
+      }
+      browse_element.appendChild (classifier_element);
+    }
+        
+    //convert default classifier format
+    Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
+					  StaticStrings.NAME_ATTRIBUTE,  StaticStrings.BROWSE_STR);
+    browse_element.appendChild (convertFormat(to, e));
+        
+    to.getDocumentElement ().appendChild (browse_element);
+  }
+  static private Element convertFormat(Document to, Element e) {
+    String format_str = XMLTools.getNodeText(e);
+    Element format = to.createElement (StaticStrings.FORMAT_STR);
+    //XMLTools.copyAllChildren (format, e);
+    XMLTools.setNodeText(format, format_str); 
+    return format;
+  }
+  //convert format statement for search
+  static private void convertSearchFormat (Document from, Document to) {
+    Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
+    Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
+					  StaticStrings.NAME_ATTRIBUTE,  StaticStrings.SEARCH_STR);
+                                                
+    search.appendChild (convertFormat(to, e));
+        
+  }
+  //convert format statement for display of the documents
+  static private void convertDisplayFormat (Document from, Document to) {
+    Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
+					  StaticStrings.NAME_ATTRIBUTE,  StaticStrings.DISPLAY_STR);
+    if (e == null) {
+      return;
+    }
+    Element display = to.createElement (StaticStrings.DISPLAY_STR);
+    display.appendChild (convertFormat(to, e));
+    to.getDocumentElement ().appendChild (display);
+  }
+  // Convert plugins in the internal(i.e. Document from) to collectionconfig.xml (i.e. Document to)
+  static private void convertPlugin (Document from, Document to) {
+    Element import_element = to.createElement (StaticStrings.IMPORT_STR);
+    Element plugin_list_element = to.createElement (StaticStrings.PLUGINLIST_STR);
+        
+    NodeList children = from.getDocumentElement ().getElementsByTagName (StaticStrings.PLUGIN_ELEMENT);
+    int num_children = (children == null)? 0 : children.getLength ();
+    if (num_children == 0) {
+      return ;
+    }
+        
+    for (int i=0; i<num_children; i++) {
+            
+      Element child =  (Element)children.item (i);
+      if (child.getAttribute (StaticStrings.SEPARATOR_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
+	continue;
+      }
+      if (child.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	continue;
+      }
+            
+      String str = child.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
+      Element plugin_element = to.createElement (StaticStrings.PLUGIN_STR);
+      plugin_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, str);
+            
+      NodeList option_children = child.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
+      for (int j=0; j<option_children.getLength (); j++) {
+	Element el = (Element)option_children.item (j);
+	if(!el.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
+	  continue;
+	}
+	String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+	String value_str = XMLTools.getNodeText (el);
+                
+                
+	if (name_str == null && value_str == null) {
+	  continue;
+	}
+	Element option_element = to.createElement (StaticStrings.OPTION_STR);
+	if (name_str != null && name_str.equals (StaticStrings.METADATA_STR)) {
+                    
+	  // The metadata argument is the fully qualified name of a metadata element, so if it contains a namespace, remove the extracted metadata namespace as the build process doesn't know about it.
+	  String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
+	  value_str = "";
+	  for (int k=0; k<=values.length-1; k++) {
+	    if(values[k].startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
+	      values[k] = values[k].substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
+	    }
+
+	    if (k < values.length-1) {
+	      value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
+	    } else {
+	      value_str = value_str + values[k];
+	    }
+	  }
+	}
+                
+	if (!name_str.equals ("")) {
+	  if (!name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
+	    name_str = StaticStrings.MINUS_CHARACTER + name_str;
+	  }
+	  option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+	}
+                
+	if (!value_str.equals ("")) {
+	  option_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, value_str);
+	}
+                
+	plugin_element.appendChild (option_element);
+      }//for loop ends
+            
+      plugin_list_element.appendChild (plugin_element);
+    }//for loop ends
+        
+    import_element.appendChild (plugin_list_element);
+        
+    //do the plugout element (used by building flax collections)
+    Node plugout = XMLTools.getChildByTagNameIndexed (from.getDocumentElement (), PLUGOUT_ELEMENT, 0);
+    if (plugout != null) {
+      Element to_element = XMLTools.duplicateElement (to, (Element)plugout, true);
+      import_element.appendChild (to_element);
+    }
+        
+    to.getDocumentElement ().appendChild (import_element);
+  }
+
+  //Handle 'searchType' of collectionConfig.xml. In the internal structure, its also called 'searchType', eg. plain, form
+  static private void convertSearchType (Document from, Document to) {
+    Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
+					  StaticStrings.NAME_ATTRIBUTE,  StaticStrings.SEARCHTYPE_ELEMENT);//searchType
+        
+    if (e == null) {
+      return;
+    }
+    Element search_type_element = to.createElement (StaticStrings.FORMAT_STR);
+        
+    //        String searchtype_str = e.getAttribute (StaticStrings.VALUE_ATTRIBUTE);        
+    //        search_type_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, searchtype_str);
+    String searchtype_str = XMLTools.getNodeText(e);        
+    XMLTools.setNodeText(search_type_element, searchtype_str);
+        
+    search_type_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.SEARCHTYPE_ELEMENT);
+    //Get the 'search' element from 'to'
+    Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
+    search.appendChild (search_type_element);
+  }
+    
+  static private void convertBuildType (Document from, Document to) {
+    Element e = XMLTools.getNamedElement (from.getDocumentElement (),
+					  StaticStrings.BUILDTYPE_ELEMENT,
+					  StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
+    if (e == null) {
+      return;
+    }
+    String indexer = XMLTools.getNodeText (e);
+    Element search = to.createElement (StaticStrings.SEARCH_STR);
+    search.setAttribute (StaticStrings.TYPE_ATTRIBUTE, indexer);
+    to.getDocumentElement ().appendChild (search);
+  }
+  static private void convertDefaultIndex (Document from, Document to, Element search) {
+    Element source = from.getDocumentElement ();
+        
+    Element default_index_element = (Element)XMLTools.getChildByTagName (source, StaticStrings.INDEX_DEFAULT_ELEMENT);
+    if (default_index_element == null) {
+      return;
+    }
+        
+    String indexer = search.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
+    String level_str = default_index_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE);
+    // Debugging purposes
+    if (level_str.equals ("") && indexer.equals (StaticStrings.MG_STR) ) {
+      System.out.println ("Bug: DefaultIndex should have its level attribute not empty.");
+    }
+        
+    NodeList content_elements = default_index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
+    int content_elements_length = content_elements.getLength ();
+        
+    // Don't output anything if no indexes are set
+    if(content_elements_length == 0) {
+      return ;//
+    }
+        
+    String index_str = "";
+        
+    if (indexer.equals (StaticStrings.MG_STR)) {
+      //combine level with indexes
+      index_str = level_str + StaticStrings.COLON_CHARACTER;
+    }
+    else { //for mgpp/lucene, just take index
+      //do nothing
+    }
+        
+    for(int k = 0; k < content_elements_length; k++) {
+      Element content_element = (Element) content_elements.item (k);
+      if (content_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	continue;
+      }
+      String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+            
+      if(name_str.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
+	name_str = name_str.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
+      }
+
+      index_str = index_str + name_str;
+            
+      // Make it comma separated string
+      if(k < content_elements_length - 1) {
+	index_str = index_str + StaticStrings.COMMA_CHARACTER;
+      }
+      content_element = null;
+    }//for loop ends
+        
+        
+    Element default_index = to.createElement (StaticStrings.INDEX_DEFAULT_ELEMENT_LOWERCASE);
+    default_index.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_str);
+    search.appendChild (default_index);
+        
+  }
+  static private void convertSubcollection (Document from, Document to) {
+    Element source = from.getDocumentElement ();
+    //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
+    Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
+        
+    // Get the Subcollection element from the internal structure
+    NodeList subcollection_elements = source.getElementsByTagName (StaticStrings.SUBCOLLECTION_ELEMENT);
+    if (subcollection_elements == null) {
+      return;
+    }
+    int subcollection_elements_length = subcollection_elements.getLength ();
+        
+    if (subcollection_elements_length == 0) { // no
+      return ;
+    }
+        
+    for(int j = 0; j < subcollection_elements_length; j++) {
+            
+      Element e = (Element) subcollection_elements.item (j);
+      if (e.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	continue;
+      }
+      String content = e.getAttribute (StaticStrings.CONTENT_ATTRIBUTE);
+      String name = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      String options = e.getAttribute (StaticStrings.OPTIONS_ATTRIBUTE);
+      String type = e.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
+      String text = XMLTools.getNodeText (e);
+            
+      String filter = "";
+      if (type.equals (StaticStrings.EXCLUDE_STR)) {
+	filter = StaticStrings.EXCLAMATION_CHARACTER;
+      }
+            
+      if(content.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
+	content = content.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
+      }
+      filter = filter + content + StaticStrings.SEPARATOR_CHARACTER + text;
+      if (options != null && options != "") {
+	filter = filter + StaticStrings.SEPARATOR_CHARACTER + options;
+      }
+      Element subcollection = to.createElement (StaticStrings.SUBCOLLECTION_STR);
+      subcollection.setAttribute (StaticStrings.FILTER_ATTRIBUTE, filter);
+      subcollection.setAttribute (StaticStrings.NAME_ATTRIBUTE, name);
+            
+      search.appendChild (subcollection);
+    }
+  }
+  static private void convertSubcollectionIndexes (Document from, Document to) {
+    Element source = from.getDocumentElement ();
+    //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
+    Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
+        
+    // Get the SubcollectionIndexes element from the internal structure
+    Element subcollection_indexes = (Element)XMLTools.getChildByTagName (source, StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT);
+    if (subcollection_indexes == null) {
+      return;
+    }
+    NodeList index_elements = subcollection_indexes.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
+    int index_elements_length = index_elements.getLength ();
+        
+    if (index_elements_length == 0) { // no indexes
+      return ;
+    }
+        
+    for(int j = 0; j < index_elements_length; j++) {
+      Element index_element = (Element) index_elements.item (j);
+      if (index_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	continue;
+      }
+            
+      Element index = to.createElement (StaticStrings.SUBCOLLECTION_INDEX_ELEMENT);
+            
+      String index_value = "";
+            
+      NodeList content_elements = index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
+      int content_elements_length = content_elements.getLength ();
+            
+      for(int k = 0; k < content_elements_length; k++) {
+	Element content_element = (Element) content_elements.item (k);
+	if (content_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	  continue;
+	}
+	String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+	index_value += name_str;
+	// Make it comma separated string
+	if(k < content_elements_length - 1) {
+	  index_value += StaticStrings.COMMA_CHARACTER;
+	}
+	content_element = null;
+      }//for loop ends
+            
+      index.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_value);
+            
+      // Now constructing 'displayItem' element for this 'indexSubcollection' element
+      // from the collectionmetadata element
+      ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
+									StaticStrings.COLLECTIONMETADATA_ELEMENT,
+									StaticStrings.NAME_ATTRIBUTE, index_value);
+            
+      if (collectionmetadata_list != null) {
+                
+	for(int k = 0; k < collectionmetadata_list.size (); k++) {
+	  Element collectionmetadata = (Element)collectionmetadata_list.get (k);
+	  if (collectionmetadata.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	    continue;
+	  }
+	  Element displayItem = constructDisplayItem (collectionmetadata, to);
+	  index.appendChild (displayItem);
+	}
+      }
+            
+      search.appendChild (index);
+            
+    } //for loop ends
+  }
+    
+  static private void convertLanguages (Document from, Document to) {
+    Element source = from.getDocumentElement ();
+    //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
+    Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
+        
+    // Get the Languages element from the internal structure
+    Element languages = (Element)XMLTools.getChildByTagName (source, StaticStrings.LANGUAGES_ELEMENT);
+    if (languages == null) {
+      return;
+    }
+    NodeList language_elements = languages.getElementsByTagName (StaticStrings.LANGUAGE_ELEMENT);
+    int language_elements_length = language_elements.getLength ();
+        
+    if (language_elements_length == 0) {
+      return ;
+    }
+        
+    for(int j = 0; j < language_elements_length; j++) {
+      Element element = (Element) language_elements.item (j);
+      if (element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	continue;
+      }
+            
+      // Create indexLanguage element
+      Element index_language = to.createElement (StaticStrings.LANGUAGE_INDEX_ELEMENT);
+            
+      String name_str = element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      index_language.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+            
+      // Now constructing 'displayItem' element for this 'indexLanguage' element
+      // from the collectionmetadata element
+      ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
+									StaticStrings.COLLECTIONMETADATA_ELEMENT,
+									StaticStrings.NAME_ATTRIBUTE, name_str);
+            
+      if (collectionmetadata_list != null) {
+                
+	for(int k = 0; k < collectionmetadata_list.size (); k++) {
+	  Element collectionmetadata = (Element)collectionmetadata_list.get (k);
+	  if (collectionmetadata.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	    continue;
+	  }
+	  Element displayItem = constructDisplayItem (collectionmetadata, to);
+	  index_language.appendChild (displayItem);
+	}
+      }
+            
+      search.appendChild (index_language);
+            
+    } //for loop ends
+        
+    // Convert DefaultLanguage
+    // Get the DefaultLanguage element from the internal structure
+    Element default_language = (Element)XMLTools.getChildByTagName (source, StaticStrings.LANGUAGE_DEFAULT_ELEMENT);
+    if(default_language != null) {
+      String lang_name = default_language.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      Element default_index_language = to.createElement (StaticStrings.LANGUAGE_DEFAULT_INDEX_ELEMENT);
+      default_index_language.setAttribute (StaticStrings.NAME_ATTRIBUTE, lang_name);
+      search.appendChild (default_index_language);
+    }
+    // Convert LanguageMetadata
+    // Get the LanguageMetadata element from the internal structure
+    Element language_metadata = (Element)XMLTools.getChildByTagName (source, StaticStrings.LANGUAGE_METADATA_ELEMENT);
+    if(language_metadata != null) {
+      String meta_name = language_metadata.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      Element language_meta = to.createElement (StaticStrings.LANGUAGE_METADATA_ELEMENT_STR);
+      if(meta_name.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
+	meta_name = meta_name.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
+      }
+      language_meta.setAttribute (StaticStrings.NAME_ATTRIBUTE, meta_name);
+      search.appendChild (language_meta);
+    }
+  }
+    
+  //convert indexes and their displayItems, which go in 'search' element in collectionConfig.xml
+  //parameter 'to' is the document to be saved as collectionConfig.xml
+  //parameter 'from' is the internal xml structure
+  static private void convertIndex (Document from, Document to) {
+    Element source = from.getDocumentElement ();
+    //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
+    Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
+        
+    //THere are two sets of indexes elements, find the one which is assigned 'true'
+    Element indexes = XMLTools.getNamedElement (source,
+						StaticStrings.INDEXES_ELEMENT,
+						StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+    if (indexes == null) {
+      return;
+    }
+    NodeList index_elements = indexes.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
+    int index_elements_length = index_elements.getLength ();
+        
+    if (index_elements_length == 0) { // no indexes
+      return ;
+    }
+        
+    //find out it's mg or mgpp/lucene
+    String mg = search.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
+    boolean mg_indexer = false;
+    if (mg.equals (StaticStrings.MG_STR)) {
+      mg_indexer = true;//it's mg, then the level is set as attribute of
+    }
+    if (mg_indexer == false) {
+      // It's mgpp. Construct 'level' and 'defaultLevel' elements separately.
+      convertLevels (from, to, search);
+    }
+        
+    for(int j = 0; j < index_elements_length; j++) {
+      Element index_element = (Element) index_elements.item (j);
+      if (index_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	continue;
+      }
+            
+      Element index_ele = to.createElement (StaticStrings.INDEX_LOW_STR);//index
+            
+      // Used for creating displayItem for this element 'index_ele' further below
+      // full_index_names contain 'ex.'
+      String full_index_name = "";
+      String level_str = "";
+            
+      StringBuffer index_value = new StringBuffer ();
+      if (mg_indexer == true) {
+	// For mg indexer, there is a 'level' attribute in the index element of the internal structure
+	// But mgpp/lucene don't
+	level_str = index_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE);
+	if(level_str.length () > 0) {
+	  index_value.append (level_str).append (StaticStrings.COLON_CHARACTER);
+	  //index_value = index_value.StaticStrings.COLON_CHARACTER;
+	}
+      }
+            
+      NodeList content_elements = index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
+      int content_elements_length = content_elements.getLength ();
+            
+      for(int k = 0; k < content_elements_length; k++) {
+	Element content_element = (Element) content_elements.item (k);
+	if (content_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	  continue;
+	}
+	String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+                
+	full_index_name = full_index_name + name_str;
+	if (k < content_elements_length - 1) {
+	  full_index_name = full_index_name + StaticStrings.COMMA_CHARACTER;
+	}
+                
+	if(name_str.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
+	  name_str = name_str.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
+	}
+
+	index_value.append (name_str);
+	name_str = null;
+	// Make it comma separated string
+	if(k < content_elements_length - 1) {
+	  index_value.append (StaticStrings.COMMA_CHARACTER);
+	}
+	content_element = null;
+      }//for loop ends
+            
+      String temp_str = index_value.toString ();
+      index_ele.setAttribute (StaticStrings.NAME_ATTRIBUTE, temp_str);
+            
+      // Now constructing 'displayItem' element for this 'index_ele' element
+      // The index names in the collectionmetadata elements in the internal structure are not the names that
+      // are used in the content elements (i.e. ex.Source or dc.Subject and keywords), but the names that are
+      // in the configuration files (i.e. Source or dc.Subject)
+      ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
+									StaticStrings.COLLECTIONMETADATA_ELEMENT,
+									StaticStrings.NAME_ATTRIBUTE, temp_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) {
+                
+	for(int k = 0; k < collectionmetadata_list.size (); k++) {
+	  Element collectionmetadata = (Element)collectionmetadata_list.get (k);
+	  if (collectionmetadata.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+	    continue;
+	  }
+	  Element displayItem = constructDisplayItem (collectionmetadata, to);
+                    
+	  index_ele.appendChild (displayItem);
+	}
+      }
+            
+      search.appendChild (index_ele);
+            
+    } //for loop ends
+        
+    //Convert default index
+    convertDefaultIndex (from, to, search);
+    convertIndexOptions(from, to, search);
+  }
+  // Convert levels for mgpp/lucene. This method is called by converIndex() when mgpp indexer is detected.
+  static private void convertLevels (Document from, Document to, Element search) {
+    Element source = from.getDocumentElement ();
+    Element index_option = XMLTools.getNamedElement (source,
+						     StaticStrings.INDEXOPTIONS_ELEMENT,
+						     StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVELS_STR);
+    if (index_option == null) {
+      return;
+    }
+    //Debugging purposes
+    if (index_option.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+      DebugStream.println ("For mgpp, there should be an IndexOption element for levels which is assigned 'true': possible bug.");
+    }
+        
+    NodeList option_elements = index_option.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
+    int num_elements = option_elements.getLength ();
+        
+    // Don't output anything if no indexes are set
+    if(num_elements == 0) {
+      return ;//
+    }
+        
+    for(int k = 0; k < num_elements; k++) {
+      Element e = (Element) option_elements.item (k);
+      String name_str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+      Element level_element = to.createElement (StaticStrings.LEVEL_ELEMENT);
+      level_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
+            
+      //Now construct displayItem for this level element from collectionmetadata
+      ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
+									StaticStrings.COLLECTIONMETADATA_ELEMENT,
+									StaticStrings.NAME_ATTRIBUTE, name_str);
+            
+      if (collectionmetadata_list != null) {
+                
+	for(int j = 0; j < collectionmetadata_list.size (); j++) {
+	  Element collectionmetadata = (Element)collectionmetadata_list.get (j);
+                    
+	  Element displayItem = constructDisplayItem (collectionmetadata, to);
+	  level_element.appendChild (displayItem);
+	}
+      }
+      search.appendChild (level_element);
+    }
+        
+    //Convert default level
+    Element default_index_option = XMLTools.getNamedElement (source,
+							     StaticStrings.INDEXOPTION_DEFAULT_ELEMENT,
+							     StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVEL_DEFAULT_STR);
+    if (default_index_option == null) {
+      return;
+    }
+    Element default_level = to.createElement (StaticStrings.LEVEL_DEFAULT_ELEMENT);
+    String default_level_str = default_index_option.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
+    default_level.setAttribute (StaticStrings.NAME_ATTRIBUTE, default_level_str);
+    search.appendChild (default_level);
+        
+  }
+  // Convert indexoptions for mg/mgpp/lucene. This method is called by convertIndex().
+  static private void convertIndexOptions (Document from, Document to, Element search) {
+    Element source = from.getDocumentElement ();
+    Element index_option = XMLTools.getNamedElement (source,
+						     StaticStrings.INDEXOPTIONS_ELEMENT,
+						     StaticStrings.NAME_ATTRIBUTE, StaticStrings.INDEXOPTIONS_STR);
+    if (index_option == null) {
+      return;
+    }
+    //Debugging purposes
+    if (index_option.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
+      DebugStream.println ("There should be an IndexOption element which is assigned 'true': possible bug.");
+    }
+    Element indexOptionEl = to.createElement(StaticStrings.INDEXOPTION_STR);
+    NodeList option_elements = index_option.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
+    int num_elements = option_elements.getLength ();        
+    // Don't output anything if no index
+    if(num_elements == 0) {
+      return ;//
+    }
+    search.appendChild (indexOptionEl);
+        
+    for(int k = 0; k < num_elements; k++) {
+      Element e = (Element) option_elements.item (k);
+      String name_att = e.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+      Element optionEl = to.createElement(StaticStrings.OPTION_STR);
+      optionEl.setAttribute(StaticStrings.NAME_ATTRIBUTE, name_att);
+      indexOptionEl.appendChild(optionEl);
+    }
+           
+  }
+  // Append the element son to the element mother in the appropriate position.
+  static public void appendProperly (Element mother, Element son) {
+    if (son == null)
+      return;
+        
+    Node reference_node = findInsertionPoint (mother, son);
+    if(reference_node != null) {
+      mother.insertBefore (son, reference_node);
+    }
+    else {
+      mother.appendChild (son);
+    }
+  }
+  /** Find the best insertion position for the given DOM Element 'target_element' in the DOM Element 'document_element'. This should try to match command tag, and if found should then try to group by name or type (eg CollectionMeta), or append to end is no such grouping exists (eg Plugins). Failing a command match it will check against the command order for the best insertion location.
+   * @param target_element the command Element to be inserted
+   * @return the Element which the given command should be inserted before, or null to append to end of list
+   */
+  static public Node findInsertionPoint (Element document_element, Element target_element) {
+    ///ystem.err.println("Find insertion point: " + target_element.getNodeName());
+    String target_element_name = target_element.getNodeName ();
+        
+    // Try to find commands with the same tag.
+    NodeList matching_elements = document_element.getElementsByTagName (target_element_name);
+    // If we found matching elements, then we have our most likely insertion location, so check within for groupings
+    if(matching_elements.getLength () != 0) {
+      ///ystem.err.println("Found matching elements.");
+      // Only CollectionMeta are grouped.
+      if(target_element_name.equals (StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
+	///ystem.err.println("Dealing with collection metadata");
+	// Special case: CollectionMeta can be added at either the start or end of a collection configuration file. However the start position is reserved for special metadata, so if no non-special metadata can be found we must append to the end.
+	// So if the command to be added is special add it immediately after any other special command
+	if(target_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
+	  int index = 0;
+	  Element matched_element = (Element) matching_elements.item (index);
+	  Element sibling_element = (Element) matched_element.getNextSibling ();
+	  while(sibling_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
+	    index++;
+	    matched_element = (Element) matching_elements.item (index);
+	    sibling_element = (Element) matched_element.getNextSibling ();
+	  }
+	  if(sibling_element.getNodeName ().equals (CollectionConfiguration.NEWLINE_ELEMENT)) {
+	    Element newline_element = document_element.getOwnerDocument().createElement (CollectionConfiguration.NEWLINE_ELEMENT);
+	    document_element.insertBefore (newline_element, sibling_element);
+	  }
+	  return sibling_element;
+	}
+	// Otherwise try to find a matching 'name' and add after the last one in that group.
+	else {
+	  int index = 0;
+	  target_element_name = target_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+	  boolean found = false;
+	  // Skip all of the special metadata
+	  Element matched_element = (Element) matching_elements.item (index);
+	  while(matched_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
+	    index++;
+	    matched_element = (Element) matching_elements.item (index);
+	  }
+	  // Begin search
+	  while(!found && matched_element != null) {
+	    if(matched_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
+	      found = true;
+	    }
+	    else {
+	      index++;
+	      matched_element = (Element) matching_elements.item (index);
+	    }
+	  }
+	  // If we found a match, we need to continue checking until we find the last name match.
+	  if(found) {
+	    index++;
+	    Element previous_sibling = matched_element;
+	    Element sibling_element = (Element) matching_elements.item (index);
+	    while(sibling_element != null && sibling_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
+	      previous_sibling = sibling_element;
+	      index++;
+	      sibling_element = (Element) matching_elements.item (index);
+	    }
+	    // Previous sibling now holds the command immediately before where we want to add, so find its next sibling and add to that. In this one case we can ignore new lines!
+	    return previous_sibling.getNextSibling ();
+	  }
+	  // If not found we just add after last metadata element
+	  else {
+	    Element last_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
+	    return last_element.getNextSibling ();
+	  }
+	}
+                
+      }
+      else {
+	///ystem.err.println("Not dealing with collection meta.");
+	Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
+	// One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
+	Node sibling_element = matched_element.getNextSibling ();
+	if(sibling_element != null && sibling_element.getNodeName ().equals (CollectionConfiguration.NEWLINE_ELEMENT)) {
+	  Element newline_element = document_element.getOwnerDocument().createElement (CollectionConfiguration.NEWLINE_ELEMENT);
+	  document_element.insertBefore (newline_element, sibling_element);
+	}
+	return sibling_element; // Note that this may be null
+      }
+    }
+    ///ystem.err.println("No matching elements found.");
+    // Locate where this command is in the ordering
+    int command_index = -1;
+    for(int i = 0; command_index == -1 && i < CollectionConfiguration.COMMAND_ORDER.length; i++) {
+      if(CollectionConfiguration.COMMAND_ORDER[i].equals (target_element_name)) {
+	command_index = i;
+      }
+    }
+    ///ystem.err.println("Command index is: " + command_index);
+    // Now move forward, checking for existing elements in each of the preceeding command orders.
+    int preceeding_index = command_index - 1;
+    ///ystem.err.println("Searching before the target command.");
+    while(preceeding_index >= 0) {
+      matching_elements = document_element.getElementsByTagName (CollectionConfiguration.COMMAND_ORDER[preceeding_index]);
+      // If we've found a match
+      if(matching_elements.getLength () > 0) {
+	// We add after the last element
+	Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
+	// One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
+	Node sibling_element = matched_element.getNextSibling ();
+	if(sibling_element != null && sibling_element.getNodeName ().equals (CollectionConfiguration.NEWLINE_ELEMENT)) {
+	  Element newline_element = document_element.getOwnerDocument().createElement (CollectionConfiguration.NEWLINE_ELEMENT);
+	  document_element.insertBefore (newline_element, sibling_element);
+	}
+	return sibling_element; // Note that this may be null
+      }
+      preceeding_index--;
+    }
+    // If all that fails, we now move backwards through the commands
+    int susceeding_index = command_index + 1;
+    ///ystem.err.println("Searching after the target command.");
+    while(susceeding_index < CollectionConfiguration.COMMAND_ORDER.length) {
+      matching_elements = document_element.getElementsByTagName (CollectionConfiguration.COMMAND_ORDER[susceeding_index]);
+      // If we've found a match
+      if(matching_elements.getLength () > 0) {
+	// We add before the first element
+	Element matched_element = (Element) matching_elements.item (0);
+	// One final quick test. If the matched element is immediately preceeded by a NewLine command, then we insert another NewLine before the matched command, then return this new NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
+	Node sibling_element = matched_element.getPreviousSibling ();
+	if(sibling_element != null && sibling_element.getNodeName ().equals (CollectionConfiguration.NEWLINE_ELEMENT)) {
+	  Element newline_element = document_element.getOwnerDocument().createElement (CollectionConfiguration.NEWLINE_ELEMENT);
+	  document_element.insertBefore (newline_element, sibling_element);
+	}
+	return sibling_element; // Note that this may be null
+      }
+      susceeding_index++;
+    }
+    // Well. Apparently there are no other commands in this collection configuration. So append away...
+    return null;
+  }
+  // From collectionConfig.xml to internal structure:add 'ex.' namespace (if none).
+  // From internal structure to collectionConfig.xml:always peel off 'ex.' namespace (if any), except for format statement
+  //This method parses 'xml_file_doc' into 'dOc'
+  static public void parse(File xml_file, Document dOc) {
+        
+    Document xml_file_doc = XMLTools.parseXMLFile (xml_file);
+    Element fromElement = xml_file_doc.getDocumentElement ();
+    Element toElement = dOc.getDocumentElement ();
+        
+    // It's deliberately set that 'creator', 'maintainer', and 'public' are only in English (as they are just names).
+    // So the following ArrayList have only one element.
+    Node metadataListNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.METADATALIST_STR, 0);
+    if (metadataListNode != null) {
+      ArrayList creator = doMetadataList (dOc, metadataListNode, StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT,
+					  StaticStrings.COLLECTIONMETADATA_CREATOR_STR);
+      ArrayList maintainer = doMetadataList (dOc, metadataListNode,
+					     StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT,
+					     StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR);
+      ArrayList is_public = doMetadataList (dOc, metadataListNode, StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT,
+					    StaticStrings.COLLECTIONMETADATA_PUBLIC_STR);
+            
+      appendArrayList (toElement, creator);
+      appendArrayList (toElement, maintainer);
+      appendArrayList (toElement, is_public);
+    }
+        
+    Node searchNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.SEARCH_STR, 0);
+    String buildtype_value = ((Element)searchNode).getAttribute (StaticStrings.TYPE_ATTRIBUTE);//might be mg|mgpp|lucene
+    Element buildtype = doBuildType (dOc, buildtype_value);
+    appendProperly (toElement, buildtype);
+        
+        
+    Node importNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.IMPORT_STR, 0);
+    if (importNode == null) {
+      System.out.println ("There is no content in the 'import' block.");
+    }
+    if (importNode != null) {
+      //do plugin list nodes
+      Node pluginListNode = XMLTools.getChildByTagNameIndexed ((Element)importNode, StaticStrings.PLUGINLIST_STR, 0);           
+      if (pluginListNode == null) {
+	System.out.println ("There is no pluginlist set.");
+      }
+      if (pluginListNode != null) {
+                
+	doPlugin (dOc, pluginListNode);
+      }
+            
+      //do the plugout element (used by building flax collections)
+      Node plugout = XMLTools.getChildByTagNameIndexed ((Element)importNode, PLUGOUT_ELEMENT, 0);
+      if (plugout != null) {
+	Element to_element = XMLTools.duplicateElement (dOc, (Element)plugout, true);
+	toElement.appendChild (to_element);
+      }
+    }
+        
+    Node browseNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.BROWSE_STR, 0);
+    if (browseNode != null) {
+      if (browseNode == null) {
+	System.out.println ("There is no classifier.");
+      }
+      doClassifier (dOc, browseNode);
+    }
+        
+    Node displayItemListNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.DISPLAYITEMLIST_STR, 0);
+    if (displayItemListNode != null) {
+      ArrayList description = doDisplayItemList (dOc, displayItemListNode, StaticStrings.DESCRIPTION_STR,
+						 StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR);
+      ArrayList smallicon = doDisplayItemList (dOc, displayItemListNode, StaticStrings.SMALLICON_STR,
+					       StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR);
+      ArrayList icon = doDisplayItemList (dOc, displayItemListNode, StaticStrings.ICON_STR,
+					  StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR);
+      ArrayList name = doDisplayItemList (dOc, displayItemListNode, StaticStrings.NAME_STR,
+					  StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR);
+            
+      appendArrayList (toElement, description);
+      appendArrayList (toElement, smallicon);
+      appendArrayList (toElement, icon);
+      appendArrayList (toElement, name);
+    }
+        
+    if (buildtype_value.equalsIgnoreCase ("mg")) {
+      doMGIndexes (dOc, searchNode);
+    }
+    else {
+      doMGPPIndexes (dOc, searchNode);
+    }
+        
+    doDefaultIndex (dOc, searchNode);
+    //doSearchType (dOc, searchNode);
+    doDefaultLevel (dOc, searchNode);
+    doLevel (dOc, searchNode);
+    doIndexOption (dOc, searchNode);
+    doSubcollection (dOc, searchNode);
+    doIndexSubcollection (dOc, searchNode);
+    doIndexLanguage (dOc, searchNode);
+    doDefaultIndexLanguage (dOc, searchNode);
+    doLanguageMetadata (dOc, searchNode);
+    doSearchFormat (dOc, searchNode);
+    doDisplayFormat (dOc, fromElement);
+    doReplaceListRef (dOc, fromElement);
+    doOAIElement (dOc, fromElement);
+        
+  }
+    
+    
+  static public String generateStringVersion(Document doc) {
+    return XMLTools.xmlNodeToString(doc);
+  }
+  
+  static public void save (File collect_config_xml_file, Document doc) {
+        
+    Document collection_config_xml_document = convertInternalToCollectionConfig (doc);
+    String[] nonEscapingTagNames = {StaticStrings.FORMAT_STR};
+    XMLTools.writeXMLFile (collect_config_xml_file, collection_config_xml_document, nonEscapingTagNames);
+       
+  }
+
+  //Convert the internal XML DOM tree (dOc) into that of collectionConfig.xml (skeleton)
+  static private Document convertInternalToCollectionConfig (Document dOc) {
+    //first parse an empty skeleton of xml config file
+    //The aim is to convert the internal structure into this skeleton
+    Document skeleton = XMLTools.parseXMLFile ("xml/CollectionConfig.xml", true);
+    //Element internal = dOc.getDocumentElement();
+    convertMetadataList (dOc, skeleton);
+    convertDisplayItemList (dOc, skeleton);
+    convertBuildType (dOc, skeleton);
+    convertIndex (dOc, skeleton);
+    convertPlugin (dOc, skeleton);//also do the plugout element
+    convertClassifier (dOc, skeleton);
+    convertSubcollectionIndexes (dOc, skeleton);
+    convertLanguages (dOc, skeleton);
+    convertSubcollection (dOc, skeleton);
+    convertSearchType (dOc, skeleton);
+    convertSearchFormat (dOc, skeleton);
+    convertDisplayFormat (dOc, skeleton);
+    convertReplaceListRef (dOc, skeleton);
+    convertOAIElement(dOc, skeleton);
+
+    return skeleton;
+  }
+
+  // Append the elements, which are of Element type, in 'list' to Element 'to'
+  static private void appendArrayList (Element to, ArrayList list) {
+    if (list == null) return;
+        
+    for (int i=0; i<list.size (); i++) {
+      appendProperly (to, (Element)list.get (i));
+    }
+  }
+
+
+  
+}
Index: /gli/trunk/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java
===================================================================
--- /gli/trunk/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java	(revision 20446)
+++ /gli/trunk/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java	(revision 20447)
@@ -32,5 +32,4 @@
 import java.util.*;
 import javax.swing.*;
-import org.greenstone.gatherer.Configuration;
 import org.greenstone.gatherer.DebugStream;
 import org.greenstone.gatherer.Gatherer;
@@ -38,10 +37,6 @@
 import org.greenstone.gatherer.greenstone.LocalLibraryServer;
 import org.greenstone.gatherer.gui.GLIButton;
-import org.greenstone.gatherer.metadata.MetadataElement;
-import org.greenstone.gatherer.metadata.MetadataSetManager;
-import org.greenstone.gatherer.metadata.MetadataTools;
 import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
 import org.greenstone.gatherer.util.DOMTree;
-import org.greenstone.gatherer.util.Codec;
 import org.greenstone.gatherer.util.StaticStrings;
 import org.greenstone.gatherer.util.XMLTools;
@@ -51,3857 +46,434 @@
 /** This class provides access to an xml-type view of the collect.cfg file. This is useful as it allows the manipulation and free form editing of a collect.cfg file while still allowing the various CDM data managers to base themselves directly on this model (whereas they used to be independant ListModels which clobbered the ordering of unparsed commands).
  * @author John Thompson, Greenstone Digital Library, University of Waikato
- * @version 2.3d
  */
 public class CollectionConfiguration {
-    static final private String ENCODING = "UTF-8";
-    static final private String NEWLINE_ELEMENT = "NewLine";
-    static final private String PLUGOUT_ELEMENT = "plugout";//used by building flax collections
-    
-    static private Document document;
-    static private StringBuffer saved_collect_cfg_string_buffer = null;
-    
-    
-    static public Element createElement (String element_name) {
-        return document.createElement (element_name);
-    }
-    
-    
-    /** Find the best insertion position for the given DOM Element. This should try to match command tag, and if found should then try to group by name or type (eg CollectionMeta), or append to end is no such grouping exists (eg Plugins). Failing a command match it will check against the command order for the best insertion location.
-     * @param target_element the command Element to be inserted
-     * @return the Element which the given command should be inserted before, or null to append to end of list
-     */
-    static public Node findInsertionPoint (Element target_element) {
-        ///ystem.err.println("Find insertion point: " + target_element.getNodeName());
-        String target_element_name = target_element.getNodeName ();
-        Element document_element = document.getDocumentElement ();
-        // Try to find commands with the same tag.
-        NodeList matching_elements = document_element.getElementsByTagName (target_element_name);
-        // If we found matching elements, then we have our most likely insertion location, so check within for groupings
-        if(matching_elements.getLength () != 0) {
-            ///ystem.err.println("Found matching elements.");
-            // Only CollectionMeta are grouped.
-            if(target_element_name.equals (StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
-                ///ystem.err.println("Dealing with collection metadata");
-                // Special case: CollectionMeta can be added at either the start or end of a collection configuration file. However the start position is reserved for special metadata, so if no non-special metadata can be found we must append to the end.
-                // So if the command to be added is special add it immediately after any other special command
-                if(target_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-                    int index = 0;
-                    Element matched_element = (Element) matching_elements.item (index);
-                    Element sibling_element = (Element) matched_element.getNextSibling ();
-                    while(sibling_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-                        index++;
-                        matched_element = (Element) matching_elements.item (index);
-                        sibling_element = (Element) matched_element.getNextSibling ();
-                    }
-                    if(sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
-                        Element newline_element = document.createElement (NEWLINE_ELEMENT);
-                        document_element.insertBefore (newline_element, sibling_element);
-                    }
-                    return sibling_element;
-                }
-                // Otherwise try to find a matching 'name' and add after the last one in that group.
-                else {
-                    int index = 0;
-                    target_element_name = target_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-                    boolean found = false;
-                    // Skip all of the special metadata
-                    Element matched_element = (Element) matching_elements.item (index);
-                    while(matched_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-                        index++;
-                        matched_element = (Element) matching_elements.item (index);
-                    }
-                    // Begin search
-                    while(!found && matched_element != null) {
-                        if(matched_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
-                            found = true;
-                        }
-                        else {
-                            index++;
-                            matched_element = (Element) matching_elements.item (index);
-                        }
-                    }
-                    // If we found a match, we need to continue checking until we find the last name match.
-                    if(found) {
-                        index++;
-                        Element previous_sibling = matched_element;
-                        Element sibling_element = (Element) matching_elements.item (index);
-                        while(sibling_element != null && sibling_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
-                            previous_sibling = sibling_element;
-                            index++;
-                            sibling_element = (Element) matching_elements.item (index);
-                        }
-                        // Previous sibling now holds the command immediately before where we want to add, so find its next sibling and add to that. In this one case we can ignore new lines!
-                        return previous_sibling.getNextSibling ();
-                    }
-                    // If not found we just add after last metadata element
-                    else {
-                        Element last_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
-                        return last_element.getNextSibling ();
-                    }
-                }
+  static final public String ENCODING = "UTF-8";
+  static final public String NEWLINE_ELEMENT = "NewLine";
+    
+  static private Document document;
+  static private String saved_config_file_string = null;
+    
+  // may be collec.cfg (GS2) or collectionConfig.xml (GS3)
+  private File collect_config_file;
+  private String collect_config_filename;
+  
+  // This method is initilised in CollectionDesignManager.java constructor
+  public CollectionConfiguration (File collect_config_file) {
+    this.collect_config_file = collect_config_file;
+    this.collect_config_filename = collect_config_file.getName();
+    // parse the XML template
+    document = XMLTools.parseXMLFile ("xml/CollectionConfig.xml", true);
+    String filename = collect_config_filename.toLowerCase ();
+        
+    if (filename.endsWith (".cfg")) {
+      saved_config_file_string = CollectCfgReadWrite.parse (collect_config_file, document);
+    }
+    else if (filename.endsWith (".xml")) {
+      CollectionConfigXMLReadWrite.parse (collect_config_file, document);
+    }
+        
+    //XMLTools.printXMLNode(document.getDocumentElement());
+  }
+
+  static public Element createElement (String element_name) {
+    return document.createElement (element_name);
+  }
+    
+  /** Gives the preferred ordering of commands */
+  static final public String[] COMMAND_ORDER =
+  {StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, StaticStrings.BUILDTYPE_ELEMENT, StaticStrings.PLUGIN_ELEMENT, StaticStrings.INDEXES_ELEMENT, StaticStrings.INDEX_DEFAULT_ELEMENT, StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.INDEXOPTION_DEFAULT_ELEMENT, StaticStrings.LANGUAGES_ELEMENT, StaticStrings.LANGUAGE_DEFAULT_ELEMENT, StaticStrings.LANGUAGE_METADATA_ELEMENT, StaticStrings.SUBCOLLECTION_ELEMENT, StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT, StaticStrings.SUPERCOLLECTION_ELEMENT, StaticStrings.CLASSIFY_ELEMENT, StaticStrings.FORMAT_ELEMENT, StaticStrings.COLLECTIONMETADATA_ELEMENT};
+     
+  /** Find the best insertion position for the given DOM Element. This should try to match command tag, and if found should then try to group by name or type (eg CollectionMeta), or append to end is no such grouping exists (eg Plugins). Failing a command match it will check against the command order for the best insertion location.
+   * @param target_element the command Element to be inserted
+   * @return the Element which the given command should be inserted before, or null to append to end of list
+   */
+  static public Node findInsertionPoint (Element target_element) {
+    ///ystem.err.println("Find insertion point: " + target_element.getNodeName());
+    String target_element_name = target_element.getNodeName ();
+    Element document_element = document.getDocumentElement ();
+    // Try to find commands with the same tag.
+    NodeList matching_elements = document_element.getElementsByTagName (target_element_name);
+    // If we found matching elements, then we have our most likely insertion location, so check within for groupings
+    if(matching_elements.getLength () != 0) {
+      ///ystem.err.println("Found matching elements.");
+      // Only CollectionMeta are grouped.
+      if(target_element_name.equals (StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
+	///ystem.err.println("Dealing with collection metadata");
+	// Special case: CollectionMeta can be added at either the start or end of a collection configuration file. However the start position is reserved for special metadata, so if no non-special metadata can be found we must append to the end.
+	// So if the command to be added is special add it immediately after any other special command
+	if(target_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
+	  int index = 0;
+	  Element matched_element = (Element) matching_elements.item (index);
+	  Element sibling_element = (Element) matched_element.getNextSibling ();
+	  while(sibling_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
+	    index++;
+	    matched_element = (Element) matching_elements.item (index);
+	    sibling_element = (Element) matched_element.getNextSibling ();
+	  }
+	  if(sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
+	    Element newline_element = document.createElement (NEWLINE_ELEMENT);
+	    document_element.insertBefore (newline_element, sibling_element);
+	  }
+	  return sibling_element;
+	}
+	// Otherwise try to find a matching 'name' and add after the last one in that group.
+	else {
+	  int index = 0;
+	  target_element_name = target_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
+	  boolean found = false;
+	  // Skip all of the special metadata
+	  Element matched_element = (Element) matching_elements.item (index);
+	  while(matched_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
+	    index++;
+	    matched_element = (Element) matching_elements.item (index);
+	  }
+	  // Begin search
+	  while(!found && matched_element != null) {
+	    if(matched_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
+	      found = true;
+	    }
+	    else {
+	      index++;
+	      matched_element = (Element) matching_elements.item (index);
+	    }
+	  }
+	  // If we found a match, we need to continue checking until we find the last name match.
+	  if(found) {
+	    index++;
+	    Element previous_sibling = matched_element;
+	    Element sibling_element = (Element) matching_elements.item (index);
+	    while(sibling_element != null && sibling_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
+	      previous_sibling = sibling_element;
+	      index++;
+	      sibling_element = (Element) matching_elements.item (index);
+	    }
+	    // Previous sibling now holds the command immediately before where we want to add, so find its next sibling and add to that. In this one case we can ignore new lines!
+	    return previous_sibling.getNextSibling ();
+	  }
+	  // If not found we just add after last metadata element
+	  else {
+	    Element last_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
+	    return last_element.getNextSibling ();
+	  }
+	}
                 
-            }
-            else {
-                ///ystem.err.println("Not dealing with collection meta.");
-                Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
-                // One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
-                Node sibling_element = matched_element.getNextSibling ();
-                if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
-                    Element newline_element = document.createElement (NEWLINE_ELEMENT);
-                    document_element.insertBefore (newline_element, sibling_element);
-                }
-                return sibling_element; // Note that this may be null
-            }
-        }
-        ///ystem.err.println("No matching elements found.");
-        // Locate where this command is in the ordering
-        int command_index = -1;
-        for(int i = 0; command_index == -1 && i < COMMAND_ORDER.length; i++) {
-            if(COMMAND_ORDER[i].equals (target_element_name)) {
-                command_index = i;
-            }
-        }
-        ///ystem.err.println("Command index is: " + command_index);
-        // Now move forward, checking for existing elements in each of the preceeding command orders.
-        int preceeding_index = command_index - 1;
-        ///ystem.err.println("Searching before the target command.");
-        while(preceeding_index >= 0) {
-            matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[preceeding_index]);
-            // If we've found a match
-            if(matching_elements.getLength () > 0) {
-                // We add after the last element
-                Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
-                // One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
-                Node sibling_element = matched_element.getNextSibling ();
-                if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
-                    Element newline_element = document.createElement (NEWLINE_ELEMENT);
-                    document_element.insertBefore (newline_element, sibling_element);
-                }
-                return sibling_element; // Note that this may be null
-            }
-            preceeding_index--;
-        }
-        // If all that fails, we now move backwards through the commands
-        int susceeding_index = command_index + 1;
-        ///ystem.err.println("Searching after the target command.");
-        while(susceeding_index < COMMAND_ORDER.length) {
-            matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[susceeding_index]);
-            // If we've found a match
-            if(matching_elements.getLength () > 0) {
-                // We add before the first element
-                Element matched_element = (Element) matching_elements.item (0);
-                // One final quick test. If the matched element is immediately preceeded by a NewLine command, then we insert another NewLine before the matched command, then return this new NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
-                Node sibling_element = matched_element.getPreviousSibling ();
-                if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
-                    Element newline_element = document.createElement (NEWLINE_ELEMENT);
-                    document_element.insertBefore (newline_element, sibling_element);
-                }
-                return sibling_element; // Note that this may be null
-            }
-            susceeding_index++;
-        }
-        // Well. Apparently there are no other commands in this collection configuration. So append away...
-        return null;
-    }
-    
-    
-    static public NodeList getElementsByTagName (String element_name) {
-        return document.getDocumentElement ().getElementsByTagName (element_name);
-    }
-    
-    
-  static public String toString (Element command_element) {
-        String command_element_name = command_element.getNodeName ();
-        if(command_element_name.equals (StaticStrings.CLASSIFY_ELEMENT)) {
-            return classifyToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.FORMAT_ELEMENT)) {
-            return formatToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.INDEXES_ELEMENT)) {
-            return indexesToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.INDEX_DEFAULT_ELEMENT)) {
-            return indexDefaultToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.LANGUAGES_ELEMENT)) {
-            return languagesToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.LANGUAGE_DEFAULT_ELEMENT)) {
-            return languageDefaultToString (command_element);
-        }
-        else if (command_element_name.equals (StaticStrings.LANGUAGE_METADATA_ELEMENT)) {
-            return languageMetadataToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.INDEXOPTIONS_ELEMENT)) {
-            return indexOptionsToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT)) {
-            return indexOptionDefaultToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
-	  return metadataToString (command_element); 
-        }
-        else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT)) {
-	  return metadataToString (command_element); 
-        }
-        else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT)) {
-            return metadataToString (command_element); 
-        }
-        else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT)) {
-            return metadataToString (command_element); 
-        }
-        else if (command_element_name.equals (StaticStrings.BUILDTYPE_ELEMENT)) {
-            return metadataToString (command_element); 
-        }
-        else if(command_element_name.equals (StaticStrings.PLUGIN_ELEMENT)) {
-            return pluginToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.SUBCOLLECTION_ELEMENT)) {
-            return subcollectionToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT)) {
-            return subcollectionDefaultIndexToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT)) {
-            return subcollectionIndexesToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.SUPERCOLLECTION_ELEMENT)) {
-            return supercollectionToString (command_element);
-        }
-        else if(command_element_name.equals (StaticStrings.UNKNOWN_ELEMENT)) {
-            return unknownToString (command_element);
-        }
-        return "";
-    }
-    
-    /** Parses arguments from a tokenizer and returns a HashMap of mappings. The tricky bit here is that not all entries in the HashMap are name->value pairs, as some arguments are boolean and are turned on by their presence. Arguments are denoted by a '-' prefix.
-     * @param tokenizer a CommandTokenizer based on the unconsumed portion of a command string
-     * @return a HashMap containing the arguments parsed
-     */
-    static public HashMap parseArguments (CommandTokenizer tokenizer) {
-        HashMap arguments = new HashMap ();
-        String name = null;
-        String value = null;
-        while(tokenizer.hasMoreTokens () || name != null) {
-            // First we retrieve a name if we need one.
-            if(name == null) {
-                name = tokenizer.nextToken ();
-            }
-            // Now we attempt to retrieve a value
-            if(tokenizer.hasMoreTokens ()) {
-                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.
-		// 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;
-                }
-                // Otherwise we have a typical name->value pair ready to go
-                else {
-                    arguments.put (name, value);
-                    name = null;
-                }
-            }
-            // Otherwise its a binary flag
-            else {
-                arguments.put (name, null);
-                name = null;
-            }
-        }
-        return arguments;
-    }
-    
-    /** Gives the preferred ordering of commands */
-    static final private String[] COMMAND_ORDER =
-    {StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, StaticStrings.BUILDTYPE_ELEMENT, StaticStrings.PLUGIN_ELEMENT, StaticStrings.INDEXES_ELEMENT, StaticStrings.INDEX_DEFAULT_ELEMENT, StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.INDEXOPTION_DEFAULT_ELEMENT, StaticStrings.LANGUAGES_ELEMENT, StaticStrings.LANGUAGE_DEFAULT_ELEMENT, StaticStrings.LANGUAGE_METADATA_ELEMENT, StaticStrings.SUBCOLLECTION_ELEMENT, StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT, StaticStrings.SUPERCOLLECTION_ELEMENT, StaticStrings.CLASSIFY_ELEMENT, StaticStrings.FORMAT_ELEMENT, StaticStrings.COLLECTIONMETADATA_ELEMENT};
-    
-    /** ************************** Public Data Members ***************************/
-    
-    /** ************************** Private Data Members ***************************/
-    
-    private File collect_cfg_file;
-    
-    /** ************************** Public Methods ***************************/
-    
-    
-    /** This debug facility shows the currently loaded collect.cfg or CollectConfig.xml file as a DOM tree. */
-    public void display () {
-        JDialog dialog = new JDialog (Gatherer.g_man, "Collection Configuration", false);
-        dialog.setSize (400,400);
-        JPanel content_pane = (JPanel) dialog.getContentPane ();
-        final DOMTree tree = new DOMTree (document);
-        JButton refresh_button = new GLIButton ("Refresh Tree");
-        refresh_button.addActionListener (new ActionListener () {
-            public void actionPerformed (ActionEvent event) {
-                tree.setDocument (document);
-            }
-        });
-        content_pane.setBorder (BorderFactory.createEmptyBorder (5,5,5,5));
-        content_pane.setLayout (new BorderLayout ());
-        content_pane.add (new JScrollPane (tree), BorderLayout.CENTER);
-        content_pane.add (refresh_button, BorderLayout.SOUTH);
-        dialog.setVisible (true);
-    }
-    
-    
-    public Element getCreator () {
-        Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, null, null);
-        element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_CREATOR_STR);
-        element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
-        return element;
-    }
-    
-    public Element getDocumentElement () {
-        return document.getDocumentElement ();
-    }
-    
-    public File getFile () {
-        return collect_cfg_file;
-    }
-    
-    /** Retrieve or create the languages Element. */
-    public Element getLanguages () {
-        return getOrCreateElementByTagName (StaticStrings.LANGUAGES_ELEMENT, null, null);
-    }
-    
-    public Element getLanguageMetadata () {
-        return getOrCreateElementByTagName (StaticStrings.LANGUAGE_METADATA_ELEMENT, null, null);
-    }
-    
-    public Element getLevels () {
-        return getOrCreateElementByTagName (StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVELS_STR);
-    }
-    
-    public Element getLevelDefault () {
-        return getOrCreateElementByTagName (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVEL_DEFAULT_STR);
-    }
-    
-    public Element getIndexOptions () {
-        return getOrCreateElementByTagName (StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.INDEXOPTIONS_STR);
-    }
-    
-    
-    public Element getMaintainer () {
-        Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, null, null);
-        element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR);
-        element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
-        return element;
-    }
-    
-    /** Retrieve or create the indexes Element. Note that this method behaves differently from the other getBlah methods, in that it also has to keep in mind that indexes come in two flavours, MG and MGPP. */
-    public Element getMGIndexes () {
-        return getOrCreateElementByTagName (StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
-    }
-    
-    public Element getMGPPIndexes () {
-        return getOrCreateElementByTagName (StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
-    }
-    
-    public Element getPublic () {
-        Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, null, null);
-        element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_PUBLIC_STR);
-        element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
-        return element;
-    }
-    
-    public Element getBuildType () {
-        Element element = getOrCreateElementByTagName (StaticStrings.BUILDTYPE_ELEMENT, null, null);
-        element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
-        element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
-        return element;
-        
-    }
-    
-    /** Retrieve or create the subindexes Element. */
-    public Element getSubIndexes () {
-        return getOrCreateElementByTagName (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, null, null);
-    }
-    
-    /** Retrieve or create the supercollections Element. */
-    public Element getSuperCollection () {
-        return getOrCreateElementByTagName (StaticStrings.SUPERCOLLECTION_ELEMENT, null, null);
-    }
-    
-    public boolean ready () {
-        return document != null;
-    }
-    
-    
-    
-    
-    /** ************************** Private Methods ***************************/
-    
-    static private String classifyToString (Element command_element) {
-        StringBuffer text = new StringBuffer (StaticStrings.CLASSIFY_STR);
-        text.append (StaticStrings.TAB_CHARACTER);
-        text.append (command_element.getAttribute (StaticStrings.TYPE_ATTRIBUTE));
-        NodeList option_elements = command_element.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
-        int option_elements_length = option_elements.getLength ();
-        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);
-	
-	      //	      value_str = modifyMetadataArgumentValue(value_str);
-	      if (value_str.length () > 0) {
-		text.append (StaticStrings.SPACE_CHARACTER);
-		if(value_str.indexOf (StaticStrings.SPACE_CHARACTER) != -1) {
-		    // enclose in quotes
-		    text.append(StaticStrings.SPEECH_CHARACTER);
-		    text.append(value_str);
-		    text.append(StaticStrings.SPEECH_CHARACTER);
-		} else {
-		    
-		    text.append(value_str);
-		}
-	      }
-              
-	      value_str = null;
-            }
-            option_element = null;
-        }
-        option_elements = null;
-        return text.toString ();
-    }
-    
-    static private String formatToString (Element command_element) {
-        StringBuffer text = new StringBuffer (StaticStrings.FORMAT_STR);
-        text.append (StaticStrings.SPACE_CHARACTER);
-        text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-        text.append (StaticStrings.SPACE_CHARACTER);
-        String value_str = command_element.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
-        if(value_str.length () != 0) {
-            text.append (value_str);
-        }
-        else {
-            // Remember to encode format string to Greenstone specification
-            value_str = Codec.transform (XMLTools.getValue (command_element), Codec.DOM_TO_GREENSTONE);
-            text.append (StaticStrings.SPEECH_CHARACTER);
-            text.append (value_str);
-            text.append (StaticStrings.SPEECH_CHARACTER);
-        }
-        value_str = null;
-        return text.toString ();
-    }
-    
-    /** Retrieve or create the indexes Element. */
-    static private Element getOrCreateElementByTagName (String name, String conditional_attribute, String required_value) {
-        Element document_element = document.getDocumentElement ();
-        NodeList elements = document_element.getElementsByTagName (name);
-        int elements_length = elements.getLength ();
-        if(elements_length > 0) {
-            if(conditional_attribute == null) {
-                document_element = null;
-                return (Element) elements.item (0);
-            }
-            else {
-                for(int i = 0; i < elements_length; i++) {
-                    Element element = (Element) elements.item (i);
-                    if(element.getAttribute (conditional_attribute).equals (required_value)) {
-                        document_element = null;
-                        return element;
-                    }
-                    element = null;
-                }
-            }
-        }
-        // Create the element
-        Element element = document.createElement (name);
-        // If there was a property set it
-        if(conditional_attribute != null) {
-            element.setAttribute (conditional_attribute, required_value);
-        }
-        Node target_node = findInsertionPoint (element);
-        if(target_node != null) {
-            document_element.insertBefore (element, target_node);
-        }
-        else {
-            document_element.appendChild (element);
-        }
-        document_element = null;
-        return element;
-    }
-    
-    static private String indexesToString (Element command_element) {
-        boolean comment_only = false;
-        StringBuffer text = new StringBuffer ("");
-        if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-            text.append ("#");
-            comment_only = true;
-        }
-        text.append (StaticStrings.INDEX_STR);
-        text.append (StaticStrings.TAB_CHARACTER);
-        if(!comment_only) {
-            text.append (StaticStrings.TAB_CHARACTER);
-        }
-        NodeList index_elements = command_element.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
-        if (index_elements.getLength () == 0) { // no indexes
-            return "";
-        }
-        // For each index, write its level, a colon, then concatenate its child content elements into a single comma separated list
-        int index_elements_length = index_elements.getLength ();
-        for(int j = 0; j < index_elements_length; j++) {
-            Element index_element = (Element) index_elements.item (j);
-            String level_str = index_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE);
-            if(level_str.length () > 0) {
-                text.append (level_str);
-                text.append (StaticStrings.COLON_CHARACTER);
-            }
-            NodeList content_elements = index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
-            int content_elements_length = content_elements.getLength ();
-            // Don't output anything if no indexes are set
-            if(content_elements_length == 0) {
-                return null;
-            }
-            for(int k = 0; k < content_elements_length; k++) {
-                Element content_element = (Element) content_elements.item (k);
-                String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-                text.append (name_str);
-                name_str = null;
-                if(k < content_elements_length - 1) {
-                    text.append (StaticStrings.COMMA_CHARACTER);
-                }
-                content_element = null;
-            }
-            if(j < index_elements_length - 1) {
-                text.append (StaticStrings.SPACE_CHARACTER);
-            }
-            content_elements = null;
-            index_element = null;
-        }
-        index_elements = null;
-        return text.toString ();
-    }
-    
-    static private String indexDefaultToString (Element command_element) {
-        StringBuffer text = new StringBuffer ("");
-        if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-            text.append ("#");
-        }
-        text.append (StaticStrings.INDEX_DEFAULT_STR);
-        text.append (StaticStrings.TAB_CHARACTER);
-        if (!command_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE).equals ("")) {
-            text.append (command_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE));
-            text.append (StaticStrings.COLON_CHARACTER);
-        }
-        NodeList content_elements = command_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
-        int content_elements_length = content_elements.getLength ();
-        for(int j = 0; j < content_elements_length; j++) {
-            Element content_element = (Element) content_elements.item (j);
-            String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            text.append (name_str);
-            name_str = null;
-            if(j < content_elements_length - 1) {
-                text.append (StaticStrings.COMMA_CHARACTER);
-            }
-            content_element = null;
-        }
-        content_elements = null;
-        return text.toString ();
-    }
-    
-    static private String languagesToString (Element command_element) {
-        StringBuffer text = new StringBuffer (StaticStrings.LANGUAGES_STR);
-        text.append (StaticStrings.TAB_CHARACTER);
-        // Retrieve all the languages and write them out in a space separated list
-        NodeList language_elements = command_element.getElementsByTagName (StaticStrings.LANGUAGE_ELEMENT);
-        int language_elements_length = language_elements.getLength ();
-        if(language_elements_length == 0) {
-            return null;
-        }
-        for(int j = 0; j < language_elements_length; j++) {
-            Element language_element = (Element) language_elements.item (j);
-            text.append (language_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-            if(j < language_elements_length - 1) {
-                text.append (StaticStrings.SPACE_CHARACTER);
-            }
-        }
-        return text.toString ();
-    }
-    
-    static private String languageDefaultToString (Element command_element) {
-        StringBuffer text = new StringBuffer (StaticStrings.LANGUAGE_DEFAULT_STR);
-        text.append (StaticStrings.TAB_CHARACTER);
-        text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-        return text.toString ();
-    }
-    
-    static private String languageMetadataToString (Element command_element) {
-        if (!command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-            return "";
-        }
-        StringBuffer text = new StringBuffer (StaticStrings.LANGUAGE_METADATA_STR);
-        text.append (StaticStrings.TAB_CHARACTER);
-        String name_str = command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-        text.append (name_str);
-        return text.toString ();
-    }
-    
-    static private String indexOptionsToString (Element command_element) {
-        StringBuffer text = new StringBuffer ("");
-        if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-            text.append ("#");
-        }
-        text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-        text.append (StaticStrings.TAB_CHARACTER);
-        NodeList content_elements = command_element.getElementsByTagName (StaticStrings.INDEXOPTION_ELEMENT);
-        int content_elements_length = content_elements.getLength ();
-        // Don't output anything if no options are set.
-        if(content_elements_length == 0) {
-            return null;
-        }
-        for(int i = 0; i < content_elements_length; i++) {
-            Element content_element = (Element) content_elements.item (i);
-            text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-            text.append (StaticStrings.SPACE_CHARACTER);
-        }
-        return text.substring (0, text.length () - 1);
-    }
-    
-    static private String indexOptionDefaultToString (Element command_element) {
-        // Don't bother if there is no value
-        if (command_element.getAttribute (StaticStrings.VALUE_ATTRIBUTE).equals ("")) {
-            return "";
-        }
-        StringBuffer text = new StringBuffer ("");
-        if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-            text.append ("#");
-        }
-        text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-        text.append (StaticStrings.TAB_CHARACTER);
-        text.append (command_element.getAttribute (StaticStrings.VALUE_ATTRIBUTE));
-        return text.toString ();
-    }
-    
-    static private String metadataToString (Element command_element) {
-        // lets first check the value - if its empty, don't bother sticking it in the config file
-        String value_str = XMLTools.getValue (command_element);
-        if (value_str.equals ("")) {
-            return "";
-        }
-        boolean special = false;
-        
-        StringBuffer text = new StringBuffer ("");
-        String name_str = command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-        // If the name is one of the special four, we don't write the collectionmeta first. Note maintainer and buildtype are singled out for 'prittying' reasons.
-        if(name_str.equals (StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR)|| name_str.equals (StaticStrings.BUILDTYPE_STR) ) {
-            text.append (name_str);
-            text.append (StaticStrings.TAB_CHARACTER);
-            special = true;
-        }
-        else if (name_str.equals (StaticStrings.COLLECTIONMETADATA_CREATOR_STR) || name_str.equals (StaticStrings.COLLECTIONMETADATA_PUBLIC_STR) ) {
-            text.append (name_str);
-            text.append (StaticStrings.TAB_CHARACTER);
-            text.append (StaticStrings.TAB_CHARACTER);
-            special = true;
-        }
-        else {
-            text.append (StaticStrings.COLLECTIONMETADATA_STR);
-            text.append (StaticStrings.TAB_CHARACTER);
-            text.append (name_str);
-            text.append (StaticStrings.SPACE_CHARACTER);
-            String language_str = command_element.getAttribute (StaticStrings.LANGUAGE_ATTRIBUTE);
-            text.append (StaticStrings.LBRACKET_CHARACTER);
-            text.append (StaticStrings.LANGUAGE_ARGUMENT);
-            text.append (language_str);
-            text.append (StaticStrings.RBRACKET_CHARACTER);
-            text.append (StaticStrings.SPACE_CHARACTER);
-        }
-        name_str = null;
-        
-	// decode the value from XML to a form for config file
-	value_str = Codec.transform (value_str, Codec.DOM_TO_GREENSTONE);
-        
-        // We don't wrap the email addresses in quotes, nor the other special metadata
-        if(special) {
-            text.append (value_str);
-        }
-        else {
-            text.append (StaticStrings.SPEECH_CHARACTER);
-            text.append (value_str);
-            text.append (StaticStrings.SPEECH_CHARACTER);
-        }
-        value_str = null;
-        return text.toString ();
-    }
-    
-    /** Parse a collect.cfg into a DOM model representation.
-     * note we are ignoring 2.39 compatibility now. */
-    private void parse (File collect_cfg_file) {
-        // hack for pre 2.71 compatibility - we need to add in a
-        // build type if there is not one there
-        boolean search_types_parsed = false;
-        boolean build_types_parsed = false;
-        try {
-            saved_collect_cfg_string_buffer = new StringBuffer ();
-            
-            Element collect_cfg_element = document.getDocumentElement ();
-            // Read in the file one command at a time.
-            InputStream istream = new FileInputStream (collect_cfg_file);
-            Reader in_reader = new InputStreamReader (istream, ENCODING);
-            BufferedReader in = new BufferedReader (in_reader);
-            String command_str = null;
-            while((command_str = in.readLine ()) != null) {
-                saved_collect_cfg_string_buffer.append (command_str + "\n");
-                
-                boolean append_element = true;
-                Element command_element = null;
-                // A command may be broken over several lines.
-                command_str = command_str.trim ();
-                boolean eof = false;
-                while(!eof && command_str.endsWith (StaticStrings.NEWLINE_CHARACTER)) {
-                    String next_line = in.readLine ();
-                    if(next_line != null) {
-                        next_line = next_line.trim ();
-                        if(next_line.length () > 0) {
-                            // Remove the new line character
-                            command_str = command_str.substring (0, command_str.lastIndexOf (StaticStrings.NEWLINE_CHARACTER));
-                            // And append the next line, which due to the test above must be non-zero length
-                            command_str = command_str + next_line;
-                        }
-                        next_line = null;
-                    }
-                    // If we've reached the end of the file theres nothing more we can do
-                    else {
-                        eof = true;
-                    }
-                }
-                // If there is still a new line character, then we remove it and hope for the best
-                if(command_str.endsWith (StaticStrings.NEWLINE_CHARACTER)) {
-                    command_str = command_str.substring (0, command_str.lastIndexOf (StaticStrings.NEWLINE_CHARACTER));
-                }
-                // Now we've either got a command to parse...
-                if(command_str.length () != 0) {
-                    // Start trying to figure out what it is
-                    //StringTokenizer tokenizer = new StringTokenizer(command_str);
-                    // Instead of a standard string tokenizer I'm going to use the new version of CommandTokenizer, which is not only smart enough to correctly notice speech marks and correctly parse them out, but now also takes the input stream so it can rebuild tokens that stretch over several lines.
-                    CommandTokenizer tokenizer = new CommandTokenizer (command_str, in);
-                    String command_type = tokenizer.nextToken ().toLowerCase ();
-                    // Why can't you switch on strings eh? We pass it to the various subparsers who each have a bash at parsing the command. If none can parse the command, an unknown element is created
-                    if(command_element == null && command_type.equals (StaticStrings.CLASSIFY_STR)) {
-                        command_element = parseClassify (command_str);
-                    }
-                    if(command_element == null && command_type.equals (StaticStrings.FORMAT_STR)) {
-                        command_element = parseFormat (tokenizer); // Revised to handle multiple lines
-                    }
-                    if(command_element == null && (command_type.equals (StaticStrings.INDEX_STR)  || command_type.equals (StaticStrings.COMMENTED_INDEXES_STR))) {
-                        command_element = parseIndex (command_str);
-                    }
-                    if(command_element == null && (command_type.equals (StaticStrings.INDEX_DEFAULT_STR) || command_type.equals (StaticStrings.COMMENTED_INDEX_DEFAULT_STR))) {
-                        
-                        command_element = parseIndexDefault (command_str);
-                    }
-                    if(command_element == null && command_type.equals (StaticStrings.LANGUAGES_STR)) {
-                        command_element = parseLanguage (command_str);
-                    }
-                    if(command_element == null && command_type.equals (StaticStrings.LANGUAGE_DEFAULT_STR)) {
-                        command_element = parseLanguageDefault (command_str);
-                    }
-                    if (command_element == null && command_type.equals (StaticStrings.LANGUAGE_METADATA_STR)) {
-                        command_element = parseLanguageMetadata (command_str);
-                    }
-                    if(command_element == null && command_type.equals (StaticStrings.LEVELS_STR)) {
-                        command_element = parseIndexOptions (command_str, StaticStrings.LEVELS_STR, true);
-                    }
-                    if (command_element == null && command_type.equals (StaticStrings.COMMENTED_LEVELS_STR)) {
-                        command_element = parseIndexOptions (command_str, StaticStrings.LEVELS_STR, false);
-                    }
-                    if(command_element == null && command_type.equals (StaticStrings.LEVEL_DEFAULT_STR)) {
-                        command_element = parseIndexOptionDefault (command_str, StaticStrings.LEVEL_DEFAULT_STR, true);
-                    }
-                    if(command_element == null && command_type.equals (StaticStrings.COMMENTED_LEVEL_DEFAULT_STR)) {
-                        command_element = parseIndexOptionDefault (command_str, StaticStrings.LEVEL_DEFAULT_STR, false);
-                    }
-                    if (command_element == null && command_type.equals (StaticStrings.INDEXOPTIONS_STR)) {
-                        command_element = parseIndexOptions (command_str, StaticStrings.INDEXOPTIONS_STR, true);
-                    }
-                    if (command_element == null && command_type.equals (StaticStrings.COMMENTED_INDEXOPTIONS_STR)) {
-                        command_element = parseIndexOptions (command_str, StaticStrings.INDEXOPTIONS_STR, false);
-                    }
-                    if(command_element == null && command_type.equals (StaticStrings.COLLECTIONMETADATA_STR)) {
-                        command_element = parseMetadata (tokenizer); // Revised to handle multiple lines
-                    }
-                    if(command_element == null && (command_type.equals (StaticStrings.COLLECTIONMETADATA_PUBLIC_STR) || command_type.equals (StaticStrings.COLLECTIONMETADATA_CREATOR_STR) || command_type.equals (StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR) || command_type.equals (StaticStrings.BUILDTYPE_STR))) {
-                        command_element = parseMetadataSpecial (command_str);
-                        // pre 2.71 hack
-                        if (command_type.equals (StaticStrings.BUILDTYPE_STR)) {
-                            build_types_parsed = true;
-                        }
-                    }
-                    if(command_element == null && command_type.equals (StaticStrings.PLUGIN_STR)) {
-                        command_element = parsePlugin (command_str);
-                    }
-                    // leave here for backwards compatibility
-                    if(command_element == null && command_type.equals (StaticStrings.SEARCHTYPE_STR)) {
-                        command_element = parseSearchType (command_str);
-                        // pre 2.71 hack
-                        search_types_parsed = true;
-                        
-                    }
-                    if(command_element == null && command_type.equals (StaticStrings.SUBCOLLECTION_STR)) {
-                        command_element = parseSubCollection (command_str);
-                    }
-                    if(command_element == null && command_type.equals (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_STR)) {
-                        command_element = parseSubCollectionDefaultIndex (command_str);
-                    }
-                    if(command_element == null && command_type.equals (StaticStrings.SUBCOLLECTION_INDEX_STR)) {
-                        command_element = parseSubCollectionIndex (command_str);
-                    }
-                    if(command_element == null && (command_type.equals (StaticStrings.SUPERCOLLECTION_STR) || command_type.equals (StaticStrings.CCS_STR))) {
-                        command_element = parseSuperCollection (command_str);
-                    }
-                    // Doesn't match any known type
-                    command_type = null;
-                    if(command_element == null) {
-                        // No-one knows what to do with this command, so we create an Unknown command element
-                        command_element = document.createElement (StaticStrings.UNKNOWN_ELEMENT);
-                        XMLTools.setValue (command_element, command_str);
-                    }
-                }
-                // Or an empty line to remember for later
-                else {
-                    command_element = document.createElement (NEWLINE_ELEMENT);
-                }
-                // Now command element shouldn't be null so we append it to the collection config DOM, but only if we haven't been told not to add it
-                //if(append_element) {
-                collect_cfg_element.appendChild (command_element);
-                //}
-            }
-            if (!build_types_parsed) {
-                String buildtype_type = BuildTypeManager.BUILD_TYPE_MG;
-                if (search_types_parsed) {
-                    buildtype_type = BuildTypeManager.BUILD_TYPE_MGPP;
-                }
-                Element command_element = parseMetadataSpecial (StaticStrings.BUILDTYPE_STR+"  "+buildtype_type);
-                Node target_node = findInsertionPoint (command_element);
-                if(target_node != null) {
-                    collect_cfg_element.insertBefore (command_element, target_node);
-                }
-                else {
-                    collect_cfg_element.appendChild (command_element);
-                }
-                
-            }
-        }
-        catch(Exception exception) {
-            DebugStream.println ("Error in CollectionConfiguration.parse(java.io.File): " + exception);
-            DebugStream.printStackTrace (exception);
-        }
-    }
-    
-    
-    private Element parseClassify (String command_str) {
-        Element command_element = null;
-        try {
-            CommandTokenizer tokenizer = new CommandTokenizer (command_str);
-            // Check the token count. The token count from a command tokenizer isn't guarenteed to be correct, but it does give the maximum number of available tokens according to the underlying StringTokenizer (some of which may actually be append together by the CommandTokenizer as being a single argument).
-            if(tokenizer.countTokens () >= 2) {  // Must support "classify Phind" (no args)
-                command_element = document.createElement (StaticStrings.CLASSIFY_ELEMENT);
-                // First token is classify
-                tokenizer.nextToken ();
-                // The next token is the classifier type
-                command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, tokenizer.nextToken ());
-                // Now we parse out the remaining arguments into a hashmapping from name to value
-                HashMap arguments = parseArguments (tokenizer);
-                // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
-                Iterator names = arguments.keySet ().iterator ();
-                while(names.hasNext ()) {
-                    String name = (String) names.next ();
-                    String value = (String) arguments.get (name); // Can be null
-                    // The metadata argument gets added as the content attribute
-		    /*                   if (name.equals (StaticStrings.METADATA_ARGUMENT) && value != null) {
-                        // Add the extracted namespace onto un-namespaced metadata names
-                        StringTokenizer string_tokenizer = new StringTokenizer (value, ",");
-                        value = "";
-                        while (string_tokenizer.hasMoreElements ()) {
-                            String token = (String) string_tokenizer.nextElement ();
-                            
-                            if (token.indexOf (StaticStrings.NS_SEP) == -1) {
-                                token = StaticStrings.EXTRACTED_NAMESPACE + token;
-                            }
-                            else {
-                                MetadataElement metadata_element = MetadataTools.getMetadataElementWithName (token);
-                                if (metadata_element != null) {
-                                    token = metadata_element.getDisplayName ();
-                                }
-                            }
-                            
-                            if (!value.equals ("")) {
-                                value = value + ",";
-                            }
-                            value = value + token;
-                        }
-			}*/
-                    // Everything else is an Option Element
-                    Element option_element = document.createElement (StaticStrings.OPTION_ELEMENT);
-                    option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name.substring (1));
-                    if(value != null) {
-                        // Remove any speech marks appended in strings containing whitespace
-                        if(value.startsWith (StaticStrings.SPEECH_CHARACTER) && value.endsWith (StaticStrings.SPEECH_CHARACTER)) {
-                            value = value.substring (1, value.length () - 1);
-                        }
-                        XMLTools.setValue (option_element, value);
-                    }
-                    option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-                    command_element.appendChild (option_element);
-                    option_element = null;
-                    name = null;
-                    value = null;
-                }
-                names = null;
-                arguments = null;
-            }
-            tokenizer = null;
-        }
-        catch(Exception error) {
-        }
-        return command_element;
-    }
-    
-    private Element parseFormat (CommandTokenizer tokenizer) {
-        Element command_element = null;
-        try {
-            command_element = document.createElement (StaticStrings.FORMAT_ELEMENT);
-            String name_str = tokenizer.nextToken ();
-            String value_str = tokenizer.nextToken ();
-            if(name_str != null && value_str != null) {
-                command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-                // If the value is true or false we add it as an attribute
-                if(value_str.equalsIgnoreCase (StaticStrings.TRUE_STR) || value_str.equalsIgnoreCase (StaticStrings.FALSE_STR)) {
-                    command_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, value_str.toLowerCase ());
-                }
-                // Otherwise it gets added as a text node
-                else {
-                    // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
-                    value_str = Codec.transform (value_str, Codec.GREENSTONE_TO_DOM);
-                    XMLTools.setValue (command_element, value_str);
-                }
-            }
-            else {
-                command_element = null;
-            }
-            name_str = null;
-            value_str = null;
-        }
-        catch (Exception exception) {
-            DebugStream.printStackTrace (exception);
-            command_element = null;
-        }
-        return command_element;
-    }
-    
-    private Element parseIndex (String command_str) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            String command = tokenizer.nextToken ();
-            command_element = document.createElement (StaticStrings.INDEXES_ELEMENT);
-            command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, (command.equals (StaticStrings.INDEX_STR) ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
-            command = null;
-            if(!tokenizer.hasMoreTokens ()) {
-                
-                // there are no indexes
-                command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
-                command_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR); // for now
-                tokenizer = null;
-                return command_element;
-            }
-            
-            while(tokenizer.hasMoreTokens ()) {
-                Element index_element = document.createElement (StaticStrings.INDEX_ELEMENT);
-                String index_str = tokenizer.nextToken ();
-                // There are two types of index we have to consider. Old G2.38 and earlier use level:source tuplets while G2.39+ have just a single, non-comma separated list where order is important.
-                boolean old_index;
-                if(index_str.indexOf (StaticStrings.COLON_CHARACTER) != -1) {
-                    old_index = true;
-                    index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE, index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER)));
-                    index_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
-                    command_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
-                }
-                else {
-                    command_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
-                    old_index = false;
-                }
-                StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
-                while(content_tokenizer.hasMoreTokens ()) {
-                    Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
-                    String content_str = content_tokenizer.nextToken ();
-                    // 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.indexOf (StaticStrings.NS_SEP) == -1) {
-                        if(content_str.equals (StaticStrings.TEXT_STR) || (!old_index && content_str.equals (StaticStrings.ALLFIELDS_STR))) {
-                            // Our special strings are OK.
-                        }
-                        else {
-                            content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
-                        }
-                    }
-                    content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
-                    index_element.appendChild (content_element);
-                    content_element = null;
-                }
-                content_tokenizer = null;
-                index_str = null;
-                command_element.appendChild (index_element);
-                index_element = null;
-            }
-            tokenizer = null;
-        }
-        catch (Exception exception) {
-            exception.printStackTrace ();
-        }
-        return command_element;
-    }
-    
-    private Element parseIndexDefault (String command_str) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            if(tokenizer.countTokens () >= 2) {
-                command_element = document.createElement (StaticStrings.INDEX_DEFAULT_ELEMENT);
-                command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken ()).equals (StaticStrings.INDEX_DEFAULT_STR) ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
-                String index_str = tokenizer.nextToken ();
-                String level="";
-                if (index_str.indexOf (StaticStrings.COLON_CHARACTER) !=-1) {
-                    level =  index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER));
-                }
-                
-                command_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE,level);
-                
-                String content_str = index_str;
-                
-                if (index_str.indexOf (StaticStrings.COLON_CHARACTER) !=-1) {
-                    content_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
-                }
-                
-                StringTokenizer content_tokenizer = new StringTokenizer (content_str, StaticStrings.COMMA_CHARACTER);
-                while(content_tokenizer.hasMoreTokens ()) {
-                    Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
-                    content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken ());
-                    command_element.appendChild (content_element);
-                    content_element = null;
-                }
-                content_tokenizer = null;
-                content_str = null;
-                content_str = null;
-                index_str = null;
-            }
-            tokenizer = null;
-        }
-        catch (Exception exception) {
-        }
-        return command_element;
-    }
-    
-    private Element parseLanguage (String command_str) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            tokenizer.nextToken ();
-            if(tokenizer.hasMoreTokens ()) {
-                command_element = document.createElement (StaticStrings.LANGUAGES_ELEMENT);
-                while(tokenizer.hasMoreTokens ()) {
-                    Element language_element = document.createElement (StaticStrings.LANGUAGE_ELEMENT);
-                    language_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
-                    command_element.appendChild (language_element);
-                    language_element = null;
-                }
-            }
-            tokenizer = null;
-        }
-        catch (Exception exception) {
-        }
-        return command_element;
-    }
-    
-    private Element parseLanguageDefault (String command_str) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            if(tokenizer.countTokens () >= 2) {
-                command_element = document.createElement (StaticStrings.LANGUAGE_DEFAULT_ELEMENT);
-                tokenizer.nextToken ();
-                String default_language_str = tokenizer.nextToken ();
-                command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, default_language_str);
-                command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-                default_language_str = null;
-            }
-            tokenizer = null;
-        }
-        catch (Exception exception) {
-        }
-        return command_element;
-    }
-    
-    private Element parseLanguageMetadata (String command_str) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            if(tokenizer.countTokens () >= 2) {
-                command_element = document.createElement (StaticStrings.LANGUAGE_METADATA_ELEMENT);
-                tokenizer.nextToken ();
-                String language_metadata_str = tokenizer.nextToken ();
-                if (language_metadata_str.indexOf (StaticStrings.NS_SEP) == -1) {
-                    language_metadata_str = StaticStrings.EXTRACTED_NAMESPACE + language_metadata_str;
-                }
-                command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, language_metadata_str);
-                command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-                language_metadata_str = null;
-            }
-            tokenizer = null;
-            
-        }
-        catch (Exception exception) {
-        }
-        return command_element;
-    }
-    
-    private Element parseIndexOptions (String command_str, String type, boolean assigned) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            // First token is command type
-            String command = tokenizer.nextToken ();
-            if(tokenizer.hasMoreTokens ()) {
-                command_element = document.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
-                command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE,type);
-                command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
-                while(tokenizer.hasMoreTokens ()) {
-                    Element option_element = document.createElement (StaticStrings.INDEXOPTION_ELEMENT);
-                    option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
-                    command_element.appendChild (option_element);
-                    option_element = null;
-                }
-            }
-            command = null;
-        }
-        catch(Exception exception) {
-        }
-        return command_element;
-    }
-    
-    private Element parseIndexOptionDefault (String command_str, String type, boolean assigned) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            // First token is command type
-            String command = tokenizer.nextToken ();
-            if(tokenizer.hasMoreTokens ()) {
-                command_element = document.createElement (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT);
-                command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR)); // is it commented out or not?
-                command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, type);
-                command_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, tokenizer.nextToken ());
-            }
-            
-            tokenizer = null;
-        }
-        catch (Exception exception) {
-        }
-        return command_element;
-    }
-    
-    private Element parseMetadata (CommandTokenizer tokenizer) {
-        Element command_element = null;
-        try {
-            command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
-            String name_str = tokenizer.nextToken ();
-            String value_str = tokenizer.nextToken ();
-            if(name_str != null && value_str != null) {
-                String language_str = Configuration.getLanguage ();
-                // Check if the value string is actually a language string
-                if(value_str.startsWith (StaticStrings.LBRACKET_CHARACTER) && value_str.endsWith (StaticStrings.RBRACKET_CHARACTER)) {
-                    language_str = value_str.substring (value_str.indexOf (StaticStrings.LANGUAGE_ARGUMENT) + 2, value_str.length () - 1);
-                    value_str = tokenizer.nextToken ();
-                }
-                if(value_str != null) {
-                    // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
-                    value_str = Codec.transform (value_str, Codec.GREENSTONE_TO_DOM);
-                    command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-                    command_element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, language_str);
-                    command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-                    XMLTools.setValue (command_element, value_str);
-                }
-                else {
-                    command_element = null;
-                }
-                language_str = null;
-            }
-            else {
-                command_element = null;
-            }
-            name_str = null;
-            value_str = null;
-        }
-        catch (Exception exception) {
-            DebugStream.printStackTrace (exception);
-            command_element = null;
-        }
-        return command_element;
-    }
-    
-    private Element parseMetadataSpecial (String command_str) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            if(tokenizer.countTokens () >= 2) {
-                String name_str = tokenizer.nextToken ();
-                String value_str = tokenizer.nextToken ();
-                if (name_str.equals (StaticStrings.COLLECTIONMETADATA_CREATOR_STR)) {
-                    command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT);
-                }
-                else if(name_str.equals (StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR)) {
-                    command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT);
-                }
-                else if(name_str.equals (StaticStrings.COLLECTIONMETADATA_PUBLIC_STR)) {
-                    command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT);
-                }
-                else if (name_str.equals (StaticStrings.BUILDTYPE_STR)) {
-                    command_element = document.createElement (StaticStrings.BUILDTYPE_ELEMENT);
-                }
-                if(command_element != null) {
-                    command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-                    command_element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
-                    command_element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
-                    command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-                    if(value_str.startsWith (StaticStrings.SPEECH_CHARACTER) && value_str.endsWith (StaticStrings.SPEECH_CHARACTER)) {
-                        value_str = value_str.substring (1, value_str.length () - 1);
-                    }
-                    XMLTools.setValue (command_element, value_str);
-                }
-                value_str = null;
-                name_str = null;
-            }
-            tokenizer = null;
-        }
-        catch (Exception exception) {
-        }
-        return command_element;
-    }
-    
-    private Element parsePlugin (String command_str) {
-        Element command_element = null;
-        try {
-            CommandTokenizer tokenizer = new CommandTokenizer (command_str);
-            // Check the token count. The token count from a command tokenizer isn't guarenteed to be correct, but it does give the maximum number of available tokens according to the underlying StringTokenizer (some of which may actually be append together by the CommandTokenizer as being a single argument).
-            if(tokenizer.countTokens () >= 2) {
-                command_element = document.createElement (StaticStrings.PLUGIN_ELEMENT);
-                // First token is plugin
-                tokenizer.nextToken ();
-                // 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
-                HashMap arguments = parseArguments (tokenizer);
-                // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
-                // also watch out for the deprecated -use_metadata_files option to RecPlug and remove it
-                Iterator names = arguments.keySet ().iterator ();
-                while(names.hasNext ()) {
-                    String name = (String) names.next ();
-                    String value = (String) arguments.get (name); // Can be null
-                    
-                    if(type.equals (StaticStrings.RECPLUG_STR) && name.substring (1).equals (StaticStrings.USE_METADATA_FILES_ARGUMENT)) {
-                        continue; // ignore this option
-                    }
-                    Element option_element = document.createElement (StaticStrings.OPTION_ELEMENT);
-                    option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name.substring (1));
-                    option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-                    if(value != null) {
-                        // Remove any speech marks appended in strings containing whitespace
-                        if(value.startsWith (StaticStrings.SPEECH_CHARACTER) && value.endsWith (StaticStrings.SPEECH_CHARACTER)) {
-                            value = value.substring (1, value.length () - 1);
-                        }
-                        if(name.equals (StaticStrings.METADATA_ARGUMENT)) {
-                            // The metadata argument must be the fully qualified name of a metadata element, so if it doesn't yet have a namespace, append the extracted metadata namespace.
-                            if(value.indexOf (StaticStrings.NS_SEP) == -1) {
-                                value = StaticStrings.EXTRACTED_NAMESPACE + value;
-                            }
-                        }
-                        XMLTools.setValue (option_element, value);
-                    }
-                    command_element.appendChild (option_element);
-                    option_element = null;
-                    name = null;
-                    value = null;
-                }
-                
-                type = null;
-                names = null;
-                arguments = null;
-            }
-            tokenizer = null;
-        }
-        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;
-    }
-    
-    /* search types are now handled as formats - leave this here to convert in case we have an old config file */
-    private Element parseSearchType (String command_str) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            // First token is command type (searchtype)
-            tokenizer.nextToken ();
-            if(tokenizer.hasMoreTokens ()) {
-                command_element = document.createElement (StaticStrings.FORMAT_ELEMENT);
-                command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, "SearchTypes");
-                String value = tokenizer.nextToken ();
-                while(tokenizer.hasMoreTokens ()) {
-                    value += ","+tokenizer.nextToken ();
-                }
-                value = Codec.transform (value, Codec.GREENSTONE_TO_DOM);
-                XMLTools.setValue (command_element, value);
-            }
-        }
-        catch(Exception exception) {
-        }
-        return command_element;
-    }
-    
-    private Element parseSubCollection (String command_str) {
-        Element command_element = null;
-        try {
-            CommandTokenizer tokenizer = new CommandTokenizer (command_str);
-            if(tokenizer.countTokens () >= 3) {
-                command_element = document.createElement (StaticStrings.SUBCOLLECTION_ELEMENT);
-                // First token is command type
-                tokenizer.nextToken ();
-                // Then subcollection identifier
-                command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
-                // Then finally the pattern used to build the subcollection partition
-                String full_pattern_str = tokenizer.nextToken ();
-                // Set inclusion/exclusion flag and remove any exclamation mark
-                boolean exclusion = full_pattern_str.startsWith (StaticStrings.EXCLAMATION_CHARACTER);
-                if (exclusion) {
-                    full_pattern_str = full_pattern_str.substring (1, full_pattern_str.length ());
-                    command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, StaticStrings.EXCLUDE_STR);
-                }
-                else {
-                    command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, StaticStrings.INCLUDE_STR);
-                }
-
-                // 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) {
-                        content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
-                    }
-                    command_element.setAttribute (StaticStrings.CONTENT_ATTRIBUTE, content_str);
-                    XMLTools.setValue (command_element, results[1]);
-                    if (results.length >= 3) {
-                        command_element.setAttribute (StaticStrings.OPTIONS_ATTRIBUTE, results[2]);
-                    }
-                }
-            }
-        }
-        catch(Exception exception) {
-            exception.printStackTrace ();
-        }
-        return command_element;
-    }
-    
-    private Element parseSubCollectionDefaultIndex (String command_str) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            if(tokenizer.countTokens () == 2) {
-                command_element = document.createElement (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
-                tokenizer.nextToken ();
-                //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
-                String content_str = tokenizer.nextToken ();
-                StringTokenizer content_tokenizer = new StringTokenizer (content_str, StaticStrings.COMMA_CHARACTER);
-                while(content_tokenizer.hasMoreTokens ()) {
-                    Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
-                    content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken ());
-                    command_element.appendChild (content_element);
-                    content_element = null;
-                }
-                content_tokenizer = null;
-                content_str = null;
-            }
-            tokenizer = null;
-        }
-        catch(Exception exception) {
-        }
-        return command_element;
-    }
-    
-    private Element parseSubCollectionIndex (String command_str) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            tokenizer.nextToken ();
-            if(tokenizer.hasMoreTokens ()) {
-                command_element = document.createElement (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT);
-            }
-            while(tokenizer.hasMoreTokens ()) {
-                Element subcollectionindex_element = document.createElement (StaticStrings.INDEX_ELEMENT);
-                //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
-                String content_str = tokenizer.nextToken ();
-                StringTokenizer content_tokenizer = new StringTokenizer (content_str, StaticStrings.COMMA_CHARACTER);
-                while(content_tokenizer.hasMoreTokens ()) {
-                    Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
-                    content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken ());
-                    subcollectionindex_element.appendChild (content_element);
-                    content_element = null;
-                }
-                content_tokenizer = null;
-                content_str = null;
-                command_element.appendChild (subcollectionindex_element);
-                subcollectionindex_element = null;
-            }
-            tokenizer = null;
-        }
-        catch (Exception exception) {
-        }
-        return command_element;
-    }
-    
-    private Element parseSuperCollection (String command_str) {
-        Element command_element = null;
-        try {
-            StringTokenizer tokenizer = new StringTokenizer (command_str);
-            if(tokenizer.countTokens () >= 3) {
-                command_element = document.createElement (StaticStrings.SUPERCOLLECTION_ELEMENT);
-                tokenizer.nextToken ();
-                while(tokenizer.hasMoreTokens ()) {
-                    Element collection_element = document.createElement (StaticStrings.COLLECTION_ELEMENT);
-                    collection_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
-                    command_element.appendChild (collection_element);
-                    collection_element = null;
-                }
-            }
-            tokenizer = null;
-        }
-        catch(Exception exception) {
-        }
-        return command_element;
-    }
-    
-    static private String pluginToString (Element command_element) {
-        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);
-	      // turn display name into proper name
-	      //value_str = modifyMetadataArgumentValue(value_str);
-	      if (value_str.length () > 0) {
-		text.append (StaticStrings.SPACE_CHARACTER);
-		if(value_str.indexOf (StaticStrings.SPACE_CHARACTER) != -1) {
-		    // enclose in quotes
-		    text.append(StaticStrings.SPEECH_CHARACTER);
-		    text.append(value_str);
-		    text.append(StaticStrings.SPEECH_CHARACTER);
-		} else {
-		    
-		    text.append(value_str);
-		}
-	      }
-	      
-	      value_str = null;
-	    }
-	    option_element = null;
-	  }
-	}
-	option_elements = null;
-	
-	return text.toString ();
-    }
-
-    // Convert metadata element names to internal names, and remove extracted metadata namespaces
-    /*  static private String modifyMetadataArgumentValue(String value_str) {
-    if (value_str.length () == 0) {
-      return value_str;
-    }
-    
-    // final true arg to return delims as tokens
-    StringTokenizer string_tokenizer = new StringTokenizer (value_str, ",;", true);
-    StringBuffer value_buffer = new StringBuffer ();
-    while (string_tokenizer.hasMoreElements ()) {
-      String raw_token = (String) string_tokenizer.nextElement ();
-      String token = raw_token.trim ();
-      boolean modified_token = false;
-      // not a delimiter token
-      if (!raw_token.equals(",") && !raw_token.equals(";")) {
-	  //MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName (token);
-	  //if (metadata_element != null) {
-	  //token = metadata_element.getFullName ();
-	  //modified_token = true;
-	  //}
-	
-	//	if (token.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
-	// token = token.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
-	// modified_token = true;
-	//}
-      }
-      if (modified_token) {
-	value_buffer.append (token);
+      }
+      else {
+	///ystem.err.println("Not dealing with collection meta.");
+	Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
+	// One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
+	Node sibling_element = matched_element.getNextSibling ();
+	if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
+	  Element newline_element = document.createElement (NEWLINE_ELEMENT);
+	  document_element.insertBefore (newline_element, sibling_element);
+	}
+	return sibling_element; // Note that this may be null
+      }
+    }
+    ///ystem.err.println("No matching elements found.");
+    // Locate where this command is in the ordering
+    int command_index = -1;
+    for(int i = 0; command_index == -1 && i < COMMAND_ORDER.length; i++) {
+      if(COMMAND_ORDER[i].equals (target_element_name)) {
+	command_index = i;
+      }
+    }
+    ///ystem.err.println("Command index is: " + command_index);
+    // Now move forward, checking for existing elements in each of the preceeding command orders.
+    int preceeding_index = command_index - 1;
+    ///ystem.err.println("Searching before the target command.");
+    while(preceeding_index >= 0) {
+      matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[preceeding_index]);
+      // If we've found a match
+      if(matching_elements.getLength () > 0) {
+	// We add after the last element
+	Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
+	// One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
+	Node sibling_element = matched_element.getNextSibling ();
+	if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
+	  Element newline_element = document.createElement (NEWLINE_ELEMENT);
+	  document_element.insertBefore (newline_element, sibling_element);
+	}
+	return sibling_element; // Note that this may be null
+      }
+      preceeding_index--;
+    }
+    // If all that fails, we now move backwards through the commands
+    int susceeding_index = command_index + 1;
+    ///ystem.err.println("Searching after the target command.");
+    while(susceeding_index < COMMAND_ORDER.length) {
+      matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[susceeding_index]);
+      // If we've found a match
+      if(matching_elements.getLength () > 0) {
+	// We add before the first element
+	Element matched_element = (Element) matching_elements.item (0);
+	// One final quick test. If the matched element is immediately preceeded by a NewLine command, then we insert another NewLine before the matched command, then return this new NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
+	Node sibling_element = matched_element.getPreviousSibling ();
+	if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
+	  Element newline_element = document.createElement (NEWLINE_ELEMENT);
+	  document_element.insertBefore (newline_element, sibling_element);
+	}
+	return sibling_element; // Note that this may be null
+      }
+      susceeding_index++;
+    }
+    // Well. Apparently there are no other commands in this collection configuration. So append away...
+    return null;
+  }
+    
+    
+  static public NodeList getElementsByTagName (String element_name) {
+    return document.getDocumentElement ().getElementsByTagName (element_name);
+  }
+       
+  public Element getDocumentElement () {
+    return document.getDocumentElement ();
+  }
+    
+  /** This debug facility shows the currently loaded collect.cfg or CollectConfig.xml file as a DOM tree. */
+  public void display () {
+    JDialog dialog = new JDialog (Gatherer.g_man, "Collection Configuration", false);
+    dialog.setSize (400,400);
+    JPanel content_pane = (JPanel) dialog.getContentPane ();
+    final DOMTree tree = new DOMTree (document);
+    JButton refresh_button = new GLIButton ("Refresh Tree");
+    refresh_button.addActionListener (new ActionListener () {
+	public void actionPerformed (ActionEvent event) {
+	  tree.setDocument (document);
+	}
+      });
+    content_pane.setBorder (BorderFactory.createEmptyBorder (5,5,5,5));
+    content_pane.setLayout (new BorderLayout ());
+    content_pane.add (new JScrollPane (tree), BorderLayout.CENTER);
+    content_pane.add (refresh_button, BorderLayout.SOUTH);
+    dialog.setVisible (true);
+  }
+    
+        
+    
+  public File getFile () {
+    return collect_config_file;
+  }
+    
+  public Element getCreator () {
+    Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, null, null);
+    element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_CREATOR_STR);
+    element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+    return element;
+  }
+
+  public Element getMaintainer () {
+    Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, null, null);
+    element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR);
+    element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+    return element;
+  }
+
+  /** Retrieve or create the languages Element. */
+  public Element getLanguages () {
+    return getOrCreateElementByTagName (StaticStrings.LANGUAGES_ELEMENT, null, null);
+  }
+    
+  public Element getLanguageMetadata () {
+    return getOrCreateElementByTagName (StaticStrings.LANGUAGE_METADATA_ELEMENT, null, null);
+  }
+    
+  public Element getLevels () {
+    return getOrCreateElementByTagName (StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVELS_STR);
+  }
+    
+  public Element getLevelDefault () {
+    return getOrCreateElementByTagName (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVEL_DEFAULT_STR);
+  }
+    
+  public Element getIndexOptions () {
+    return getOrCreateElementByTagName (StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.INDEXOPTIONS_STR);
+  }
+    
+       
+  /** Retrieve or create the indexes Element. Note that this method behaves differently from the other getBlah methods, in that it also has to keep in mind that indexes come in two flavours, MG and MGPP. */
+  public Element getMGIndexes () {
+    return getOrCreateElementByTagName (StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
+  }
+    
+  public Element getMGPPIndexes () {
+    return getOrCreateElementByTagName (StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
+  }
+    
+  public Element getPublic () {
+    Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, null, null);
+    element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_PUBLIC_STR);
+    element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+    return element;
+  }
+    
+  public Element getBuildType () {
+    Element element = getOrCreateElementByTagName (StaticStrings.BUILDTYPE_ELEMENT, null, null);
+    element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
+    element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+    return element;
+        
+  }
+    
+  /** Retrieve or create the subindexes Element. */
+  public Element getSubIndexes () {
+    return getOrCreateElementByTagName (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, null, null);
+  }
+    
+  /** Retrieve or create the supercollections Element. */
+  public Element getSuperCollection () {
+    return getOrCreateElementByTagName (StaticStrings.SUPERCOLLECTION_ELEMENT, null, null);
+  }
+    
+  public boolean ready () {
+    return document != null;
+  }
+    
+    
+    
+    
+  /** ************************** Private Methods ***************************/
+    
+  
+  /** Retrieve or create the indexes Element. */
+  static private Element getOrCreateElementByTagName (String name, String conditional_attribute, String required_value) {
+    Element document_element = document.getDocumentElement ();
+    NodeList elements = document_element.getElementsByTagName (name);
+    int elements_length = elements.getLength ();
+    if(elements_length > 0) {
+      if(conditional_attribute == null) {
+	document_element = null;
+	return (Element) elements.item (0);
+      }
+      else {
+	for(int i = 0; i < elements_length; i++) {
+	  Element element = (Element) elements.item (i);
+	  if(element.getAttribute (conditional_attribute).equals (required_value)) {
+	    document_element = null;
+	    return element;
+	  }
+	  element = null;
+	}
+      }
+    }
+    // Create the element
+    Element element = document.createElement (name);
+    // If there was a property set it
+    if(conditional_attribute != null) {
+      element.setAttribute (conditional_attribute, required_value);
+    }
+    Node target_node = findInsertionPoint (element);
+    if(target_node != null) {
+      document_element.insertBefore (element, target_node);
+    }
+    else {
+      document_element.appendChild (element);
+    }
+    document_element = null;
+    return element;
+  }
+    
+
+
+ 
+
+  /** Write the text to the buffer. This is used so we don't have to worry about storing intermediate String values just so we can calaulate length and offset.
+   * @param writer the BufferedWriter to which the str will be written
+   * @param str the String to be written
+   */
+  private void write (BufferedWriter writer, String str)
+    throws IOException {
+    writer.write (str, 0, str.length ());
+  }
+    
+
+  public void saveIfNecessary () {
+    
+    // Generate a string version of internal document
+    String config_file_string = null;
+    if (Gatherer.GS3) {
+      config_file_string = CollectionConfigXMLReadWrite.generateStringVersion(document);
+    } else {
+      config_file_string = CollectCfgReadWrite.generateStringVersion(document);
+    }
+    // compare to saved version
+    if (saved_config_file_string != null) {
+      if (saved_config_file_string.equals(config_file_string)) {
+	DebugStream.println (collect_config_filename +" file hasn't changed so no save necessary...");
+	return;
+      }
+    }
+    
+    // We need to save...
+    DebugStream.println (collect_config_filename +" file has changed, saving now...");
+
+       
+    // If we're using the Local Library we must release the collection before writing to the collect.cfg file
+    String collection_name = CollectionManager.getLoadedCollectionName ();
+    boolean collection_released = false;
+    if (Gatherer.c_man.built () && LocalLibraryServer.isRunning () == true) {
+      // Release the collection
+      LocalLibraryServer.releaseCollection (collection_name);
+      collection_released = true;
+    }
+        
+    // Make a backup of the existing config file
+    if (collect_config_file.exists ()) {
+      String config_filename;
+      String backup_filename;
+      if (Gatherer.GS3) {
+	config_filename = Utility.COLLECTION_CONFIG_XML;
+	backup_filename = Utility.COLLECTION_CONFIG_BAK;
       } else {
-	// we may have had whitespace etc that was part of the string
-	value_buffer.append (raw_token);
-      }
-    }
-    
-    
-    if(value_buffer.length () == 0) {
-      return "";
-    }
-    if(value_str.indexOf (StaticStrings.SPACE_CHARACTER) == -1) {
-      return value_buffer.toString();
-    }
-    
-    // it must contain a space, so we surround the value with quotes
-    value_buffer.insert(0, StaticStrings.SPEECH_CHARACTER);
-    value_buffer.append(StaticStrings.SPEECH_CHARACTER);
-    return value_buffer.toString();
-
-    }*/
-    
-    static private String searchtypeToString (Element command_element) {
-        if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-            StringBuffer text = new StringBuffer (StaticStrings.SEARCHTYPE_STR);
-            text.append (StaticStrings.TAB_CHARACTER);
-            NodeList search_elements = command_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
-            int search_elements_length = search_elements.getLength ();
-            for(int i = 0; i < search_elements_length; i++) {
-                Element search_element = (Element) search_elements.item (i);
-                text.append (search_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-                text.append (StaticStrings.SPACE_CHARACTER);
-            }
-            return text.substring (0, text.length () - 1);
-        }
-        else {
-            return null;
-        }
-    }
-    
-    static private String subcollectionToString (Element command_element) {
-        StringBuffer text = new StringBuffer (StaticStrings.SUBCOLLECTION_STR);
-        text.append (StaticStrings.SPACE_CHARACTER);
-        text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-        text.append (StaticStrings.SPACE_CHARACTER);
-        text.append (StaticStrings.TAB_CHARACTER);
-        text.append (StaticStrings.SPEECH_CHARACTER);
-        if(command_element.getAttribute (StaticStrings.TYPE_ATTRIBUTE).equals (StaticStrings.EXCLUDE_STR)) {
-            text.append (StaticStrings.EXCLAMATION_CHARACTER);
-        }
-        text.append (command_element.getAttribute (StaticStrings.CONTENT_ATTRIBUTE));
-        text.append (StaticStrings.SEPARATOR_CHARACTER);
-        text.append (XMLTools.getValue (command_element));
-        text.append (StaticStrings.SEPARATOR_CHARACTER);
-        String options_str = command_element.getAttribute (StaticStrings.OPTIONS_ATTRIBUTE);
-        if(options_str.length () > 0) {
-            text.append (options_str);
-        }
-        options_str = null;
-        text.append (StaticStrings.SPEECH_CHARACTER);
-        return text.toString ();
-    }
-    
-    static private String subcollectionDefaultIndexToString (Element command_element) {
-        StringBuffer text = new StringBuffer (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_STR);
-        text.append (StaticStrings.TAB_CHARACTER);
-        NodeList content_elements = command_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
-        int content_elements_length = content_elements.getLength ();
-        for(int j = 0; j < content_elements_length; j++) {
-            Element content_element = (Element) content_elements.item (j);
-            text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-            if(j < content_elements_length - 1) {
-                text.append (StaticStrings.COMMA_CHARACTER);
-            }
-        }
-        return text.toString ();
-    }
-    
-    static private String subcollectionIndexesToString (Element command_element) {
-        StringBuffer text = new StringBuffer (StaticStrings.SUBCOLLECTION_INDEX_STR);
-        text.append (StaticStrings.TAB_CHARACTER);
-        // Retrieve all of the subcollection index partitions
-        NodeList subcollectionindex_elements = command_element.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
-        int subcollectionindex_elements_length = subcollectionindex_elements.getLength ();
-        if(subcollectionindex_elements_length == 0) {
-            return null;
-        }
-        for(int j = 0; j < subcollectionindex_elements_length; j++) {
-            Element subcollectionindex_element = (Element) subcollectionindex_elements.item (j);
-            NodeList content_elements = subcollectionindex_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
-            int content_elements_length = content_elements.getLength ();
-            for(int k = 0; k < content_elements_length; k++) {
-                Element content_element = (Element) content_elements.item (k);
-                text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-                if(k < content_elements_length - 1) {
-                    text.append (StaticStrings.COMMA_CHARACTER);
-                }
-            }
-            if(j < subcollectionindex_elements_length - 1) {
-                text.append (StaticStrings.SPACE_CHARACTER);
-            }
-        }
-        return text.toString ();
-    }
-    
-    static private String supercollectionToString (Element command_element) {
-        NodeList content_elements = command_element.getElementsByTagName (StaticStrings.COLLECTION_ELEMENT);
-        int content_elements_length = content_elements.getLength ();
-        if(content_elements_length > 1) {
-            StringBuffer text = new StringBuffer (StaticStrings.SUPERCOLLECTION_STR);
-            text.append (StaticStrings.TAB_CHARACTER);
-            for(int j = 0; j < content_elements_length; j++) {
-                Element content_element = (Element) content_elements.item (j);
-                text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
-                if(j < content_elements_length - 1) {
-                    text.append (StaticStrings.SPACE_CHARACTER);
-                }
-            }
-            return text.toString ();
-        }
-        return null;
-    }
-    
-    static private String unknownToString (Element command_element) {
-        return XMLTools.getValue (command_element);
-    }
-    
-    /** Write the text to the buffer. This is used so we don't have to worry about storing intermediate String values just so we can calaulate length and offset.
-     * @param writer the BufferedWriter to which the str will be written
-     * @param str the String to be written
-     */
-    private void write (BufferedWriter writer, String str)
-    throws IOException {
-        writer.write (str, 0, str.length ());
-    }
-    
-    /** ********************************************************************************************************
-        The code from this point below are used for greenstone 3 collection configuration, i.e., read ColletionConfig.xml
-     * into the internal DOM tree, and convert the internal DOM tree back to CollectionConfig.xml.
-     *
-    Methods named 'doXXXX' are for convert collectionConfig.xml into the internal configuration xml structure;
-    Methods named 'convertXXXX' are for convert the internal configuration xml structure back to collectionConfig.xml.
-    ************************************************************************************************************ */
-    
-    /**Arguments:  metadataListNode->the 'displayItemList' element in collectionConfig.xml
-                name_value->the value of the 'name' attribute of 'index' element;
-                att_value->the value of the 'name' attribute of 'displayItem' element
-    return:     an ArrayList of the contructed 'CollectionMetadata' elements
-    */
-    private ArrayList doDisplayItemList (Document to, Node displayListNode, String att_value, String name_value) {
-        Element toElement = to.getDocumentElement ();
-        ArrayList display_item_list = new ArrayList ();
-        ArrayList item_list = XMLTools.getNamedElementList ((Element)displayListNode,
-        StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, att_value);
-        if (item_list == null) {
-            return null;
-        }
-        
-        for (int i=0; i<item_list.size (); i++) {
-            Element item = (Element)item_list.get (i);
-            String text = XMLTools.getNodeText (item);
-            
-            //If there is nothing to display, don't bother creating the element
-            if (text == "") {
-                continue;
-            }
-            //get the value in 'lang=value'
-            String lang = item.getAttribute (StaticStrings.LANG_STR);
-            
-            Element e = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
-            e.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-            e.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_value);
-            e.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
-            XMLTools.setNodeText (e, text);
-            display_item_list.add (e);
-        }
-        return display_item_list;
-    }
-    
-    private ArrayList doMetadataList (Document to, Node metadataListNode, String ele_name, String att_value) {
-        Element toElement = to.getDocumentElement ();
-        ArrayList metadata_list = new ArrayList ();
-        
-        ArrayList item_list = XMLTools.getNamedElementList ((Element)metadataListNode,
-        StaticStrings.METADATA_STR, StaticStrings.NAME_ATTRIBUTE, att_value);
-        if (item_list == null) {
-            return null;
-        }
-        
-        for (int i=0; i<item_list.size (); i++) {
-            Element item = (Element)item_list.get (i);
-            String text = XMLTools.getNodeText (item);
-            
-            //If there is nothing to display, don't bother creating the element
-            if (text == "") {
-                continue;
-            }
-            //get the value in 'lang=value'
-            String lang = item.getAttribute (StaticStrings.LANG_STR);
-            
-            Element element = to.createElement (ele_name);
-            element.setAttribute (StaticStrings.NAME_ATTRIBUTE, att_value);
-            element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
-            element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-            element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
-            XMLTools.setNodeText (element, text);
-            
-            metadata_list.add (element);
-        }
-        return metadata_list;
-    }
-    // 'to' is the internal structure
-    private void doMGIndexes (Document to, Node searchNode) {
-        Element toElement = to.getDocumentElement ();
-        Element indexes_element = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
-        indexes_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-        indexes_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
-        
-        NodeList index_children = ((Element)searchNode).getElementsByTagName (StaticStrings.INDEX_LOW_STR);//index
-        int num_nodes = index_children.getLength ();
-        
-        for (int i=0; i<num_nodes; i++) {
-            Element e = (Element)index_children.item (i);
-            String index_str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            String index_str_display = index_str;//used for creating collectionmetadata for this index
-            Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
-            
-            // For mg, it's the 'Old G2.38 and earlier' that use level:source tuplets, but we double check it anyway
-            boolean old_index = true;
-            if(index_str.indexOf (StaticStrings.COLON_CHARACTER) == -1) {
-                // It doesn't contain ':' character
-                System.err.println ("Something is wrong! the index should be level:source tuplets.");
-                old_index = false;
-            }
-            else {
-                // Handling 'index' element
-                index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE,
-                index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER)));
-                index_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
-                
-                //Each index may have a list of comma-separated strings.
-                //split them into 'content' elements in the internal structure
-                StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
-                //index_str = "";
-                while(content_tokenizer.hasMoreTokens ()) {
-                    // Replace index_str to be qualified name, eg. dc.Subject and keywords insread of dc.Subject.
-                    
-                    
-                    Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
-                    String content_str = content_tokenizer.nextToken ();
-                    // 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.indexOf (StaticStrings.NS_SEP) == -1) {
-                        if(content_str.equals (StaticStrings.TEXT_STR) ||
-                        (!old_index && content_str.equals (StaticStrings.ALLFIELDS_STR))) {
-                            // in this case, do nothing
-                        }
-                        else {
-                            content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
-                        }
-                    }
-                    
-                    content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
-                    index_element.appendChild (content_element);
-                    content_element = null;
-                } 	// while ends
-                
-                indexes_element.appendChild (index_element);
-                
-                // Handling 'displayItem' elements and Constructing 'collectionmetadata' elements
-                // Use the fully qualified index names
-                ArrayList collectionmetadata_list = doDisplayItemList (to, e, StaticStrings.NAME_ATTRIBUTE, index_str_display);
-                appendArrayList (toElement, collectionmetadata_list);
-            } //else ends
-        } //for loop ends
-        appendProperly (toElement, indexes_element);
-        
-        //***//
-        // create another set of <indexes> which will be used when user switches to MGPP/LUCENE
-        // i.e. we build a default index set for a start
-        
-        String []index_strs =
-        {StaticStrings.TEXT_STR,
-         StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.TITLE_ELEMENT,
-         StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.SOURCE_ELEMENT};
-         
-         Element mgpp_indexes = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
-         mgpp_indexes.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
-         mgpp_indexes.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
-         for (int i=0; i<index_strs.length; i++) {
-             Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
-             Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
-             content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_strs[i]);
-             index_element.appendChild (content_element);
-             mgpp_indexes.appendChild (index_element);
-             
-             // Contructing 'collectionmetadata' elements for 'mgpp' indexes
-             Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
-             collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-             collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_strs[i]);
-             collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
-             if (index_strs[i].indexOf (StaticStrings.NS_SEP) != -1) {
-                 index_strs[i] = index_strs[i].substring (index_strs[i].indexOf (StaticStrings.NS_SEP) + 1);
-             }
-             XMLTools.setNodeText (collectionmetadata, index_strs[i]);
-             
-             appendProperly (toElement, collectionmetadata);
-             
-         }
-         appendProperly (toElement, mgpp_indexes);
-    }
-    
-    //This is actually doing indexes for both mgpp and lucene
-    private void doMGPPIndexes (Document to, Node searchNode) {
-        Element toElement = to.getDocumentElement ();
-        Element indexes_element = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
-        indexes_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-        indexes_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
-        
-        NodeList index_children = ((Element)searchNode).getElementsByTagName (StaticStrings.INDEX_LOW_STR);//index
-        int num_nodes = index_children.getLength ();
-        
-        for (int i=0; i<num_nodes; i++) {
-            
-            Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
-            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 
-            
-            // Handling 'index' element
-            // Double check to make sure it's not colon separated style index.
-            boolean old_index = false;
-            if(index_str.indexOf (StaticStrings.COLON_CHARACTER) != -1) {
-                System.err.println ("Something is wrong! the index should NOT be level:source tuplets style.");
-                old_index = true;
-            }
-            //Each index may have a list of comma-separated strings.
-            //split them into 'content' elements in the internal structure
-            StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
-            //index_str = "";
-            while(content_tokenizer.hasMoreTokens ()) {
-                // Replace index_str to be qualified name, eg. dc.Subject and keywords insread of dc.Subject.             
-                
-                Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
-                String content_str = content_tokenizer.nextToken ();
-                // 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.indexOf (StaticStrings.NS_SEP) == -1) {
-                    if(content_str.equals (StaticStrings.TEXT_STR)) {
-                        // in this case, do nothing
-                    }
-                    else {
-                        content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
-                    }
-                }
-                content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
-                index_element.appendChild (content_element);
-                content_element = null;
-            } //while ends
-            
-            indexes_element.appendChild (index_element);
-            
-            
-            index_element = null;
-            
-            // Handling 'displayItem' element of this 'index' element
-            // 'e' is the parent element 'index' of 'displayItem' element
-            ArrayList collectionmetadata_list = doDisplayItemList (to, e, StaticStrings.NAME_ATTRIBUTE, index_str_display);
-            appendArrayList (toElement, collectionmetadata_list);
-            
-            
-        } // for loop ends
-        toElement.appendChild (indexes_element);
-        
-        // create another set of <indexes> which will be used when user switches to MG
-        // i.e. we build a default index set for a start
-        Element mg_indexes = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
-        mg_indexes.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
-        mg_indexes.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
-        
-        //put the namespace '.ex' as prefix to the indexes
-        String []index_strs =
-        {StaticStrings.TEXT_STR,
-         StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.TITLE_ELEMENT,
-         StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.SOURCE_ELEMENT};
-         for (int i=0; i<index_strs.length; i++) {
-             Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
-             index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE, StaticStrings.DOCUMENT_STR);
-             Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
-             content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_strs[i]);
-             index_element.appendChild (content_element);
-             
-             mg_indexes.appendChild (index_element);
-             
-             // Contructing 'collectionmetadata' elements for 'mg' indexes
-             Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
-             collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-             String temp = StaticStrings.DOCUMENT_STR.concat (StaticStrings.COLON_CHARACTER).concat (index_strs[i]);
-             collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, temp);
-             collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
-             if (index_strs[i].indexOf (StaticStrings.NS_SEP) != -1) {
-                 index_strs[i] = index_strs[i].substring (index_strs[i].indexOf (StaticStrings.NS_SEP) + 1);
-             }
-             XMLTools.setNodeText (collectionmetadata, index_strs[i]);
-             
-             appendProperly (toElement, collectionmetadata);
-             
-         }
-         toElement.appendChild (mg_indexes);
-         
-    }
-    
-    private void doDisplayFormat (Document to, Element from) {
-        //display element in the xml file
-        Element de = (Element)XMLTools.getChildByTagName (from, StaticStrings.DISPLAY_STR);
-        if (de == null) {
-            return;
-        }
-        //format element in the display element
-        Element fe = (Element)XMLTools.getChildByTagName (de, StaticStrings.FORMAT_STR);
-
-        to.getDocumentElement ().appendChild (doFormat(to, fe, StaticStrings.DISPLAY_STR));
-    }
-
-    //construct 'DefaultIndex' element in the internal structure from collectionConfig.xml
-    private void doDefaultIndex (Document to, Node searchNode) {
-        Element toElement = to.getDocumentElement ();
-        Element default_index_element = to.createElement (StaticStrings.INDEX_DEFAULT_ELEMENT);
-        default_index_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-        
-        Element e = (Element)XMLTools.getChildByTagName (searchNode, StaticStrings.INDEX_DEFAULT_ELEMENT_LOWERCASE);//defaultIndex
-        if (e == null) {
-            return;
-        }
-        String index_str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-        
-        boolean old_index = false;
-        if(index_str.indexOf (StaticStrings.COLON_CHARACTER) != -1) {
-            //The index is 'level:source tuplets' which is for mg. Take out 'level'
-            old_index = true;
-            default_index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE,
-            index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER)));
-            index_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
-        } else {
-            default_index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE, "");
-        }
-        
-        //Each index may have a list of comma-separated strings.
-        //split them into 'content' elements in the internal structure
-        StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
-        while(content_tokenizer.hasMoreTokens ()) {
-            Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
-            String content_str = content_tokenizer.nextToken ();
-            // 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.indexOf (StaticStrings.NS_SEP) == -1) {
-                if(content_str.equals (StaticStrings.TEXT_STR) ||
-                (!old_index && content_str.equals (StaticStrings.ALLFIELDS_STR))) {
-                    // in this case, do nothing
-                }
-                else {
-                    content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
-                }
-            }
-
-            content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
-            default_index_element.appendChild (content_element);
-            content_element = null;
-        }
-        appendProperly (toElement, default_index_element);
-    }
-    // For mg, this method is still called, but make it 'assigned=false'
-    private void doDefaultLevel (Document to, Node searchNode) {
-        Element toElement = to.getDocumentElement ();
-        Element default_index_option = to.createElement (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT);
-        default_index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.LEVEL_DEFAULT_STR);
-        
-        Element e = (Element)XMLTools.getChildByTagName (searchNode, StaticStrings.LEVEL_DEFAULT_ELEMENT);
-        if (e != null) {
-            default_index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-            String level = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            default_index_option.setAttribute (StaticStrings.VALUE_ATTRIBUTE, level);
-        } else {
-            //In the case of mg, there's no level! build a default one using 'assigned=false value=document'
-            default_index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
-            default_index_option.setAttribute (StaticStrings.VALUE_ATTRIBUTE, StaticStrings.DOCUMENT_STR);
-        }
-        appendProperly (toElement, default_index_option);
-    }
-    
-    // Transform plugins (pluginListNode) of collectionConfig.xml into the internal structure (i.e. Document to)
-    private void doPlugin (Document to, Node pluginListNode) {
-        Element toElement = to.getDocumentElement ();
-        NodeList plugin_children = ((Element)pluginListNode).getElementsByTagName (StaticStrings.PLUGIN_STR);
-        int plugin_nodes = plugin_children.getLength ();
-        
-        if (plugin_nodes < 1) {
-            return;
-        }
-        
-        for (int i=0; i<plugin_nodes; i++) {
-            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);
-            
-            
-            NodeList option_children = e.getElementsByTagName (StaticStrings.OPTION_STR);
-            
-            for (int j=0; j<option_children.getLength (); j++) {
-                Element el = (Element)option_children.item (j);
-                String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-                if (name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
-                    name_str = name_str.substring (1);
-                }
-                String value_str = el.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
-                Element option_element = null;
-                
-                if (name_str.equals ("") && !value_str.equals ("")) {
-                    continue;
-                }
-                
-                
-                option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
-                option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-                if(name_str.equals (StaticStrings.RECPLUG_STR) && value_str.equals (StaticStrings.USE_METADATA_FILES_ARGUMENT)) {
-                    continue; // ignore this option
-                }
-                
-                if(value_str != null) {
-                    // Remove any speech marks appended in strings containing whitespace
-                    if(value_str.startsWith (StaticStrings.SPEECH_CHARACTER) && value_str.endsWith (StaticStrings.SPEECH_CHARACTER)) {
-                        value_str = value_str.substring (1, value_str.length () - 1);
-                    }
-                    if(name_str.equals (StaticStrings.METADATA_STR)) {
-                        // The metadata argument must be the fully qualified name of a metadata element, so if it doesn't yet have a namespace, append the extracted metadata namespace.
-                        String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
-                        value_str = "";
-                        for (int k=0; k<=values.length-1; k++) {
-                            if (values[k].indexOf (StaticStrings.NS_SEP) == -1) {
-                                values[k] = StaticStrings.EXTRACTED_NAMESPACE + values[k];
-                            }
-
-                            if (k < values.length-1) {
-                                value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
-                                
-                            } else {
-                                value_str = value_str + values[k];
-                            }
-                        }
-                    }
-                }
-                if (!name_str.equals ("")) {
-                    option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-                }
-                if (!value_str.equals ("")) {
-                    XMLTools.setNodeText (option_element, value_str);
-                }
-                plugin_element.appendChild (option_element);
-                
-            }
-            
-            appendProperly (toElement, plugin_element);
-        }
-        
-    }
-    
-    //Handle classifiers
-    private void doClassifier (Document to, Node browseNode) {
-        Element toElement = to.getDocumentElement ();
-        NodeList classifier_children = ((Element)browseNode).getElementsByTagName (StaticStrings.CLASSIFIER_STR);
-        int num_nodes = classifier_children.getLength ();
-        
-        if (num_nodes < 1) {
-            return;
-        }
-        
-        for (int i=0; i<num_nodes; i++) {
-            Element e = (Element)classifier_children.item (i);
-            String str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            Element classify_element = to.createElement (StaticStrings.CLASSIFY_ELEMENT);
-            classify_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, str);
-            
-            String options_str = "";
-            NodeList option_children = e.getElementsByTagName (StaticStrings.OPTION_STR);
-            for (int j=0; j<option_children.getLength (); j++) {
-                Element el = (Element)option_children.item (j);
-                String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-                options_str = options_str + ((name_str.equals(""))? "" : (" " + name_str));
-                if (name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
-                    name_str = name_str.substring (1);
-                }
-                String value_str = el.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
-                options_str = options_str + ((name_str.equals(""))? "" : (" " + value_str));
-                Element option_element = null;
-                
-                if (name_str.equals ("") && !value_str.equals ("")) {
-                    continue; //invalid condition
-                }
-                
-                option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
-                option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-                
-                if (!name_str.equals ("")) {
-                    option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-                }
-                
-                if (!value_str.equals ("") && name_str.equals (StaticStrings.METADATA_STR)) {
-                    // The metadata argument must be the fully qualified name of a metadata element, so if it doesn't yet have a namespace, append the extracted metadata namespace.
-		    String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
-		    value_str = "";
-                    for (int k=0; k<=values.length-1; k++) {
-                        if (values[k].indexOf (StaticStrings.NS_SEP) == -1) {
-                            values[k] = StaticStrings.EXTRACTED_NAMESPACE + values[k];
-                        }
-                        else {
-                            MetadataElement metadata_element = MetadataTools.getMetadataElementWithName (values[k]);
-                            if (metadata_element != null) {
-                                values[k] = metadata_element.getDisplayName ();
-                            }
-                        }
-                        if (k < values.length-1) {
-                            value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
-                        } else {
-                            value_str = value_str + values[k];
-                        }
-                    }
-                }
-                
-                if (value_str != null && !value_str.equals ("")) {
-                    XMLTools.setNodeText (option_element, value_str);
-                }
-                classify_element.appendChild (option_element);
-            }
-            //format element for this classifier
-            Element format = (Element)XMLTools.getChildByTagName (e, StaticStrings.FORMAT_STR);
-            if(format != null) {
-                classify_element.appendChild (doFormat(to, format, null));
-            }
-            appendProperly (toElement, classify_element);
-        }
-        
-        // default format statement for all classifiers
-        Element default_classifier_format = (Element)XMLTools.getChildByTagName (browseNode, StaticStrings.FORMAT_STR);
-
-        to.getDocumentElement ().appendChild (doFormat(to, default_classifier_format, StaticStrings.BROWSE_STR));
-    }
-    private Element doFormat(Document to, Element format, String name_str) {
-            Element format_element = to.createElement (StaticStrings.FORMAT_STR);
-            if (name_str != null) {
-                format_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-            }
-            if (format != null) {
-                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"),
-                					      gsf_text.indexOf(StaticStrings.FORMAT_END_TAG));
-                }
-                
-                XMLTools.setNodeText(format_element, gsf_text);
-            }
-            return format_element;
-    }
-    // Handling 'subcollection' elements in 'search' element of 'collectionConfig.xml'
-    private void doSubcollection (Document to, Node searchNode) {
-        Element toElement = to.getDocumentElement ();
-        NodeList sub_children = ((Element)searchNode).getElementsByTagName (StaticStrings.SUBCOLLECTION_STR);
-        int sub_nodes = sub_children.getLength ();
-        
-        // There is no subcollection
-        if (sub_nodes < 1) {
-            return;
-        }
-        
-        for (int i=0; i<sub_nodes; i++) {
-            Element sub_child = (Element)sub_children.item (i);
-            String name_str = sub_child.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            String filter_str = sub_child.getAttribute (StaticStrings.FILTER_ATTRIBUTE);
-            
-            // filter_str is in the form '<! (if set)><metadata>/<metadata value>/<flag (if any)>'
-            
-            int pos = filter_str.indexOf (StaticStrings.SEPARATOR_CHARACTER);
-            String meta_str = "";
-            String meta_value_str = "";
-            String clude_str = "";
-            String flag_str = "";
-            if (pos == -1) {
-                
-                meta_str = meta_value_str = filter_str;
-                clude_str = StaticStrings.INCLUDE_STR;
-            } else {
-                clude_str = StaticStrings.INCLUDE_STR;
-                if (filter_str.startsWith (StaticStrings.EXCLAMATION_CHARACTER)) {
-                    clude_str = StaticStrings.EXCLUDE_STR;
-                    // Peel off "!"
-                    filter_str = filter_str.substring (StaticStrings.EXCLAMATION_CHARACTER.length ());
-                }
-                
-                String[] strs = filter_str.split (StaticStrings.SEPARATOR_CHARACTER);
-                if (strs[0] != null && strs[0] != "") {
-                    meta_str = strs[0];
-                }
-                if(!meta_str.equals (StaticStrings.FILENAME_STR) && meta_str.indexOf (StaticStrings.NS_SEP) == -1) {
-                    meta_str = StaticStrings.EXTRACTED_NAMESPACE + meta_str;
-                }
-                
-                if (strs[1] != null && strs[1] != "") {
-                    meta_value_str = strs[1];
-                }
-                if (strs.length > 2) {
-                    //This means there has been set a flag
-                    if (strs[2] != null && strs[2] != "") {
-                        flag_str = strs[2];
-                    }
-                }
-            }
-            Element subcollection_element = to.createElement (StaticStrings.SUBCOLLECTION_ELEMENT);
-            subcollection_element.setAttribute (StaticStrings.NAME_STR, name_str);
-            subcollection_element.setAttribute (StaticStrings.CONTENT_ATTRIBUTE, meta_str);
-            subcollection_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, clude_str);
-            if (flag_str != "") {
-                subcollection_element.setAttribute (StaticStrings.OPTIONS_ATTRIBUTE, flag_str);
-            }
-            XMLTools.setNodeText (subcollection_element, meta_value_str);
-            
-            toElement.appendChild (subcollection_element);
-        }
-    }
-    //Handle levels (document, section). In the internal structure, the element is called 'IndexOption'
-    private void doLevel (Document to, Node searchNode) {
-        Element toElement = to.getDocumentElement ();
-        NodeList level_children = ((Element)searchNode).getElementsByTagName (StaticStrings.LEVEL_ATTRIBUTE);
-        int level_nodes = level_children.getLength ();
-        
-        // it's mg, there's no level. So we construct a default 'indexOption' in the internal structure
-        if (level_nodes < 1) {
-            Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
-            index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
-            index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.LEVELS_STR);
-            
-            Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
-            option_element.setAttribute (StaticStrings.NAME_STR, StaticStrings.DOCUMENT_STR);
-            index_option.appendChild (option_element);
-            
-            appendProperly (toElement, index_option);
-            
-            return;
-        }
-        
-        Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
-        index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-        index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.LEVELS_STR);
-        
-        for (int i=0; i<level_nodes; i++) {
-            Element level_element = (Element)level_children.item (i);
-            String level_str = level_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
-            option_element.setAttribute (StaticStrings.NAME_STR, level_str);
-            index_option.appendChild (option_element);
-            
-            
-            // Contructing 'collectionmetadata' elements from the 'displayItem' of this 'level' element
-            ArrayList displayItem_list = XMLTools.getNamedElementList (level_element,
-            StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_STR);
-            if (displayItem_list == null) {
-                return ;
-            }
-            for (int j=0; j<displayItem_list.size (); j++) {
-                Element item = (Element)displayItem_list.get (j);
-                String text = XMLTools.getNodeText (item);
-                String lang = item.getAttribute (StaticStrings.LANG_ATTRIBUTE);
-                
-                //If there is nothing to display, don't bother creating the element
-                if (text == "") {
-                    continue;
-                }
-                Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
-                collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-                collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, level_str);
-                collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
-                XMLTools.setNodeText (collectionmetadata, text);
-                
-                appendProperly (toElement, collectionmetadata);
-            }
-        }
-        appendProperly (toElement, index_option);
-    }
-    //Handle 'indexSubcollection' element of collectionConfig.xml,  which is called 'SubcollectionIndexes' in the internal structure. These contain the subcollection indexes (i.e. the filter or filter combinations), and displayed words for the filter names.
-    private void doIndexSubcollection (Document to, Node searchNode) {
-        Element toElement = to.getDocumentElement ();
-        NodeList index_sub_children = ((Element)searchNode).getElementsByTagName (StaticStrings.SUBCOLLECTION_INDEX_ELEMENT);
-        int num_nodes = index_sub_children.getLength ();
-        
-        // there is no subcollection index
-        if (num_nodes < 1) {
-            return;
-        }
-        
-        Element subcollection_indexes = to.createElement (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT);
-        
-        for (int i=0; i<num_nodes; i++) {
-            Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);
-            Element index_sub_child = (Element)index_sub_children.item (i);
-            String name_str = index_sub_child.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            
-            // name_str is in the form of comma separated strings, each of which is a subcollection filter name
-            String[] filters = name_str.split (StaticStrings.COMMA_CHARACTER);
-            for (int j=0; j<filters.length; j++) {
-                
-                Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
-                content_element.setAttribute (StaticStrings.NAME_STR, filters[j]);
-                index_element.appendChild (content_element);
-            }
-            subcollection_indexes.appendChild (index_element);
-            
-            // Contructing 'collectionmetadata' elements from the 'displayItem' of this 'indexSubcollection' element
-            ArrayList displayItem_list = XMLTools.getNamedElementList (index_sub_child,
-            StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_STR);
-            if (displayItem_list == null) {
-                // there is no display item for this element
-                continue;
-            }
-            for (int j=0; j<displayItem_list.size (); j++) {
-                Element item = (Element)displayItem_list.get (j);
-                String text = XMLTools.getNodeText (item);
-                String lang = item.getAttribute (StaticStrings.LANG_ATTRIBUTE);
-                
-                //If there is nothing to display, don't bother creating the element
-                if (text == "") {
-                    continue;
-                }
-                Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
-                collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-                collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-                collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
-                XMLTools.setNodeText (collectionmetadata, text);
-                
-                appendProperly (toElement, collectionmetadata);
-            }
-        }
-        appendProperly (toElement, subcollection_indexes);
-    }
-    //Handle 'indexLanguage' element of collectionConfig.xml,  which is called 'Languages' in the internal structure. These contain the language indexes, and displayed words for those language index names.
-    private void doIndexLanguage (Document to, Node searchNode) {
-        Element toElement = to.getDocumentElement ();
-        NodeList index_sub_children = ((Element)searchNode).getElementsByTagName (StaticStrings.LANGUAGE_INDEX_ELEMENT);
-        int num_nodes = index_sub_children.getLength ();
-        
-        // there is no subcollection index
-        if (num_nodes < 1) {
-            return;
-        }
-        
-        Element language_indexes = to.createElement (StaticStrings.LANGUAGES_ELEMENT);
-        
-        for (int i=0; i<num_nodes; i++) {
-            Element language_element = to.createElement (StaticStrings.LANGUAGE_ELEMENT);
-            Element index_sub_child = (Element)index_sub_children.item (i);
-            String name_str = index_sub_child.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            language_element.setAttribute (StaticStrings.NAME_STR, name_str);
-            language_indexes.appendChild (language_element);
-            
-            // Contructing 'collectionmetadata' elements from the 'displayItem' of this 'indexLanguage' element
-            ArrayList displayItem_list = XMLTools.getNamedElementList (index_sub_child,
-            StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_STR);
-            if (displayItem_list == null) {
-                // there is no display item for this element
-                continue;
-            }
-            for (int j=0; j<displayItem_list.size (); j++) {
-                Element item = (Element)displayItem_list.get (j);
-                String text = XMLTools.getNodeText (item);
-                String lang = item.getAttribute (StaticStrings.LANG_ATTRIBUTE);
-                
-                //If there is nothing to display, don't bother creating the element
-                if (text == "") {
-                    continue;
-                }
-                Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
-                collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-                collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-                collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
-                XMLTools.setNodeText (collectionmetadata, text);
-                
-                appendProperly (toElement, collectionmetadata);
-            }
-        }
-        toElement.appendChild (language_indexes);
-    }
-    // Handling both searchType and search format statement
-    private void doSearchFormat (Document to, Node searchNode) {
-        //There are two elements called <format> in <search>: one is for searchType; another is for format statement
-        NodeList format_children = ((Element)searchNode).getElementsByTagName (StaticStrings.FORMAT_STR);
-        int format_nodes = format_children.getLength ();
-        if (format_nodes < 1) {
-            return;
-        }
-        Element format = null;
-        Element search_type = null;
-        for(int i=0; i<format_nodes; i++) {
-            Node e = format_children.item (i);
-            if (e.hasAttributes () == false) {
-                //The format element for format statement has no any attribute
-                format = (Element)e;
-            }
-            else if (((Element)e).getAttribute (StaticStrings.NAME_ATTRIBUTE).equals(StaticStrings.SEARCHTYPE_ELEMENT)) {
-                search_type = (Element)e;
-            }
-        }
-        //format statement for search
-        if (format != null) {            
-            (to.getDocumentElement ()).appendChild (doFormat(to, format, StaticStrings.SEARCH_STR));
-        }
-        // searchType in search
-        if(search_type != null) {
-            String searchtype_str = XMLTools.getNodeText(search_type);
-        
-            Element search_type_element = to.createElement (StaticStrings.FORMAT_STR);
-            search_type_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.SEARCHTYPE_ELEMENT);
-            XMLTools.setNodeText(search_type_element, searchtype_str);
-        
-        
-            appendProperly (to.getDocumentElement (), search_type_element);
-        }
-    }
-    // Handling defaultIndexLanguage and languageMetadata in collectionConfig.xml ('elementNameFrom'); in the internal structure, they are called 'DefaultLanguage' and 'LanguageMetadata' ('elementNameTo') respectively.
-    // Converting from collectionConfig.xml to the internal xml structure.
-    private void doLanguageMetadata (Document to, Node searchNode) {
-        Element toElement = to.getDocumentElement ();
-        String elementNameFrom = StaticStrings.LANGUAGE_METADATA_ELEMENT_STR;
-        String elementNameTo = StaticStrings.LANGUAGE_METADATA_ELEMENT;
-        Node from_element = XMLTools.getChildByTagName (searchNode, elementNameFrom);
-        if (from_element == null) {
-            return; // such an element not found
-        }
-        
-        Element to_element = to.createElement (elementNameTo);
-        
-        String name_str = ((Element)from_element).getAttribute (StaticStrings.NAME_ATTRIBUTE);
-        if (name_str.indexOf (StaticStrings.NS_SEP) == -1) {
-            name_str = StaticStrings.EXTRACTED_NAMESPACE + name_str;
-        }
-        to_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-        to_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-        
-        toElement.appendChild (to_element);
-    }
-    private void doReplaceListRef (Document to, Element from) {
-        Element toElement = to.getDocumentElement ();
-        
-        Node replace_element = XMLTools.getChildByTagName (from, StaticStrings.REPLACELISTREF_STR);
-        if (replace_element == null) {
-            return; // such an element not found
-        }
-        
-        Element to_element = XMLTools.duplicateElement (to, (Element)replace_element, true);
-        toElement.appendChild (to_element);
-    }
-    private void convertReplaceListRef (Document from, Document to) {
-        Element toElement = to.getDocumentElement ();
-        
-        Node replace_element = XMLTools.getChildByTagName (from.getDocumentElement (), StaticStrings.REPLACELISTREF_STR);
-        if (replace_element == null) {
-            return; // such an element not found
-        }
-        
-        Element to_element = XMLTools.duplicateElement (to, (Element)replace_element, true);
-        toElement.appendChild (to_element);
-    }
-    private void doOAIElement (Document to, Element from) {
-        Element toElement = to.getDocumentElement ();
-        
-        Node oai_element = XMLTools.getChildByTagName (from, StaticStrings.OAI_ELEMENT);
-        if (oai_element == null) {
-            return; // such an element not found
-        }
-        
-        Element to_element = XMLTools.duplicateElement (to, (Element)oai_element, true);
-        toElement.appendChild (to_element);
-    }
-    private void convertOAIElement (Document from, Document to) {
-        Element toElement = to.getDocumentElement ();
-        
-        Node oai_element = XMLTools.getChildByTagName (from.getDocumentElement (), StaticStrings.OAI_ELEMENT);
-        if (oai_element == null) {
-            return; // such an element not found
-        }
-        
-        Element to_element = XMLTools.duplicateElement (to, (Element)oai_element, true);
-        toElement.appendChild (to_element);
-    }
-    private void doDefaultIndexLanguage (Document to, Node searchNode) {
-        Element toElement = to.getDocumentElement ();
-        String elementNameFrom = StaticStrings.LANGUAGE_DEFAULT_INDEX_ELEMENT;
-        String elementNameTo = StaticStrings.LANGUAGE_DEFAULT_ELEMENT;
-        Node from_element = XMLTools.getChildByTagName (searchNode, elementNameFrom);
-        if (from_element == null) {
-            return; // such an element not found
-        }
-        
-        Element to_element = to.createElement (elementNameTo);
-        
-        String name_str = ((Element)from_element).getAttribute (StaticStrings.NAME_ATTRIBUTE);
-        to_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-        to_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-        
-        toElement.appendChild (to_element);
-    }
-    
-    //Handle 'indexOption' (i.e. casefold, stem etc). In the internal structure, the element is called 'IndexOption'
-    private void doIndexOption (Document to, Node searchNode) {
-        Element toElement = to.getDocumentElement ();
-        Node index_option_node = XMLTools.getChildByTagName (searchNode, StaticStrings.INDEXOPTION_STR);
-        if (index_option_node == null) {
-            return;
-        }
-        NodeList option_children = ((Element)index_option_node).getElementsByTagName (StaticStrings.OPTION_STR);
-        int option_nodes = option_children.getLength ();
-        
-        // for lucene, there is no 'indexOption'. We build a default 'indexOption' and 'assigned=false' in case the user switches to mg or mgpp
-        if (option_nodes < 1) {
-            Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
-            index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
-            index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.INDEXOPTIONS_STR);
-            String[] option_str =
-            { StaticStrings.CASEFOLD_OPTION_STR, StaticStrings.STEM_OPTION_STR };
-            for (int i=0; i<option_str.length; i++) {
-                Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
-                option_element.setAttribute (StaticStrings.NAME_STR, option_str[i]);
-                index_option.appendChild (option_element);
-            }
-            appendProperly (toElement, index_option);
-            return;
-        }
-        
-        Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
-        index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-        index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.INDEXOPTIONS_STR);
-        
-        for (int i=0; i<option_nodes; i++) {
-            String option_str = ((Element)option_children.item (i)).getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
-            option_element.setAttribute (StaticStrings.NAME_STR, option_str);
-            index_option.appendChild (option_element);
-        }
-        appendProperly (toElement, index_option);
-    }
-    
-    private Element doBuildType (Document to, String att_value) {
-        
-        //construct 'BuildType' element
-        Element element = to.createElement (StaticStrings.BUILDTYPE_ELEMENT);
-        element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
-        element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
-        element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-        element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
-
-        XMLTools.setNodeText (element, att_value);
-        
-        return element;
-    }
-    
-    // Convert 'description', 'smallicon' etc.
-    private void convertDisplayItemList (Document from, Document to) {
-        Element displayItemList = to.createElement (StaticStrings.DISPLAYITEMLIST_STR);
-        Element destination = to.getDocumentElement ();
-        
-        String []att_values =
-        {StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR,
-         StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR,
-         StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR,
-         StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR};
-         
-         String []map_attrs =
-         {StaticStrings.DESCRIPTION_STR,
-          StaticStrings.SMALLICON_STR,
-          StaticStrings.ICON_STR,
-          StaticStrings.NAME_STR};
-          
-          for (int i=0; i<att_values.length; i++) {
-              
-              //dOc
-              ArrayList e_list = XMLTools.getNamedElementList (from.getDocumentElement (),
-              StaticStrings.COLLECTIONMETADATA_ELEMENT,
-              StaticStrings.NAME_ATTRIBUTE, att_values[i]);
-              // if such elements don't exist, don't bother
-              if (e_list == null) {
-                  continue;
-              }
-              for (int j=0; j<e_list.size (); j++) {
-                  Element e = (Element)e_list.get (j);
-                  if (e.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                      continue;
-                  }
-                  String text = XMLTools.getNodeText (e);
-                  String lang = e.getAttribute (StaticStrings.LANGUAGE_ATTRIBUTE);
-                  
-                  Element displayItem = constructElement (StaticStrings.DISPLAYITEM_STR, map_attrs[i],
-                  StaticStrings.LANG_STR, lang, text, to);
-                  displayItemList.appendChild (displayItem);
-              }
-              
-          }
-          destination.appendChild (displayItemList);
-    }
-    // This method creates a DisplayItem element of the type of 'to' by using the ingredients from the element 'e'
-    private Element constructDisplayItem (Element e, Document to) {
-        String lang_string = e.getAttribute (StaticStrings.LANGUAGE_ATTRIBUTE);
-        String text = XMLTools.getNodeText (e);
-        Element displayItem = to.createElement (StaticStrings.DISPLAYITEM_STR);
-        displayItem.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_ATTRIBUTE);
-        displayItem.setAttribute (StaticStrings.LANG_STR, lang_string);
-        XMLTools.setNodeText (displayItem, text);
-        return displayItem;
-    }
-    private void convertMetadataList (Document from, Document to) {
-        Element metadataList = to.createElement (StaticStrings.METADATALIST_STR);
-        Element destination = to.getDocumentElement ();
-        
-        String []ele_names =
-        {StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT,
-         StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT,
-         StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT};
-         String []att_names =
-         {StaticStrings.COLLECTIONMETADATA_CREATOR_STR,
-          StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR,
-          StaticStrings.COLLECTIONMETADATA_PUBLIC_STR};
-          for (int i=0; i<ele_names.length; i++) {
-              Element e = XMLTools.getNamedElement (from.getDocumentElement (),
-              ele_names[i], StaticStrings.NAME_ATTRIBUTE, att_names[i]);
-              if (e == null) {
-                  continue;
-              }
-              String text = XMLTools.getNodeText (e);
-              Element metadata = to.createElement (StaticStrings.METADATA_STR);
-              metadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, att_names[i]);
-              metadata.setAttribute (StaticStrings.LANG_STR, StaticStrings.ENGLISH_LANGUAGE_STR);
-              XMLTools.setNodeText (metadata, text);
-              metadataList.appendChild (metadata);
-          }
-
-          destination.appendChild (metadataList);
-    }
-    // This method creates an element with the name 'element_name' of the type of 'to' by using the other three strings
-    private Element constructElement (String element_name, String name_value, String lang_att, String lang_value, String text, Document to) {
-        Element e = to.createElement (element_name);
-        e.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-        e.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_value);
-        e.setAttribute (lang_att, lang_value);
-        XMLTools.setNodeText (e, text);
-        
-        return e;
-    }
-    // Convert classify in the internal(i.e. Document from) to collectionconfig.xml (i.e. Document to)
-    private void convertClassifier (Document from, Document to) {
-        Element browse_element = to.createElement (StaticStrings.BROWSE_STR);
-        NodeList children = from.getDocumentElement ().getElementsByTagName (StaticStrings.CLASSIFY_ELEMENT);
-        
-        int num_children = (children == null)? 0 : children.getLength ();
-        
-        if (num_children == 0) {
-            return ;
-        }
-        
-        for (int i=0; i<num_children; i++) {
-            
-            Element child =  (Element)children.item (i);
-            if (child.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                continue;
-            }
-            String str = child.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
-            Element classifier_element = to.createElement (StaticStrings.CLASSIFIER_STR);
-            classifier_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, str);
-            
-            NodeList option_children = child.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
-            for (int j=0; j<option_children.getLength (); j++) {
-                Element el = (Element)option_children.item (j);
-                if (el.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                    continue;
-                }
-                String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-                String value_str = XMLTools.getNodeText (el);
-                
-                
-                if (name_str == null && value_str == null) {
-                    continue;
-                }
-                Element option_element = to.createElement (StaticStrings.OPTION_STR);
-                if (name_str != null && name_str.equals (StaticStrings.METADATA_STR)) {
-                    
-                    // The metadata argument is the fully qualified name of a metadata element, so if it contains a namespace, remove the extracted metadata namespace as the build process doesn't know about it.
-		    String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
-		    value_str = "";
-                    for (int k=0; k<=values.length-1; k++) {
-                        if(values[k].startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
-                            values[k] = values[k].substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
-                        }
-                        else {
-                            MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName (values[k]);
-                            if (metadata_element != null) {
-                                values[k] = metadata_element.getFullName ();
-                            }
-                        }
-                        if (k < values.length-1) {
-                            value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
-                        } else {
-                            value_str = value_str + values[k];
-                        }
-                    }
-                }
-                
-                if (!name_str.equals ("")) {
-                    if (!name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
-                        name_str = StaticStrings.MINUS_CHARACTER + name_str;
-                    }
-                    option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-                }
-                
-                if (!value_str.equals ("")) {
-                    option_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, value_str);
-                }
-                
-                classifier_element.appendChild (option_element);
-            }
-            
-            //format element for this classifier
-            Element e = (Element)XMLTools.getChildByTagName (child, StaticStrings.FORMAT_STR);
-            
-            if (e != null) {
-                classifier_element.appendChild (convertFormat(to, e));
-            }
-            browse_element.appendChild (classifier_element);
-        }
-        
-        //convert default classifier format
-        Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
-                                                StaticStrings.NAME_ATTRIBUTE,  StaticStrings.BROWSE_STR);
-        browse_element.appendChild (convertFormat(to, e));
-        
-        to.getDocumentElement ().appendChild (browse_element);
-    }
-    private Element convertFormat(Document to, Element e) {
-        String format_str = XMLTools.getNodeText(e);
-        Element format = to.createElement (StaticStrings.FORMAT_STR);
-        //XMLTools.copyAllChildren (format, e);
-        XMLTools.setNodeText(format, format_str); 
-        return format;
-    }
-    //convert format statement for search
-    private void convertSearchFormat (Document from, Document to) {
-        Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
-        Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
-                                                StaticStrings.NAME_ATTRIBUTE,  StaticStrings.SEARCH_STR);
-                                                
-        search.appendChild (convertFormat(to, e));
-        
-    }
-    //convert format statement for display of the documents
-    private void convertDisplayFormat (Document from, Document to) {
-        Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
-                                                StaticStrings.NAME_ATTRIBUTE,  StaticStrings.DISPLAY_STR);
-        if (e == null) {
-            return;
-        }
-        Element display = to.createElement (StaticStrings.DISPLAY_STR);
-        display.appendChild (convertFormat(to, e));
-        to.getDocumentElement ().appendChild (display);
-    }
-    // Convert plugins in the internal(i.e. Document from) to collectionconfig.xml (i.e. Document to)
-    private void convertPlugin (Document from, Document to) {
-        Element import_element = to.createElement (StaticStrings.IMPORT_STR);
-        Element plugin_list_element = to.createElement (StaticStrings.PLUGINLIST_STR);
-        
-        NodeList children = from.getDocumentElement ().getElementsByTagName (StaticStrings.PLUGIN_ELEMENT);
-        int num_children = (children == null)? 0 : children.getLength ();
-        if (num_children == 0) {
-            return ;
-        }
-        
-        for (int i=0; i<num_children; i++) {
-            
-            Element child =  (Element)children.item (i);
-            if (child.getAttribute (StaticStrings.SEPARATOR_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-                continue;
-            }
-            if (child.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                continue;
-            }
-            
-            String str = child.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
-            Element plugin_element = to.createElement (StaticStrings.PLUGIN_STR);
-            plugin_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, str);
-            
-            NodeList option_children = child.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
-            for (int j=0; j<option_children.getLength (); j++) {
-                Element el = (Element)option_children.item (j);
-                if(!el.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-                    continue;
-                }
-                String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-                String value_str = XMLTools.getNodeText (el);
-                
-                
-                if (name_str == null && value_str == null) {
-                    continue;
-                }
-                Element option_element = to.createElement (StaticStrings.OPTION_STR);
-                if (name_str != null && name_str.equals (StaticStrings.METADATA_STR)) {
-                    
-                    // The metadata argument is the fully qualified name of a metadata element, so if it contains a namespace, remove the extracted metadata namespace as the build process doesn't know about it.
-                    String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
-                    value_str = "";
-                    for (int k=0; k<=values.length-1; k++) {
-                        if(values[k].startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
-                            values[k] = values[k].substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
-                        }
-
-                        if (k < values.length-1) {
-                            value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
-                        } else {
-                            value_str = value_str + values[k];
-                        }
-                    }
-                }
-                
-                if (!name_str.equals ("")) {
-                    if (!name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
-                        name_str = StaticStrings.MINUS_CHARACTER + name_str;
-                    }
-                    option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-                }
-                
-                if (!value_str.equals ("")) {
-                    option_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, value_str);
-                }
-                
-                plugin_element.appendChild (option_element);
-            }//for loop ends
-            
-            plugin_list_element.appendChild (plugin_element);
-        }//for loop ends
-        
-        import_element.appendChild (plugin_list_element);
-        
-        //do the plugout element (used by building flax collections)
-        Node plugout = XMLTools.getChildByTagNameIndexed (from.getDocumentElement (), PLUGOUT_ELEMENT, 0);
-        if (plugout != null) {
-        	Element to_element = XMLTools.duplicateElement (to, (Element)plugout, true);
-        	import_element.appendChild (to_element);
-        }
-        
-        to.getDocumentElement ().appendChild (import_element);
-    }
-
-    //Handle 'searchType' of collectionConfig.xml. In the internal structure, its also called 'searchType', eg. plain, form
-    private void convertSearchType (Document from, Document to) {
-        Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
-                StaticStrings.NAME_ATTRIBUTE,  StaticStrings.SEARCHTYPE_ELEMENT);//searchType
-        
-        if (e == null) {
-            return;
-        }
-        Element search_type_element = to.createElement (StaticStrings.FORMAT_STR);
-        
-//        String searchtype_str = e.getAttribute (StaticStrings.VALUE_ATTRIBUTE);        
-//        search_type_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, searchtype_str);
-        String searchtype_str = XMLTools.getNodeText(e);        
-        XMLTools.setNodeText(search_type_element, searchtype_str);
-        
-        search_type_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.SEARCHTYPE_ELEMENT);
-        //Get the 'search' element from 'to'
-        Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
-        search.appendChild (search_type_element);
-    }
-    
-    private void convertBuildType (Document from, Document to) {
-        Element e = XMLTools.getNamedElement (from.getDocumentElement (),
-        StaticStrings.BUILDTYPE_ELEMENT,
-        StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
-        if (e == null) {
-            return;
-        }
-        String indexer = XMLTools.getNodeText (e);
-        Element search = to.createElement (StaticStrings.SEARCH_STR);
-        search.setAttribute (StaticStrings.TYPE_ATTRIBUTE, indexer);
-        to.getDocumentElement ().appendChild (search);
-    }
-    private void convertDefaultIndex (Document from, Document to, Element search) {
-        Element source = from.getDocumentElement ();
-        
-        Element default_index_element = (Element)XMLTools.getChildByTagName (source, StaticStrings.INDEX_DEFAULT_ELEMENT);
-        if (default_index_element == null) {
-            return;
-        }
-        
-        String indexer = search.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
-        String level_str = default_index_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE);
-        // Debugging purposes
-        if (level_str.equals ("") && indexer.equals (StaticStrings.MG_STR) ) {
-            System.out.println ("Bug: DefaultIndex should have its level attribute not empty.");
-        }
-        
-        NodeList content_elements = default_index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
-        int content_elements_length = content_elements.getLength ();
-        
-        // Don't output anything if no indexes are set
-        if(content_elements_length == 0) {
-            return ;//
-        }
-        
-        String index_str = "";
-        
-        if (indexer.equals (StaticStrings.MG_STR)) {
-            //combine level with indexes
-            index_str = level_str + StaticStrings.COLON_CHARACTER;
-        }
-        else { //for mgpp/lucene, just take index
-            //do nothing
-        }
-        
-        for(int k = 0; k < content_elements_length; k++) {
-            Element content_element = (Element) content_elements.item (k);
-            if (content_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                continue;
-            }
-            String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            
-            if(name_str.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
-                name_str = name_str.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
-            }
-
-            index_str = index_str + name_str;
-            
-            // Make it comma separated string
-            if(k < content_elements_length - 1) {
-                index_str = index_str + StaticStrings.COMMA_CHARACTER;
-            }
-            content_element = null;
-        }//for loop ends
-        
-        
-        Element default_index = to.createElement (StaticStrings.INDEX_DEFAULT_ELEMENT_LOWERCASE);
-        default_index.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_str);
-        search.appendChild (default_index);
-        
-    }
-    private void convertSubcollection (Document from, Document to) {
-        Element source = from.getDocumentElement ();
-        //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
-        Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
-        
-        // Get the Subcollection element from the internal structure
-        NodeList subcollection_elements = source.getElementsByTagName (StaticStrings.SUBCOLLECTION_ELEMENT);
-        if (subcollection_elements == null) {
-            return;
-        }
-        int subcollection_elements_length = subcollection_elements.getLength ();
-        
-        if (subcollection_elements_length == 0) { // no
-            return ;
-        }
-        
-        for(int j = 0; j < subcollection_elements_length; j++) {
-            
-            Element e = (Element) subcollection_elements.item (j);
-            if (e.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                continue;
-            }
-            String content = e.getAttribute (StaticStrings.CONTENT_ATTRIBUTE);
-            String name = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            String options = e.getAttribute (StaticStrings.OPTIONS_ATTRIBUTE);
-            String type = e.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
-            String text = XMLTools.getNodeText (e);
-            
-            String filter = "";
-            if (type.equals (StaticStrings.EXCLUDE_STR)) {
-                filter = StaticStrings.EXCLAMATION_CHARACTER;
-            }
-            
-            if(content.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
-                content = content.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
-            }
-            filter = filter + content + StaticStrings.SEPARATOR_CHARACTER + text;
-            if (options != null && options != "") {
-                filter = filter + StaticStrings.SEPARATOR_CHARACTER + options;
-            }
-            Element subcollection = to.createElement (StaticStrings.SUBCOLLECTION_STR);
-            subcollection.setAttribute (StaticStrings.FILTER_ATTRIBUTE, filter);
-            subcollection.setAttribute (StaticStrings.NAME_ATTRIBUTE, name);
-            
-            search.appendChild (subcollection);
-        }
-    }
-    private void convertSubcollectionIndexes (Document from, Document to) {
-        Element source = from.getDocumentElement ();
-        //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
-        Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
-        
-        // Get the SubcollectionIndexes element from the internal structure
-        Element subcollection_indexes = (Element)XMLTools.getChildByTagName (source, StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT);
-        if (subcollection_indexes == null) {
-            return;
-        }
-        NodeList index_elements = subcollection_indexes.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
-        int index_elements_length = index_elements.getLength ();
-        
-        if (index_elements_length == 0) { // no indexes
-            return ;
-        }
-        
-        for(int j = 0; j < index_elements_length; j++) {
-            Element index_element = (Element) index_elements.item (j);
-            if (index_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                continue;
-            }
-            
-            Element index = to.createElement (StaticStrings.SUBCOLLECTION_INDEX_ELEMENT);
-            
-            String index_value = "";
-            
-            NodeList content_elements = index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
-            int content_elements_length = content_elements.getLength ();
-            
-            for(int k = 0; k < content_elements_length; k++) {
-                Element content_element = (Element) content_elements.item (k);
-                if (content_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                    continue;
-                }
-                String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-                index_value += name_str;
-                // Make it comma separated string
-                if(k < content_elements_length - 1) {
-                    index_value += StaticStrings.COMMA_CHARACTER;
-                }
-                content_element = null;
-            }//for loop ends
-            
-            index.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_value);
-            
-            // Now constructing 'displayItem' element for this 'indexSubcollection' element
-            // from the collectionmetadata element
-            ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
-            StaticStrings.COLLECTIONMETADATA_ELEMENT,
-            StaticStrings.NAME_ATTRIBUTE, index_value);
-            
-            if (collectionmetadata_list != null) {
-                
-                for(int k = 0; k < collectionmetadata_list.size (); k++) {
-                    Element collectionmetadata = (Element)collectionmetadata_list.get (k);
-                    if (collectionmetadata.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                        continue;
-                    }
-                    Element displayItem = constructDisplayItem (collectionmetadata, to);
-                    index.appendChild (displayItem);
-                }
-            }
-            
-            search.appendChild (index);
-            
-        } //for loop ends
-    }
-    
-    private void convertLanguages (Document from, Document to) {
-        Element source = from.getDocumentElement ();
-        //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
-        Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
-        
-        // Get the Languages element from the internal structure
-        Element languages = (Element)XMLTools.getChildByTagName (source, StaticStrings.LANGUAGES_ELEMENT);
-        if (languages == null) {
-            return;
-        }
-        NodeList language_elements = languages.getElementsByTagName (StaticStrings.LANGUAGE_ELEMENT);
-        int language_elements_length = language_elements.getLength ();
-        
-        if (language_elements_length == 0) {
-            return ;
-        }
-        
-        for(int j = 0; j < language_elements_length; j++) {
-            Element element = (Element) language_elements.item (j);
-            if (element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                continue;
-            }
-            
-            // Create indexLanguage element
-            Element index_language = to.createElement (StaticStrings.LANGUAGE_INDEX_ELEMENT);
-            
-            String name_str = element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            index_language.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-            
-            // Now constructing 'displayItem' element for this 'indexLanguage' element
-            // from the collectionmetadata element
-            ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
-            StaticStrings.COLLECTIONMETADATA_ELEMENT,
-            StaticStrings.NAME_ATTRIBUTE, name_str);
-            
-            if (collectionmetadata_list != null) {
-                
-                for(int k = 0; k < collectionmetadata_list.size (); k++) {
-                    Element collectionmetadata = (Element)collectionmetadata_list.get (k);
-                    if (collectionmetadata.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                        continue;
-                    }
-                    Element displayItem = constructDisplayItem (collectionmetadata, to);
-                    index_language.appendChild (displayItem);
-                }
-            }
-            
-            search.appendChild (index_language);
-            
-        } //for loop ends
-        
-        // Convert DefaultLanguage
-        // Get the DefaultLanguage element from the internal structure
-        Element default_language = (Element)XMLTools.getChildByTagName (source, StaticStrings.LANGUAGE_DEFAULT_ELEMENT);
-        if(default_language != null) {
-            String lang_name = default_language.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            Element default_index_language = to.createElement (StaticStrings.LANGUAGE_DEFAULT_INDEX_ELEMENT);
-            default_index_language.setAttribute (StaticStrings.NAME_ATTRIBUTE, lang_name);
-            search.appendChild (default_index_language);
-        }
-        // Convert LanguageMetadata
-        // Get the LanguageMetadata element from the internal structure
-        Element language_metadata = (Element)XMLTools.getChildByTagName (source, StaticStrings.LANGUAGE_METADATA_ELEMENT);
-        if(language_metadata != null) {
-            String meta_name = language_metadata.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            Element language_meta = to.createElement (StaticStrings.LANGUAGE_METADATA_ELEMENT_STR);
-            if(meta_name.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
-                meta_name = meta_name.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
-            }
-            language_meta.setAttribute (StaticStrings.NAME_ATTRIBUTE, meta_name);
-            search.appendChild (language_meta);
-        }
-    }
-    
-    //convert indexes and their displayItems, which go in 'search' element in collectionConfig.xml
-    //parameter 'to' is the document to be saved as collectionConfig.xml
-    //parameter 'from' is the internal xml structure
-    private void convertIndex (Document from, Document to) {
-        Element source = from.getDocumentElement ();
-        //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
-        Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
-        
-        //THere are two sets of indexes elements, find the one which is assigned 'true'
-        Element indexes = XMLTools.getNamedElement (source,
-        StaticStrings.INDEXES_ELEMENT,
-        StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
-        if (indexes == null) {
-            return;
-        }
-        NodeList index_elements = indexes.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
-        int index_elements_length = index_elements.getLength ();
-        
-        if (index_elements_length == 0) { // no indexes
-            return ;
-        }
-        
-        //find out it's mg or mgpp/lucene
-        String mg = search.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
-        boolean mg_indexer = false;
-        if (mg.equals (StaticStrings.MG_STR)) {
-            mg_indexer = true;//it's mg, then the level is set as attribute of
-        }
-        if (mg_indexer == false) {
-            // It's mgpp. Construct 'level' and 'defaultLevel' elements separately.
-            convertLevels (from, to, search);
-        }
-        
-        for(int j = 0; j < index_elements_length; j++) {
-            Element index_element = (Element) index_elements.item (j);
-            if (index_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                continue;
-            }
-            
-            Element index_ele = to.createElement (StaticStrings.INDEX_LOW_STR);//index
-            
-            // Used for creating displayItem for this element 'index_ele' further below
-            // full_index_names contain 'ex.'
-            String full_index_name = "";
-            String level_str = "";
-            
-            StringBuffer index_value = new StringBuffer ();
-            if (mg_indexer == true) {
-                // For mg indexer, there is a 'level' attribute in the index element of the internal structure
-                // But mgpp/lucene don't
-                level_str = index_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE);
-                if(level_str.length () > 0) {
-                    index_value.append (level_str).append (StaticStrings.COLON_CHARACTER);
-                    //index_value = index_value.StaticStrings.COLON_CHARACTER;
-                }
-            }
-            
-            NodeList content_elements = index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
-            int content_elements_length = content_elements.getLength ();
-            
-            for(int k = 0; k < content_elements_length; k++) {
-                Element content_element = (Element) content_elements.item (k);
-                if (content_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                    continue;
-                }
-                String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-                
-                full_index_name = full_index_name + name_str;
-                if (k < content_elements_length - 1) {
-                    full_index_name = full_index_name + StaticStrings.COMMA_CHARACTER;
-                }
-                
-                if(name_str.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
-                    name_str = name_str.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
-                }
-
-                index_value.append (name_str);
-                name_str = null;
-                // Make it comma separated string
-                if(k < content_elements_length - 1) {
-                    index_value.append (StaticStrings.COMMA_CHARACTER);
-                }
-                content_element = null;
-            }//for loop ends
-            
-            String temp_str = index_value.toString ();
-            index_ele.setAttribute (StaticStrings.NAME_ATTRIBUTE, temp_str);
-            
-            // Now constructing 'displayItem' element for this 'index_ele' element
-            // The index names in the collectionmetadata elements in the internal structure are not the names that
-            // are used in the content elements (i.e. ex.Source or dc.Subject and keywords), but the names that are
-            // in the configuration files (i.e. Source or dc.Subject)
-            ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
-            StaticStrings.COLLECTIONMETADATA_ELEMENT,
-            StaticStrings.NAME_ATTRIBUTE, temp_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) {
-                
-                for(int k = 0; k < collectionmetadata_list.size (); k++) {
-                    Element collectionmetadata = (Element)collectionmetadata_list.get (k);
-                    if (collectionmetadata.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-                        continue;
-                    }
-                    Element displayItem = constructDisplayItem (collectionmetadata, to);
-                    
-                    index_ele.appendChild (displayItem);
-                }
-            }
-            
-            search.appendChild (index_ele);
-            
-        } //for loop ends
-        
-        //Convert default index
-        convertDefaultIndex (from, to, search);
-        convertIndexOptions(from, to, search);
-    }
-    // Convert levels for mgpp/lucene. This method is called by converIndex() when mgpp indexer is detected.
-    private void convertLevels (Document from, Document to, Element search) {
-        Element source = from.getDocumentElement ();
-        Element index_option = XMLTools.getNamedElement (source,
-        StaticStrings.INDEXOPTIONS_ELEMENT,
-        StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVELS_STR);
-        if (index_option == null) {
-            return;
-        }
-        //Debugging purposes
-        if (index_option.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-            DebugStream.println ("For mgpp, there should be an IndexOption element for levels which is assigned 'true': possible bug.");
-        }
-        
-        NodeList option_elements = index_option.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
-        int num_elements = option_elements.getLength ();
-        
-        // Don't output anything if no indexes are set
-        if(num_elements == 0) {
-            return ;//
-        }
-        
-        for(int k = 0; k < num_elements; k++) {
-            Element e = (Element) option_elements.item (k);
-            String name_str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-            Element level_element = to.createElement (StaticStrings.LEVEL_ELEMENT);
-            level_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
-            
-            //Now construct displayItem for this level element from collectionmetadata
-            ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
-            StaticStrings.COLLECTIONMETADATA_ELEMENT,
-            StaticStrings.NAME_ATTRIBUTE, name_str);
-            
-            if (collectionmetadata_list != null) {
-                
-                for(int j = 0; j < collectionmetadata_list.size (); j++) {
-                    Element collectionmetadata = (Element)collectionmetadata_list.get (j);
-                    
-                    Element displayItem = constructDisplayItem (collectionmetadata, to);
-                    level_element.appendChild (displayItem);
-                }
-            }
-            search.appendChild (level_element);
-        }
-        
-        //Convert default level
-        Element default_index_option = XMLTools.getNamedElement (source,
-        StaticStrings.INDEXOPTION_DEFAULT_ELEMENT,
-        StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVEL_DEFAULT_STR);
-        if (default_index_option == null) {
-            return;
-        }
-        Element default_level = to.createElement (StaticStrings.LEVEL_DEFAULT_ELEMENT);
-        String default_level_str = default_index_option.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
-        default_level.setAttribute (StaticStrings.NAME_ATTRIBUTE, default_level_str);
-        search.appendChild (default_level);
-        
-    }
-    // Convert indexoptions for mg/mgpp/lucene. This method is called by convertIndex().
-    private void convertIndexOptions (Document from, Document to, Element search) {
-        Element source = from.getDocumentElement ();
-        Element index_option = XMLTools.getNamedElement (source,
-        StaticStrings.INDEXOPTIONS_ELEMENT,
-        StaticStrings.NAME_ATTRIBUTE, StaticStrings.INDEXOPTIONS_STR);
-        if (index_option == null) {
-            return;
-        }
-        //Debugging purposes
-        if (index_option.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
-            DebugStream.println ("There should be an IndexOption element which is assigned 'true': possible bug.");
-        }
-        Element indexOptionEl = to.createElement(StaticStrings.INDEXOPTION_STR);
-        NodeList option_elements = index_option.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
-        int num_elements = option_elements.getLength ();        
-        // Don't output anything if no index
-        if(num_elements == 0) {
-            return ;//
-        }
-        search.appendChild (indexOptionEl);
-        
-        for(int k = 0; k < num_elements; k++) {
-            Element e = (Element) option_elements.item (k);
-            String name_att = e.getAttribute(StaticStrings.NAME_ATTRIBUTE);
-            Element optionEl = to.createElement(StaticStrings.OPTION_STR);
-            optionEl.setAttribute(StaticStrings.NAME_ATTRIBUTE, name_att);
-            indexOptionEl.appendChild(optionEl);
-        }
-           
-    }
-    // Append the element son to the element mother in the appropriate position.
-    static public void appendProperly (Element mother, Element son) {
-        if (son == null)
-            return;
-        
-        Node reference_node = findInsertionPoint (mother, son);
-        if(reference_node != null) {
-            mother.insertBefore (son, reference_node);
-        }
-        else {
-            mother.appendChild (son);
-        }
-    }
-    /** Find the best insertion position for the given DOM Element 'target_element' in the DOM Element 'document_element'. This should try to match command tag, and if found should then try to group by name or type (eg CollectionMeta), or append to end is no such grouping exists (eg Plugins). Failing a command match it will check against the command order for the best insertion location.
-     * @param target_element the command Element to be inserted
-     * @return the Element which the given command should be inserted before, or null to append to end of list
-     */
-    static public Node findInsertionPoint (Element document_element, Element target_element) {
-        ///ystem.err.println("Find insertion point: " + target_element.getNodeName());
-        String target_element_name = target_element.getNodeName ();
-        
-        // Try to find commands with the same tag.
-        NodeList matching_elements = document_element.getElementsByTagName (target_element_name);
-        // If we found matching elements, then we have our most likely insertion location, so check within for groupings
-        if(matching_elements.getLength () != 0) {
-            ///ystem.err.println("Found matching elements.");
-            // Only CollectionMeta are grouped.
-            if(target_element_name.equals (StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
-                ///ystem.err.println("Dealing with collection metadata");
-                // Special case: CollectionMeta can be added at either the start or end of a collection configuration file. However the start position is reserved for special metadata, so if no non-special metadata can be found we must append to the end.
-                // So if the command to be added is special add it immediately after any other special command
-                if(target_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-                    int index = 0;
-                    Element matched_element = (Element) matching_elements.item (index);
-                    Element sibling_element = (Element) matched_element.getNextSibling ();
-                    while(sibling_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-                        index++;
-                        matched_element = (Element) matching_elements.item (index);
-                        sibling_element = (Element) matched_element.getNextSibling ();
-                    }
-                    if(sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
-                        Element newline_element = document.createElement (NEWLINE_ELEMENT);
-                        document_element.insertBefore (newline_element, sibling_element);
-                    }
-                    return sibling_element;
-                }
-                // Otherwise try to find a matching 'name' and add after the last one in that group.
-                else {
-                    int index = 0;
-                    target_element_name = target_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
-                    boolean found = false;
-                    // Skip all of the special metadata
-                    Element matched_element = (Element) matching_elements.item (index);
-                    while(matched_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
-                        index++;
-                        matched_element = (Element) matching_elements.item (index);
-                    }
-                    // Begin search
-                    while(!found && matched_element != null) {
-                        if(matched_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
-                            found = true;
-                        }
-                        else {
-                            index++;
-                            matched_element = (Element) matching_elements.item (index);
-                        }
-                    }
-                    // If we found a match, we need to continue checking until we find the last name match.
-                    if(found) {
-                        index++;
-                        Element previous_sibling = matched_element;
-                        Element sibling_element = (Element) matching_elements.item (index);
-                        while(sibling_element != null && sibling_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
-                            previous_sibling = sibling_element;
-                            index++;
-                            sibling_element = (Element) matching_elements.item (index);
-                        }
-                        // Previous sibling now holds the command immediately before where we want to add, so find its next sibling and add to that. In this one case we can ignore new lines!
-                        return previous_sibling.getNextSibling ();
-                    }
-                    // If not found we just add after last metadata element
-                    else {
-                        Element last_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
-                        return last_element.getNextSibling ();
-                    }
-                }
-                
-            }
-            else {
-                ///ystem.err.println("Not dealing with collection meta.");
-                Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
-                // One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
-                Node sibling_element = matched_element.getNextSibling ();
-                if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
-                    Element newline_element = document.createElement (NEWLINE_ELEMENT);
-                    document_element.insertBefore (newline_element, sibling_element);
-                }
-                return sibling_element; // Note that this may be null
-            }
-        }
-        ///ystem.err.println("No matching elements found.");
-        // Locate where this command is in the ordering
-        int command_index = -1;
-        for(int i = 0; command_index == -1 && i < COMMAND_ORDER.length; i++) {
-            if(COMMAND_ORDER[i].equals (target_element_name)) {
-                command_index = i;
-            }
-        }
-        ///ystem.err.println("Command index is: " + command_index);
-        // Now move forward, checking for existing elements in each of the preceeding command orders.
-        int preceeding_index = command_index - 1;
-        ///ystem.err.println("Searching before the target command.");
-        while(preceeding_index >= 0) {
-            matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[preceeding_index]);
-            // If we've found a match
-            if(matching_elements.getLength () > 0) {
-                // We add after the last element
-                Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
-                // One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
-                Node sibling_element = matched_element.getNextSibling ();
-                if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
-                    Element newline_element = document.createElement (NEWLINE_ELEMENT);
-                    document_element.insertBefore (newline_element, sibling_element);
-                }
-                return sibling_element; // Note that this may be null
-            }
-            preceeding_index--;
-        }
-        // If all that fails, we now move backwards through the commands
-        int susceeding_index = command_index + 1;
-        ///ystem.err.println("Searching after the target command.");
-        while(susceeding_index < COMMAND_ORDER.length) {
-            matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[susceeding_index]);
-            // If we've found a match
-            if(matching_elements.getLength () > 0) {
-                // We add before the first element
-                Element matched_element = (Element) matching_elements.item (0);
-                // One final quick test. If the matched element is immediately preceeded by a NewLine command, then we insert another NewLine before the matched command, then return this new NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
-                Node sibling_element = matched_element.getPreviousSibling ();
-                if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
-                    Element newline_element = document.createElement (NEWLINE_ELEMENT);
-                    document_element.insertBefore (newline_element, sibling_element);
-                }
-                return sibling_element; // Note that this may be null
-            }
-            susceeding_index++;
-        }
-        // Well. Apparently there are no other commands in this collection configuration. So append away...
-        return null;
-    }
-    // From collectionConfig.xml to internal structure:add 'ex.' namespace (if none).
-    // From internal structure to collectionConfig.xml:always peel off 'ex.' namespace (if any), except for format statement
-    //This method parses 'xml_file_doc' into 'dOc'
-    public void parseCollectionConfigXML (File xml_file, Document dOc) {
-        
-        Document xml_file_doc = XMLTools.parseXMLFile (xml_file);
-        Element fromElement = xml_file_doc.getDocumentElement ();
-        Element toElement = dOc.getDocumentElement ();
-        
-        // It's deliberately set that 'creator', 'maintainer', and 'public' are only in English (as they are just names).
-        // So the following ArrayList have only one element.
-        Node metadataListNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.METADATALIST_STR, 0);
-        if (metadataListNode != null) {
-            ArrayList creator = doMetadataList (dOc, metadataListNode, StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT,
-            StaticStrings.COLLECTIONMETADATA_CREATOR_STR);
-            ArrayList maintainer = doMetadataList (dOc, metadataListNode,
-            StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT,
-            StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR);
-            ArrayList is_public = doMetadataList (dOc, metadataListNode, StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT,
-            StaticStrings.COLLECTIONMETADATA_PUBLIC_STR);
-            
-            appendArrayList (toElement, creator);
-            appendArrayList (toElement, maintainer);
-            appendArrayList (toElement, is_public);
-        }
-        
-        Node searchNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.SEARCH_STR, 0);
-        String buildtype_value = ((Element)searchNode).getAttribute (StaticStrings.TYPE_ATTRIBUTE);//might be mg|mgpp|lucene
-        Element buildtype = doBuildType (dOc, buildtype_value);
-        appendProperly (toElement, buildtype);
-        
-        
-        Node importNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.IMPORT_STR, 0);
-        if (importNode == null) {
-            System.out.println ("There is no content in the 'import' block.");
-        }
-        if (importNode != null) {
-        	//do plugin list nodes
-            Node pluginListNode = XMLTools.getChildByTagNameIndexed ((Element)importNode, StaticStrings.PLUGINLIST_STR, 0);           
-            if (pluginListNode == null) {
-                System.out.println ("There is no pluginlist set.");
-            }
-            if (pluginListNode != null) {
-                
-                doPlugin (dOc, pluginListNode);
-            }
-            
-            //do the plugout element (used by building flax collections)
-            Node plugout = XMLTools.getChildByTagNameIndexed ((Element)importNode, PLUGOUT_ELEMENT, 0);
-            if (plugout != null) {
-            	Element to_element = XMLTools.duplicateElement (dOc, (Element)plugout, true);
-            	toElement.appendChild (to_element);
-            }
-        }
-        
-        Node browseNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.BROWSE_STR, 0);
-        if (browseNode != null) {
-            if (browseNode == null) {
-                System.out.println ("There is no classifier.");
-            }
-            doClassifier (dOc, browseNode);
-        }
-        
-        Node displayItemListNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.DISPLAYITEMLIST_STR, 0);
-        if (displayItemListNode != null) {
-            ArrayList description = doDisplayItemList (dOc, displayItemListNode, StaticStrings.DESCRIPTION_STR,
-            StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR);
-            ArrayList smallicon = doDisplayItemList (dOc, displayItemListNode, StaticStrings.SMALLICON_STR,
-            StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR);
-            ArrayList icon = doDisplayItemList (dOc, displayItemListNode, StaticStrings.ICON_STR,
-            StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR);
-            ArrayList name = doDisplayItemList (dOc, displayItemListNode, StaticStrings.NAME_STR,
-            StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR);
-            
-            appendArrayList (toElement, description);
-            appendArrayList (toElement, smallicon);
-            appendArrayList (toElement, icon);
-            appendArrayList (toElement, name);
-        }
-        
-        if (buildtype_value.equalsIgnoreCase ("mg")) {
-            doMGIndexes (dOc, searchNode);
-        }
-        else {
-            doMGPPIndexes (dOc, searchNode);
-        }
-        
-        doDefaultIndex (dOc, searchNode);
-        //doSearchType (dOc, searchNode);
-        doDefaultLevel (dOc, searchNode);
-        doLevel (dOc, searchNode);
-        doIndexOption (dOc, searchNode);
-        doSubcollection (dOc, searchNode);
-        doIndexSubcollection (dOc, searchNode);
-        doIndexLanguage (dOc, searchNode);
-        doDefaultIndexLanguage (dOc, searchNode);
-        doLanguageMetadata (dOc, searchNode);
-        doSearchFormat (dOc, searchNode);
-        doDisplayFormat (dOc, fromElement);
-        doReplaceListRef (dOc, fromElement);
-        doOAIElement (dOc, fromElement);
-        
-    }
-    
-    
-    public void saveCollectionConfigXML (File collect_cfg_file, Document doc) {
-        //In this method, the file collect_cfg_file must be 'collectionConfig.xml'
-        
-        
-        //Compare the internal structure (doc) with the saved structure from collectionConfig.xml and see if it has changed
-        StringBuffer collect_cfg_string_buffer = new StringBuffer (XMLTools.xmlNodeToString (doc));
-        String collect_cfg_string = collect_cfg_string_buffer.toString ();
-        if (saved_collect_cfg_string_buffer != null) {
-            String saved_collect_cfg_string = saved_collect_cfg_string_buffer.toString ();
-            if (collect_cfg_string.equals (saved_collect_cfg_string)) {
-                DebugStream.println ("'collectionConfig.xml' file hasn't changed so no save necessary...");
-                return;
-            }
-        }
-        
-        DebugStream.println ("'collectionConfig.xml' file has changed, saving now...");
-        
-        // If we're using the Local Library we must release the collection before writing to the collect.cfg file
-        String collection_name = Gatherer.c_man.getCollection ().getName ();
-        boolean collection_released = false;
-        if (Gatherer.c_man.built () && LocalLibraryServer.isRunning () == true) {
-            // Release the collection
-            LocalLibraryServer.releaseCollection (collection_name);
-            collection_released = true;
-        }
-        
-        // Make a backup of the collectionConfig.xml file so that the user can manully change back
-        if (collect_cfg_file.exists ()) {
-            
-            File original_file = new File (collect_cfg_file.getParentFile (), Utility.COLLECTION_CONFIG_XML);
-            File backup_file = new File (collect_cfg_file.getParentFile (), Utility.COLLECTION_CONFIG_BAK);
-            if (backup_file.exists ()) {
-                backup_file.delete ();
-            }
-            if (!original_file.renameTo (backup_file)) {
-                System.err.println ("Warning: can't rename collectionConfig.xml to collectionConfig.bak.");
-            }
-        }
-        
-        Document collection_config_xml_document = convertInternalToCollectionConfig (doc);
-        String[] nonEscapingTagNames = {StaticStrings.FORMAT_STR};
-        XMLTools.writeXMLFile (collect_cfg_file, collection_config_xml_document, nonEscapingTagNames);
-        saved_collect_cfg_string_buffer = collect_cfg_string_buffer;
-        
-        // If we're using a remote Greenstone server, upload the new 'collectionConfig.xml' file
-        if (Gatherer.isGsdlRemote) {
-            Gatherer.remoteGreenstoneServer.uploadCollectionFile (collection_name, collect_cfg_file);
-        }
-        
-        // Now re-add the collection to the Local Library server
-        if (collection_released) {
-            LocalLibraryServer.addCollection (collection_name);
-        }
-        
-    }
-    public void saveIfNecessary () {
-        if (Gatherer.GS3 == true) {
-            saveCollectionConfigXML (collect_cfg_file, document);
-            return;
-        }
-        // Convert the collection configuration XML tree to the collect.cfg version
-        StringBuffer collect_cfg_string_buffer = new StringBuffer ();
-        NodeList command_elements = document.getDocumentElement ().getChildNodes ();
-        boolean just_wrote_blank_line = false;  // Prevent two or more blank lines in a row
-        for (int i = 0; i < command_elements.getLength (); i++) {
-            Node command_node = command_elements.item (i);
-            if (!(command_node instanceof Element)) {
-                // We're only interested in Elements
-                continue;
-            }
-            Element command_element = (Element) command_node;
-            
-            // Handle NewLine elements (blank lines)
-            if (command_element.getNodeName ().equals (NEWLINE_ELEMENT) && !just_wrote_blank_line) {
-                collect_cfg_string_buffer.append ("\n");
-                just_wrote_blank_line = true;
-            }
-            
-            // Anything else we write to file, but only if it has been assigned, except for index and level commands
-            // (which just get commented out if unassigned -- a side effect of MG & MGPP compatibility)
-            else if (!command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR) || command_element.getNodeName ().equals (StaticStrings.INDEXES_ELEMENT) || command_element.getNodeName ().equals (StaticStrings.INDEX_DEFAULT_ELEMENT) || command_element.getNodeName ().equals (StaticStrings.INDEXOPTIONS_ELEMENT) || command_element.getNodeName ().equals (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT)) {
-	      String command = toString(command_element);
-//                 if (command_element.getNodeName ().equals (StaticStrings.FORMAT_ELEMENT)) {
-//                     // Format statements we write out with ex. still present
-// 		  command = toString (command_element); //, true);
-//                 }
-//                 else {
-// 		  command = toString (command_element);//, false);
-//                 }
-                
-                if (command != null && command.length ()> 0 ) {
-                    collect_cfg_string_buffer.append (command + "\n");
-                    just_wrote_blank_line = false;
-                }
-            }
-        }
-        
-        String collect_cfg_string = collect_cfg_string_buffer.toString ();
-        String saved_collect_cfg_string = saved_collect_cfg_string_buffer.toString ();
-        if (collect_cfg_string.equals (saved_collect_cfg_string)) {
-            DebugStream.println ("Collect.cfg file hasn't changed so no save necessary...");
-            return;
-        }
-        
-        DebugStream.println ("Collect.cfg file has changed, saving now...");
-        
-        // If we're using the Local Library we must release the collection before writing to the collect.cfg file
-        String collection_name = CollectionManager.getLoadedCollectionName ();
-        boolean collection_released = false;
-        if (Gatherer.c_man.built () && LocalLibraryServer.isRunning () == true) {
-            // Release the collection
-            LocalLibraryServer.releaseCollection (collection_name);
-            collection_released = true;
-        }
-        
-        // Make a backup of the collect.cfg file
-        if (collect_cfg_file.exists ()) {
-            File original_file = new File (collect_cfg_file.getParentFile (), StaticStrings.COLLECT_CFG);
-            File backup_file = new File (collect_cfg_file.getParentFile (), Utility.COLLECT_BAK);
-            if (backup_file.exists ()) {
-                backup_file.delete ();
-            }
-            if (!original_file.renameTo (backup_file)) {
-                System.err.println ("Warning: can't rename collect.cfg to collect.bak.");
-            }
-        }
-        
-        try {
-            OutputStream ostream = new FileOutputStream (collect_cfg_file);
-            Writer file_writer = new OutputStreamWriter (ostream, ENCODING);
-            BufferedWriter buffered_writer = new BufferedWriter (file_writer);
-            buffered_writer.write (collect_cfg_string);
-            buffered_writer.close ();
-            
-            saved_collect_cfg_string_buffer = collect_cfg_string_buffer;
-            
-            // If we're using a remote Greenstone server, upload the new collect.cfg file
-            if (Gatherer.isGsdlRemote) {
-                Gatherer.remoteGreenstoneServer.uploadCollectionFile (collection_name, collect_cfg_file);
-            }
-        }
-        catch (Exception exception) {
-            DebugStream.println ("Error in CollectionConfiguration.save(): " + exception);
-            DebugStream.printStackTrace (exception);
-        }
-        
-        // Now re-add the collection to the Local Library server
-        if (collection_released) {
-            LocalLibraryServer.addCollection (collection_name);
-        }
-    }
-    // This method is initilised in CollectionDesignManager.java constructor
-    public CollectionConfiguration (File collect_cfg_file) {
-        this.collect_cfg_file = collect_cfg_file;
-        
-        // parse the XML template
-        document = XMLTools.parseXMLFile ("xml/CollectionConfig.xml", true);
-        String filename = collect_cfg_file.getName ().toLowerCase ();
-        
-        if (filename.endsWith (".cfg")) {
-            parse (collect_cfg_file);
-        }
-        if (filename.endsWith (".xml")) {
-            parseCollectionConfigXML (collect_cfg_file, document);
-        }
-        
-        //XMLTools.printXMLNode(document.getDocumentElement());
-    }
-    
-    // Append the elements, which are of Element type, in 'list' to Element 'to'
-    private void appendArrayList (Element to, ArrayList list) {
-        if (list == null) return;
-        
-        for (int i=0; i<list.size (); i++) {
-            appendProperly (to, (Element)list.get (i));
-        }
-    }
-    //Convert the internal XML DOM tree (dOc) into that of collectionConfig.xml (skeleton)
-    public Document convertInternalToCollectionConfig (Document dOc) {
-        //first parse an empty skeleton of xml config file
-        //The aim is to convert the internal structure into this skeleton
-        Document skeleton = XMLTools.parseXMLFile ("xml/CollectionConfig.xml", true);
-        //Element internal = dOc.getDocumentElement();
-        convertMetadataList (dOc, skeleton);
-        convertDisplayItemList (dOc, skeleton);
-        convertBuildType (dOc, skeleton);
-        convertIndex (dOc, skeleton);
-        convertPlugin (dOc, skeleton);//also do the plugout element
-        convertClassifier (dOc, skeleton);
-        convertSubcollectionIndexes (dOc, skeleton);
-        convertLanguages (dOc, skeleton);
-        convertSubcollection (dOc, skeleton);
-        convertSearchType (dOc, skeleton);
-        convertSearchFormat (dOc, skeleton);
-        convertDisplayFormat (dOc, skeleton);
-        convertReplaceListRef (dOc, skeleton);
-        convertOAIElement(dOc, skeleton);
-
-        return skeleton;
-    }
-
-  static private HashMap plugin_map = null;
+	config_filename = StaticStrings.COLLECT_CFG;
+	backup_filename = Utility.COLLECT_BAK;
+      }	
+      File original_file = new File (collect_config_file.getParentFile (), config_filename);
+      File backup_file = new File (collect_config_file.getParentFile (), backup_filename);
+      if (backup_file.exists ()) {
+	backup_file.delete ();
+      }
+      if (!original_file.renameTo (backup_file)) {
+	System.err.println ("Warning: can't rename "+config_filename + " to "+ backup_filename);
+      }
+    }
+
+    // now save the file
+    if (Gatherer.GS3) {
+      CollectionConfigXMLReadWrite.save(collect_config_file, document);
+    } else {
+      // we have already converted to string, so save here
+      try {
+	OutputStream ostream = new FileOutputStream (collect_config_file);
+	Writer file_writer = new OutputStreamWriter (ostream, ENCODING);
+	BufferedWriter buffered_writer = new BufferedWriter (file_writer);
+	buffered_writer.write (config_file_string);
+	buffered_writer.close ();
+      }
+      catch (Exception exception) {
+	DebugStream.println ("Error in CollectionConfiguration.save(): " + exception);
+	DebugStream.printStackTrace (exception);
+      }
+      
+    }
+
+    // save the string version
+    saved_config_file_string = config_file_string;
+    
+    // If we're using a remote Greenstone server, upload the new collect.cfg file
+    if (Gatherer.isGsdlRemote) {
+      Gatherer.remoteGreenstoneServer.uploadCollectionFile (collection_name, collect_config_file);
+    }
   
-  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;
-  }
-   
-
-    ///*********************************************************************************************************///
+        
+    // Now re-add the collection to the Local Library server
+    if (collection_released) {
+      LocalLibraryServer.addCollection (collection_name);
+    }
+  }
+
+ 
+    
 }
 
+
