Changeset 20447


Ignore:
Timestamp:
08/31/09 14:40:43 (12 years ago)
Author:
kjdon
Message:

split CollectionConfiguration into three files: CollectionConfiguration handles all the DOM internal stuff, while CollectCfgReadWrite and CollectionConfigXMLReadWrite handle reading from and writing to collect.cfg and collectionConfig.xml files, respectively. This class was jsut getting far too big and I could never find anything in it...

Location:
gli/trunk/src/org/greenstone/gatherer/cdm
Files:
2 added
1 edited

Legend:

Unmodified
Added
Removed
  • gli/trunk/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java

    r20445 r20447  
    3232import java.util.*;
    3333import javax.swing.*;
    34 import org.greenstone.gatherer.Configuration;
    3534import org.greenstone.gatherer.DebugStream;
    3635import org.greenstone.gatherer.Gatherer;
     
    3837import org.greenstone.gatherer.greenstone.LocalLibraryServer;
    3938import org.greenstone.gatherer.gui.GLIButton;
    40 import org.greenstone.gatherer.metadata.MetadataElement;
    41 import org.greenstone.gatherer.metadata.MetadataSetManager;
    42 import org.greenstone.gatherer.metadata.MetadataTools;
    4339import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
    4440import org.greenstone.gatherer.util.DOMTree;
    45 import org.greenstone.gatherer.util.Codec;
    4641import org.greenstone.gatherer.util.StaticStrings;
    4742import org.greenstone.gatherer.util.XMLTools;
     
    5146/** 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).
    5247 * @author John Thompson, Greenstone Digital Library, University of Waikato
    53  * @version 2.3d
    5448 */
    5549public class CollectionConfiguration {
    56     static final private String ENCODING = "UTF-8";
    57     static final private String NEWLINE_ELEMENT = "NewLine";
    58     static final private String PLUGOUT_ELEMENT = "plugout";//used by building flax collections
    59    
    60     static private Document document;
    61     static private StringBuffer saved_collect_cfg_string_buffer = null;
    62    
    63    
    64     static public Element createElement (String element_name) {
    65         return document.createElement (element_name);
    66     }
    67    
    68    
    69     /** 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.
    70      * @param target_element the command Element to be inserted
    71      * @return the Element which the given command should be inserted before, or null to append to end of list
    72      */
    73     static public Node findInsertionPoint (Element target_element) {
    74         ///ystem.err.println("Find insertion point: " + target_element.getNodeName());
    75         String target_element_name = target_element.getNodeName ();
    76         Element document_element = document.getDocumentElement ();
    77         // Try to find commands with the same tag.
    78         NodeList matching_elements = document_element.getElementsByTagName (target_element_name);
    79         // If we found matching elements, then we have our most likely insertion location, so check within for groupings
    80         if(matching_elements.getLength () != 0) {
    81             ///ystem.err.println("Found matching elements.");
    82             // Only CollectionMeta are grouped.
    83             if(target_element_name.equals (StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
    84                 ///ystem.err.println("Dealing with collection metadata");
    85                 // 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.
    86                 // So if the command to be added is special add it immediately after any other special command
    87                 if(target_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    88                     int index = 0;
    89                     Element matched_element = (Element) matching_elements.item (index);
    90                     Element sibling_element = (Element) matched_element.getNextSibling ();
    91                     while(sibling_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    92                         index++;
    93                         matched_element = (Element) matching_elements.item (index);
    94                         sibling_element = (Element) matched_element.getNextSibling ();
    95                     }
    96                     if(sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
    97                         Element newline_element = document.createElement (NEWLINE_ELEMENT);
    98                         document_element.insertBefore (newline_element, sibling_element);
    99                     }
    100                     return sibling_element;
    101                 }
    102                 // Otherwise try to find a matching 'name' and add after the last one in that group.
    103                 else {
    104                     int index = 0;
    105                     target_element_name = target_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    106                     boolean found = false;
    107                     // Skip all of the special metadata
    108                     Element matched_element = (Element) matching_elements.item (index);
    109                     while(matched_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    110                         index++;
    111                         matched_element = (Element) matching_elements.item (index);
    112                     }
    113                     // Begin search
    114                     while(!found && matched_element != null) {
    115                         if(matched_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
    116                             found = true;
    117                         }
    118                         else {
    119                             index++;
    120                             matched_element = (Element) matching_elements.item (index);
    121                         }
    122                     }
    123                     // If we found a match, we need to continue checking until we find the last name match.
    124                     if(found) {
    125                         index++;
    126                         Element previous_sibling = matched_element;
    127                         Element sibling_element = (Element) matching_elements.item (index);
    128                         while(sibling_element != null && sibling_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
    129                             previous_sibling = sibling_element;
    130                             index++;
    131                             sibling_element = (Element) matching_elements.item (index);
    132                         }
    133                         // 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!
    134                         return previous_sibling.getNextSibling ();
    135                     }
    136                     // If not found we just add after last metadata element
    137                     else {
    138                         Element last_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
    139                         return last_element.getNextSibling ();
    140                     }
    141                 }
     50  static final public String ENCODING = "UTF-8";
     51  static final public String NEWLINE_ELEMENT = "NewLine";
     52   
     53  static private Document document;
     54  static private String saved_config_file_string = null;
     55   
     56  // may be collec.cfg (GS2) or collectionConfig.xml (GS3)
     57  private File collect_config_file;
     58  private String collect_config_filename;
     59 
     60  // This method is initilised in CollectionDesignManager.java constructor
     61  public CollectionConfiguration (File collect_config_file) {
     62    this.collect_config_file = collect_config_file;
     63    this.collect_config_filename = collect_config_file.getName();
     64    // parse the XML template
     65    document = XMLTools.parseXMLFile ("xml/CollectionConfig.xml", true);
     66    String filename = collect_config_filename.toLowerCase ();
     67       
     68    if (filename.endsWith (".cfg")) {
     69      saved_config_file_string = CollectCfgReadWrite.parse (collect_config_file, document);
     70    }
     71    else if (filename.endsWith (".xml")) {
     72      CollectionConfigXMLReadWrite.parse (collect_config_file, document);
     73    }
     74       
     75    //XMLTools.printXMLNode(document.getDocumentElement());
     76  }
     77
     78  static public Element createElement (String element_name) {
     79    return document.createElement (element_name);
     80  }
     81   
     82  /** Gives the preferred ordering of commands */
     83  static final public String[] COMMAND_ORDER =
     84  {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};
     85     
     86  /** 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.
     87   * @param target_element the command Element to be inserted
     88   * @return the Element which the given command should be inserted before, or null to append to end of list
     89   */
     90  static public Node findInsertionPoint (Element target_element) {
     91    ///ystem.err.println("Find insertion point: " + target_element.getNodeName());
     92    String target_element_name = target_element.getNodeName ();
     93    Element document_element = document.getDocumentElement ();
     94    // Try to find commands with the same tag.
     95    NodeList matching_elements = document_element.getElementsByTagName (target_element_name);
     96    // If we found matching elements, then we have our most likely insertion location, so check within for groupings
     97    if(matching_elements.getLength () != 0) {
     98      ///ystem.err.println("Found matching elements.");
     99      // Only CollectionMeta are grouped.
     100      if(target_element_name.equals (StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
     101    ///ystem.err.println("Dealing with collection metadata");
     102    // 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.
     103    // So if the command to be added is special add it immediately after any other special command
     104    if(target_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
     105      int index = 0;
     106      Element matched_element = (Element) matching_elements.item (index);
     107      Element sibling_element = (Element) matched_element.getNextSibling ();
     108      while(sibling_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
     109        index++;
     110        matched_element = (Element) matching_elements.item (index);
     111        sibling_element = (Element) matched_element.getNextSibling ();
     112      }
     113      if(sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
     114        Element newline_element = document.createElement (NEWLINE_ELEMENT);
     115        document_element.insertBefore (newline_element, sibling_element);
     116      }
     117      return sibling_element;
     118    }
     119    // Otherwise try to find a matching 'name' and add after the last one in that group.
     120    else {
     121      int index = 0;
     122      target_element_name = target_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
     123      boolean found = false;
     124      // Skip all of the special metadata
     125      Element matched_element = (Element) matching_elements.item (index);
     126      while(matched_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
     127        index++;
     128        matched_element = (Element) matching_elements.item (index);
     129      }
     130      // Begin search
     131      while(!found && matched_element != null) {
     132        if(matched_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
     133          found = true;
     134        }
     135        else {
     136          index++;
     137          matched_element = (Element) matching_elements.item (index);
     138        }
     139      }
     140      // If we found a match, we need to continue checking until we find the last name match.
     141      if(found) {
     142        index++;
     143        Element previous_sibling = matched_element;
     144        Element sibling_element = (Element) matching_elements.item (index);
     145        while(sibling_element != null && sibling_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
     146          previous_sibling = sibling_element;
     147          index++;
     148          sibling_element = (Element) matching_elements.item (index);
     149        }
     150        // 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!
     151        return previous_sibling.getNextSibling ();
     152      }
     153      // If not found we just add after last metadata element
     154      else {
     155        Element last_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
     156        return last_element.getNextSibling ();
     157      }
     158    }
    142159               
    143             }
    144             else {
    145                 ///ystem.err.println("Not dealing with collection meta.");
    146                 Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
    147                 // 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)
    148                 Node sibling_element = matched_element.getNextSibling ();
    149                 if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
    150                     Element newline_element = document.createElement (NEWLINE_ELEMENT);
    151                     document_element.insertBefore (newline_element, sibling_element);
    152                 }
    153                 return sibling_element; // Note that this may be null
    154             }
    155         }
    156         ///ystem.err.println("No matching elements found.");
    157         // Locate where this command is in the ordering
    158         int command_index = -1;
    159         for(int i = 0; command_index == -1 && i < COMMAND_ORDER.length; i++) {
    160             if(COMMAND_ORDER[i].equals (target_element_name)) {
    161                 command_index = i;
    162             }
    163         }
    164         ///ystem.err.println("Command index is: " + command_index);
    165         // Now move forward, checking for existing elements in each of the preceeding command orders.
    166         int preceeding_index = command_index - 1;
    167         ///ystem.err.println("Searching before the target command.");
    168         while(preceeding_index >= 0) {
    169             matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[preceeding_index]);
    170             // If we've found a match
    171             if(matching_elements.getLength () > 0) {
    172                 // We add after the last element
    173                 Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
    174                 // 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)
    175                 Node sibling_element = matched_element.getNextSibling ();
    176                 if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
    177                     Element newline_element = document.createElement (NEWLINE_ELEMENT);
    178                     document_element.insertBefore (newline_element, sibling_element);
    179                 }
    180                 return sibling_element; // Note that this may be null
    181             }
    182             preceeding_index--;
    183         }
    184         // If all that fails, we now move backwards through the commands
    185         int susceeding_index = command_index + 1;
    186         ///ystem.err.println("Searching after the target command.");
    187         while(susceeding_index < COMMAND_ORDER.length) {
    188             matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[susceeding_index]);
    189             // If we've found a match
    190             if(matching_elements.getLength () > 0) {
    191                 // We add before the first element
    192                 Element matched_element = (Element) matching_elements.item (0);
    193                 // 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)
    194                 Node sibling_element = matched_element.getPreviousSibling ();
    195                 if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
    196                     Element newline_element = document.createElement (NEWLINE_ELEMENT);
    197                     document_element.insertBefore (newline_element, sibling_element);
    198                 }
    199                 return sibling_element; // Note that this may be null
    200             }
    201             susceeding_index++;
    202         }
    203         // Well. Apparently there are no other commands in this collection configuration. So append away...
    204         return null;
    205     }
    206    
    207    
    208     static public NodeList getElementsByTagName (String element_name) {
    209         return document.getDocumentElement ().getElementsByTagName (element_name);
    210     }
    211    
    212    
    213   static public String toString (Element command_element) {
    214         String command_element_name = command_element.getNodeName ();
    215         if(command_element_name.equals (StaticStrings.CLASSIFY_ELEMENT)) {
    216             return classifyToString (command_element);
    217         }
    218         else if(command_element_name.equals (StaticStrings.FORMAT_ELEMENT)) {
    219             return formatToString (command_element);
    220         }
    221         else if(command_element_name.equals (StaticStrings.INDEXES_ELEMENT)) {
    222             return indexesToString (command_element);
    223         }
    224         else if(command_element_name.equals (StaticStrings.INDEX_DEFAULT_ELEMENT)) {
    225             return indexDefaultToString (command_element);
    226         }
    227         else if(command_element_name.equals (StaticStrings.LANGUAGES_ELEMENT)) {
    228             return languagesToString (command_element);
    229         }
    230         else if(command_element_name.equals (StaticStrings.LANGUAGE_DEFAULT_ELEMENT)) {
    231             return languageDefaultToString (command_element);
    232         }
    233         else if (command_element_name.equals (StaticStrings.LANGUAGE_METADATA_ELEMENT)) {
    234             return languageMetadataToString (command_element);
    235         }
    236         else if(command_element_name.equals (StaticStrings.INDEXOPTIONS_ELEMENT)) {
    237             return indexOptionsToString (command_element);
    238         }
    239         else if(command_element_name.equals (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT)) {
    240             return indexOptionDefaultToString (command_element);
    241         }
    242         else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
    243       return metadataToString (command_element);
    244         }
    245         else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT)) {
    246       return metadataToString (command_element);
    247         }
    248         else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT)) {
    249             return metadataToString (command_element);
    250         }
    251         else if(command_element_name.equals (StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT)) {
    252             return metadataToString (command_element);
    253         }
    254         else if (command_element_name.equals (StaticStrings.BUILDTYPE_ELEMENT)) {
    255             return metadataToString (command_element);
    256         }
    257         else if(command_element_name.equals (StaticStrings.PLUGIN_ELEMENT)) {
    258             return pluginToString (command_element);
    259         }
    260         else if(command_element_name.equals (StaticStrings.SUBCOLLECTION_ELEMENT)) {
    261             return subcollectionToString (command_element);
    262         }
    263         else if(command_element_name.equals (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT)) {
    264             return subcollectionDefaultIndexToString (command_element);
    265         }
    266         else if(command_element_name.equals (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT)) {
    267             return subcollectionIndexesToString (command_element);
    268         }
    269         else if(command_element_name.equals (StaticStrings.SUPERCOLLECTION_ELEMENT)) {
    270             return supercollectionToString (command_element);
    271         }
    272         else if(command_element_name.equals (StaticStrings.UNKNOWN_ELEMENT)) {
    273             return unknownToString (command_element);
    274         }
    275         return "";
    276     }
    277    
    278     /** 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.
    279      * @param tokenizer a CommandTokenizer based on the unconsumed portion of a command string
    280      * @return a HashMap containing the arguments parsed
    281      */
    282     static public HashMap parseArguments (CommandTokenizer tokenizer) {
    283         HashMap arguments = new HashMap ();
    284         String name = null;
    285         String value = null;
    286         while(tokenizer.hasMoreTokens () || name != null) {
    287             // First we retrieve a name if we need one.
    288             if(name == null) {
    289                 name = tokenizer.nextToken ();
    290             }
    291             // Now we attempt to retrieve a value
    292             if(tokenizer.hasMoreTokens ()) {
    293                 value = tokenizer.nextToken ();
    294                 // 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.
    295         // The value is not a name if it contains a space character: it's a quoted value
    296                 if (value.startsWith(StaticStrings.MINUS_CHARACTER) && value.indexOf(StaticStrings.SPACE_CHARACTER) == -1) {
    297                     arguments.put (name, null);
    298                     name = value;
    299                 }
    300                 // Otherwise we have a typical name->value pair ready to go
    301                 else {
    302                     arguments.put (name, value);
    303                     name = null;
    304                 }
    305             }
    306             // Otherwise its a binary flag
    307             else {
    308                 arguments.put (name, null);
    309                 name = null;
    310             }
    311         }
    312         return arguments;
    313     }
    314    
    315     /** Gives the preferred ordering of commands */
    316     static final private String[] COMMAND_ORDER =
    317     {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};
    318    
    319     /** ************************** Public Data Members ***************************/
    320    
    321     /** ************************** Private Data Members ***************************/
    322    
    323     private File collect_cfg_file;
    324    
    325     /** ************************** Public Methods ***************************/
    326    
    327    
    328     /** This debug facility shows the currently loaded collect.cfg or CollectConfig.xml file as a DOM tree. */
    329     public void display () {
    330         JDialog dialog = new JDialog (Gatherer.g_man, "Collection Configuration", false);
    331         dialog.setSize (400,400);
    332         JPanel content_pane = (JPanel) dialog.getContentPane ();
    333         final DOMTree tree = new DOMTree (document);
    334         JButton refresh_button = new GLIButton ("Refresh Tree");
    335         refresh_button.addActionListener (new ActionListener () {
    336             public void actionPerformed (ActionEvent event) {
    337                 tree.setDocument (document);
    338             }
    339         });
    340         content_pane.setBorder (BorderFactory.createEmptyBorder (5,5,5,5));
    341         content_pane.setLayout (new BorderLayout ());
    342         content_pane.add (new JScrollPane (tree), BorderLayout.CENTER);
    343         content_pane.add (refresh_button, BorderLayout.SOUTH);
    344         dialog.setVisible (true);
    345     }
    346    
    347    
    348     public Element getCreator () {
    349         Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, null, null);
    350         element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_CREATOR_STR);
    351         element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
    352         return element;
    353     }
    354    
    355     public Element getDocumentElement () {
    356         return document.getDocumentElement ();
    357     }
    358    
    359     public File getFile () {
    360         return collect_cfg_file;
    361     }
    362    
    363     /** Retrieve or create the languages Element. */
    364     public Element getLanguages () {
    365         return getOrCreateElementByTagName (StaticStrings.LANGUAGES_ELEMENT, null, null);
    366     }
    367    
    368     public Element getLanguageMetadata () {
    369         return getOrCreateElementByTagName (StaticStrings.LANGUAGE_METADATA_ELEMENT, null, null);
    370     }
    371    
    372     public Element getLevels () {
    373         return getOrCreateElementByTagName (StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVELS_STR);
    374     }
    375    
    376     public Element getLevelDefault () {
    377         return getOrCreateElementByTagName (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVEL_DEFAULT_STR);
    378     }
    379    
    380     public Element getIndexOptions () {
    381         return getOrCreateElementByTagName (StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.INDEXOPTIONS_STR);
    382     }
    383    
    384    
    385     public Element getMaintainer () {
    386         Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, null, null);
    387         element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR);
    388         element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
    389         return element;
    390     }
    391    
    392     /** 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. */
    393     public Element getMGIndexes () {
    394         return getOrCreateElementByTagName (StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
    395     }
    396    
    397     public Element getMGPPIndexes () {
    398         return getOrCreateElementByTagName (StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
    399     }
    400    
    401     public Element getPublic () {
    402         Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, null, null);
    403         element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_PUBLIC_STR);
    404         element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
    405         return element;
    406     }
    407    
    408     public Element getBuildType () {
    409         Element element = getOrCreateElementByTagName (StaticStrings.BUILDTYPE_ELEMENT, null, null);
    410         element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
    411         element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
    412         return element;
    413        
    414     }
    415    
    416     /** Retrieve or create the subindexes Element. */
    417     public Element getSubIndexes () {
    418         return getOrCreateElementByTagName (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, null, null);
    419     }
    420    
    421     /** Retrieve or create the supercollections Element. */
    422     public Element getSuperCollection () {
    423         return getOrCreateElementByTagName (StaticStrings.SUPERCOLLECTION_ELEMENT, null, null);
    424     }
    425    
    426     public boolean ready () {
    427         return document != null;
    428     }
    429    
    430    
    431    
    432    
    433     /** ************************** Private Methods ***************************/
    434    
    435     static private String classifyToString (Element command_element) {
    436         StringBuffer text = new StringBuffer (StaticStrings.CLASSIFY_STR);
    437         text.append (StaticStrings.TAB_CHARACTER);
    438         text.append (command_element.getAttribute (StaticStrings.TYPE_ATTRIBUTE));
    439         NodeList option_elements = command_element.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
    440         int option_elements_length = option_elements.getLength ();
    441         for(int j = 0; j < option_elements_length; j++) {
    442       Element option_element = (Element) option_elements.item (j);
    443             if(option_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    444           text.append (StaticStrings.SPACE_CHARACTER);
    445           text.append (StaticStrings.MINUS_CHARACTER);
    446           text.append (option_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    447           String value_str = XMLTools.getValue (option_element);
    448    
    449           //          value_str = modifyMetadataArgumentValue(value_str);
    450           if (value_str.length () > 0) {
    451         text.append (StaticStrings.SPACE_CHARACTER);
    452         if(value_str.indexOf (StaticStrings.SPACE_CHARACTER) != -1) {
    453             // enclose in quotes
    454             text.append(StaticStrings.SPEECH_CHARACTER);
    455             text.append(value_str);
    456             text.append(StaticStrings.SPEECH_CHARACTER);
    457         } else {
    458            
    459             text.append(value_str);
    460         }
    461           }
    462              
    463           value_str = null;
    464             }
    465             option_element = null;
    466         }
    467         option_elements = null;
    468         return text.toString ();
    469     }
    470    
    471     static private String formatToString (Element command_element) {
    472         StringBuffer text = new StringBuffer (StaticStrings.FORMAT_STR);
    473         text.append (StaticStrings.SPACE_CHARACTER);
    474         text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    475         text.append (StaticStrings.SPACE_CHARACTER);
    476         String value_str = command_element.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
    477         if(value_str.length () != 0) {
    478             text.append (value_str);
    479         }
    480         else {
    481             // Remember to encode format string to Greenstone specification
    482             value_str = Codec.transform (XMLTools.getValue (command_element), Codec.DOM_TO_GREENSTONE);
    483             text.append (StaticStrings.SPEECH_CHARACTER);
    484             text.append (value_str);
    485             text.append (StaticStrings.SPEECH_CHARACTER);
    486         }
    487         value_str = null;
    488         return text.toString ();
    489     }
    490    
    491     /** Retrieve or create the indexes Element. */
    492     static private Element getOrCreateElementByTagName (String name, String conditional_attribute, String required_value) {
    493         Element document_element = document.getDocumentElement ();
    494         NodeList elements = document_element.getElementsByTagName (name);
    495         int elements_length = elements.getLength ();
    496         if(elements_length > 0) {
    497             if(conditional_attribute == null) {
    498                 document_element = null;
    499                 return (Element) elements.item (0);
    500             }
    501             else {
    502                 for(int i = 0; i < elements_length; i++) {
    503                     Element element = (Element) elements.item (i);
    504                     if(element.getAttribute (conditional_attribute).equals (required_value)) {
    505                         document_element = null;
    506                         return element;
    507                     }
    508                     element = null;
    509                 }
    510             }
    511         }
    512         // Create the element
    513         Element element = document.createElement (name);
    514         // If there was a property set it
    515         if(conditional_attribute != null) {
    516             element.setAttribute (conditional_attribute, required_value);
    517         }
    518         Node target_node = findInsertionPoint (element);
    519         if(target_node != null) {
    520             document_element.insertBefore (element, target_node);
    521         }
    522         else {
    523             document_element.appendChild (element);
    524         }
    525         document_element = null;
    526         return element;
    527     }
    528    
    529     static private String indexesToString (Element command_element) {
    530         boolean comment_only = false;
    531         StringBuffer text = new StringBuffer ("");
    532         if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    533             text.append ("#");
    534             comment_only = true;
    535         }
    536         text.append (StaticStrings.INDEX_STR);
    537         text.append (StaticStrings.TAB_CHARACTER);
    538         if(!comment_only) {
    539             text.append (StaticStrings.TAB_CHARACTER);
    540         }
    541         NodeList index_elements = command_element.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
    542         if (index_elements.getLength () == 0) { // no indexes
    543             return "";
    544         }
    545         // For each index, write its level, a colon, then concatenate its child content elements into a single comma separated list
    546         int index_elements_length = index_elements.getLength ();
    547         for(int j = 0; j < index_elements_length; j++) {
    548             Element index_element = (Element) index_elements.item (j);
    549             String level_str = index_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE);
    550             if(level_str.length () > 0) {
    551                 text.append (level_str);
    552                 text.append (StaticStrings.COLON_CHARACTER);
    553             }
    554             NodeList content_elements = index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
    555             int content_elements_length = content_elements.getLength ();
    556             // Don't output anything if no indexes are set
    557             if(content_elements_length == 0) {
    558                 return null;
    559             }
    560             for(int k = 0; k < content_elements_length; k++) {
    561                 Element content_element = (Element) content_elements.item (k);
    562                 String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    563                 text.append (name_str);
    564                 name_str = null;
    565                 if(k < content_elements_length - 1) {
    566                     text.append (StaticStrings.COMMA_CHARACTER);
    567                 }
    568                 content_element = null;
    569             }
    570             if(j < index_elements_length - 1) {
    571                 text.append (StaticStrings.SPACE_CHARACTER);
    572             }
    573             content_elements = null;
    574             index_element = null;
    575         }
    576         index_elements = null;
    577         return text.toString ();
    578     }
    579    
    580     static private String indexDefaultToString (Element command_element) {
    581         StringBuffer text = new StringBuffer ("");
    582         if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    583             text.append ("#");
    584         }
    585         text.append (StaticStrings.INDEX_DEFAULT_STR);
    586         text.append (StaticStrings.TAB_CHARACTER);
    587         if (!command_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE).equals ("")) {
    588             text.append (command_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE));
    589             text.append (StaticStrings.COLON_CHARACTER);
    590         }
    591         NodeList content_elements = command_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
    592         int content_elements_length = content_elements.getLength ();
    593         for(int j = 0; j < content_elements_length; j++) {
    594             Element content_element = (Element) content_elements.item (j);
    595             String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    596             text.append (name_str);
    597             name_str = null;
    598             if(j < content_elements_length - 1) {
    599                 text.append (StaticStrings.COMMA_CHARACTER);
    600             }
    601             content_element = null;
    602         }
    603         content_elements = null;
    604         return text.toString ();
    605     }
    606    
    607     static private String languagesToString (Element command_element) {
    608         StringBuffer text = new StringBuffer (StaticStrings.LANGUAGES_STR);
    609         text.append (StaticStrings.TAB_CHARACTER);
    610         // Retrieve all the languages and write them out in a space separated list
    611         NodeList language_elements = command_element.getElementsByTagName (StaticStrings.LANGUAGE_ELEMENT);
    612         int language_elements_length = language_elements.getLength ();
    613         if(language_elements_length == 0) {
    614             return null;
    615         }
    616         for(int j = 0; j < language_elements_length; j++) {
    617             Element language_element = (Element) language_elements.item (j);
    618             text.append (language_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    619             if(j < language_elements_length - 1) {
    620                 text.append (StaticStrings.SPACE_CHARACTER);
    621             }
    622         }
    623         return text.toString ();
    624     }
    625    
    626     static private String languageDefaultToString (Element command_element) {
    627         StringBuffer text = new StringBuffer (StaticStrings.LANGUAGE_DEFAULT_STR);
    628         text.append (StaticStrings.TAB_CHARACTER);
    629         text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    630         return text.toString ();
    631     }
    632    
    633     static private String languageMetadataToString (Element command_element) {
    634         if (!command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    635             return "";
    636         }
    637         StringBuffer text = new StringBuffer (StaticStrings.LANGUAGE_METADATA_STR);
    638         text.append (StaticStrings.TAB_CHARACTER);
    639         String name_str = command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    640         text.append (name_str);
    641         return text.toString ();
    642     }
    643    
    644     static private String indexOptionsToString (Element command_element) {
    645         StringBuffer text = new StringBuffer ("");
    646         if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    647             text.append ("#");
    648         }
    649         text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    650         text.append (StaticStrings.TAB_CHARACTER);
    651         NodeList content_elements = command_element.getElementsByTagName (StaticStrings.INDEXOPTION_ELEMENT);
    652         int content_elements_length = content_elements.getLength ();
    653         // Don't output anything if no options are set.
    654         if(content_elements_length == 0) {
    655             return null;
    656         }
    657         for(int i = 0; i < content_elements_length; i++) {
    658             Element content_element = (Element) content_elements.item (i);
    659             text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    660             text.append (StaticStrings.SPACE_CHARACTER);
    661         }
    662         return text.substring (0, text.length () - 1);
    663     }
    664    
    665     static private String indexOptionDefaultToString (Element command_element) {
    666         // Don't bother if there is no value
    667         if (command_element.getAttribute (StaticStrings.VALUE_ATTRIBUTE).equals ("")) {
    668             return "";
    669         }
    670         StringBuffer text = new StringBuffer ("");
    671         if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    672             text.append ("#");
    673         }
    674         text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    675         text.append (StaticStrings.TAB_CHARACTER);
    676         text.append (command_element.getAttribute (StaticStrings.VALUE_ATTRIBUTE));
    677         return text.toString ();
    678     }
    679    
    680     static private String metadataToString (Element command_element) {
    681         // lets first check the value - if its empty, don't bother sticking it in the config file
    682         String value_str = XMLTools.getValue (command_element);
    683         if (value_str.equals ("")) {
    684             return "";
    685         }
    686         boolean special = false;
    687        
    688         StringBuffer text = new StringBuffer ("");
    689         String name_str = command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    690         // 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.
    691         if(name_str.equals (StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR)|| name_str.equals (StaticStrings.BUILDTYPE_STR) ) {
    692             text.append (name_str);
    693             text.append (StaticStrings.TAB_CHARACTER);
    694             special = true;
    695         }
    696         else if (name_str.equals (StaticStrings.COLLECTIONMETADATA_CREATOR_STR) || name_str.equals (StaticStrings.COLLECTIONMETADATA_PUBLIC_STR) ) {
    697             text.append (name_str);
    698             text.append (StaticStrings.TAB_CHARACTER);
    699             text.append (StaticStrings.TAB_CHARACTER);
    700             special = true;
    701         }
    702         else {
    703             text.append (StaticStrings.COLLECTIONMETADATA_STR);
    704             text.append (StaticStrings.TAB_CHARACTER);
    705             text.append (name_str);
    706             text.append (StaticStrings.SPACE_CHARACTER);
    707             String language_str = command_element.getAttribute (StaticStrings.LANGUAGE_ATTRIBUTE);
    708             text.append (StaticStrings.LBRACKET_CHARACTER);
    709             text.append (StaticStrings.LANGUAGE_ARGUMENT);
    710             text.append (language_str);
    711             text.append (StaticStrings.RBRACKET_CHARACTER);
    712             text.append (StaticStrings.SPACE_CHARACTER);
    713         }
    714         name_str = null;
    715        
    716     // decode the value from XML to a form for config file
    717     value_str = Codec.transform (value_str, Codec.DOM_TO_GREENSTONE);
    718        
    719         // We don't wrap the email addresses in quotes, nor the other special metadata
    720         if(special) {
    721             text.append (value_str);
    722         }
    723         else {
    724             text.append (StaticStrings.SPEECH_CHARACTER);
    725             text.append (value_str);
    726             text.append (StaticStrings.SPEECH_CHARACTER);
    727         }
    728         value_str = null;
    729         return text.toString ();
    730     }
    731    
    732     /** Parse a collect.cfg into a DOM model representation.
    733      * note we are ignoring 2.39 compatibility now. */
    734     private void parse (File collect_cfg_file) {
    735         // hack for pre 2.71 compatibility - we need to add in a
    736         // build type if there is not one there
    737         boolean search_types_parsed = false;
    738         boolean build_types_parsed = false;
    739         try {
    740             saved_collect_cfg_string_buffer = new StringBuffer ();
    741            
    742             Element collect_cfg_element = document.getDocumentElement ();
    743             // Read in the file one command at a time.
    744             InputStream istream = new FileInputStream (collect_cfg_file);
    745             Reader in_reader = new InputStreamReader (istream, ENCODING);
    746             BufferedReader in = new BufferedReader (in_reader);
    747             String command_str = null;
    748             while((command_str = in.readLine ()) != null) {
    749                 saved_collect_cfg_string_buffer.append (command_str + "\n");
    750                
    751                 boolean append_element = true;
    752                 Element command_element = null;
    753                 // A command may be broken over several lines.
    754                 command_str = command_str.trim ();
    755                 boolean eof = false;
    756                 while(!eof && command_str.endsWith (StaticStrings.NEWLINE_CHARACTER)) {
    757                     String next_line = in.readLine ();
    758                     if(next_line != null) {
    759                         next_line = next_line.trim ();
    760                         if(next_line.length () > 0) {
    761                             // Remove the new line character
    762                             command_str = command_str.substring (0, command_str.lastIndexOf (StaticStrings.NEWLINE_CHARACTER));
    763                             // And append the next line, which due to the test above must be non-zero length
    764                             command_str = command_str + next_line;
    765                         }
    766                         next_line = null;
    767                     }
    768                     // If we've reached the end of the file theres nothing more we can do
    769                     else {
    770                         eof = true;
    771                     }
    772                 }
    773                 // If there is still a new line character, then we remove it and hope for the best
    774                 if(command_str.endsWith (StaticStrings.NEWLINE_CHARACTER)) {
    775                     command_str = command_str.substring (0, command_str.lastIndexOf (StaticStrings.NEWLINE_CHARACTER));
    776                 }
    777                 // Now we've either got a command to parse...
    778                 if(command_str.length () != 0) {
    779                     // Start trying to figure out what it is
    780                     //StringTokenizer tokenizer = new StringTokenizer(command_str);
    781                     // 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.
    782                     CommandTokenizer tokenizer = new CommandTokenizer (command_str, in);
    783                     String command_type = tokenizer.nextToken ().toLowerCase ();
    784                     // 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
    785                     if(command_element == null && command_type.equals (StaticStrings.CLASSIFY_STR)) {
    786                         command_element = parseClassify (command_str);
    787                     }
    788                     if(command_element == null && command_type.equals (StaticStrings.FORMAT_STR)) {
    789                         command_element = parseFormat (tokenizer); // Revised to handle multiple lines
    790                     }
    791                     if(command_element == null && (command_type.equals (StaticStrings.INDEX_STR)  || command_type.equals (StaticStrings.COMMENTED_INDEXES_STR))) {
    792                         command_element = parseIndex (command_str);
    793                     }
    794                     if(command_element == null && (command_type.equals (StaticStrings.INDEX_DEFAULT_STR) || command_type.equals (StaticStrings.COMMENTED_INDEX_DEFAULT_STR))) {
    795                        
    796                         command_element = parseIndexDefault (command_str);
    797                     }
    798                     if(command_element == null && command_type.equals (StaticStrings.LANGUAGES_STR)) {
    799                         command_element = parseLanguage (command_str);
    800                     }
    801                     if(command_element == null && command_type.equals (StaticStrings.LANGUAGE_DEFAULT_STR)) {
    802                         command_element = parseLanguageDefault (command_str);
    803                     }
    804                     if (command_element == null && command_type.equals (StaticStrings.LANGUAGE_METADATA_STR)) {
    805                         command_element = parseLanguageMetadata (command_str);
    806                     }
    807                     if(command_element == null && command_type.equals (StaticStrings.LEVELS_STR)) {
    808                         command_element = parseIndexOptions (command_str, StaticStrings.LEVELS_STR, true);
    809                     }
    810                     if (command_element == null && command_type.equals (StaticStrings.COMMENTED_LEVELS_STR)) {
    811                         command_element = parseIndexOptions (command_str, StaticStrings.LEVELS_STR, false);
    812                     }
    813                     if(command_element == null && command_type.equals (StaticStrings.LEVEL_DEFAULT_STR)) {
    814                         command_element = parseIndexOptionDefault (command_str, StaticStrings.LEVEL_DEFAULT_STR, true);
    815                     }
    816                     if(command_element == null && command_type.equals (StaticStrings.COMMENTED_LEVEL_DEFAULT_STR)) {
    817                         command_element = parseIndexOptionDefault (command_str, StaticStrings.LEVEL_DEFAULT_STR, false);
    818                     }
    819                     if (command_element == null && command_type.equals (StaticStrings.INDEXOPTIONS_STR)) {
    820                         command_element = parseIndexOptions (command_str, StaticStrings.INDEXOPTIONS_STR, true);
    821                     }
    822                     if (command_element == null && command_type.equals (StaticStrings.COMMENTED_INDEXOPTIONS_STR)) {
    823                         command_element = parseIndexOptions (command_str, StaticStrings.INDEXOPTIONS_STR, false);
    824                     }
    825                     if(command_element == null && command_type.equals (StaticStrings.COLLECTIONMETADATA_STR)) {
    826                         command_element = parseMetadata (tokenizer); // Revised to handle multiple lines
    827                     }
    828                     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))) {
    829                         command_element = parseMetadataSpecial (command_str);
    830                         // pre 2.71 hack
    831                         if (command_type.equals (StaticStrings.BUILDTYPE_STR)) {
    832                             build_types_parsed = true;
    833                         }
    834                     }
    835                     if(command_element == null && command_type.equals (StaticStrings.PLUGIN_STR)) {
    836                         command_element = parsePlugin (command_str);
    837                     }
    838                     // leave here for backwards compatibility
    839                     if(command_element == null && command_type.equals (StaticStrings.SEARCHTYPE_STR)) {
    840                         command_element = parseSearchType (command_str);
    841                         // pre 2.71 hack
    842                         search_types_parsed = true;
    843                        
    844                     }
    845                     if(command_element == null && command_type.equals (StaticStrings.SUBCOLLECTION_STR)) {
    846                         command_element = parseSubCollection (command_str);
    847                     }
    848                     if(command_element == null && command_type.equals (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_STR)) {
    849                         command_element = parseSubCollectionDefaultIndex (command_str);
    850                     }
    851                     if(command_element == null && command_type.equals (StaticStrings.SUBCOLLECTION_INDEX_STR)) {
    852                         command_element = parseSubCollectionIndex (command_str);
    853                     }
    854                     if(command_element == null && (command_type.equals (StaticStrings.SUPERCOLLECTION_STR) || command_type.equals (StaticStrings.CCS_STR))) {
    855                         command_element = parseSuperCollection (command_str);
    856                     }
    857                     // Doesn't match any known type
    858                     command_type = null;
    859                     if(command_element == null) {
    860                         // No-one knows what to do with this command, so we create an Unknown command element
    861                         command_element = document.createElement (StaticStrings.UNKNOWN_ELEMENT);
    862                         XMLTools.setValue (command_element, command_str);
    863                     }
    864                 }
    865                 // Or an empty line to remember for later
    866                 else {
    867                     command_element = document.createElement (NEWLINE_ELEMENT);
    868                 }
    869                 // 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
    870                 //if(append_element) {
    871                 collect_cfg_element.appendChild (command_element);
    872                 //}
    873             }
    874             if (!build_types_parsed) {
    875                 String buildtype_type = BuildTypeManager.BUILD_TYPE_MG;
    876                 if (search_types_parsed) {
    877                     buildtype_type = BuildTypeManager.BUILD_TYPE_MGPP;
    878                 }
    879                 Element command_element = parseMetadataSpecial (StaticStrings.BUILDTYPE_STR+"  "+buildtype_type);
    880                 Node target_node = findInsertionPoint (command_element);
    881                 if(target_node != null) {
    882                     collect_cfg_element.insertBefore (command_element, target_node);
    883                 }
    884                 else {
    885                     collect_cfg_element.appendChild (command_element);
    886                 }
    887                
    888             }
    889         }
    890         catch(Exception exception) {
    891             DebugStream.println ("Error in CollectionConfiguration.parse(java.io.File): " + exception);
    892             DebugStream.printStackTrace (exception);
    893         }
    894     }
    895    
    896    
    897     private Element parseClassify (String command_str) {
    898         Element command_element = null;
    899         try {
    900             CommandTokenizer tokenizer = new CommandTokenizer (command_str);
    901             // 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).
    902             if(tokenizer.countTokens () >= 2) {  // Must support "classify Phind" (no args)
    903                 command_element = document.createElement (StaticStrings.CLASSIFY_ELEMENT);
    904                 // First token is classify
    905                 tokenizer.nextToken ();
    906                 // The next token is the classifier type
    907                 command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, tokenizer.nextToken ());
    908                 // Now we parse out the remaining arguments into a hashmapping from name to value
    909                 HashMap arguments = parseArguments (tokenizer);
    910                 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
    911                 Iterator names = arguments.keySet ().iterator ();
    912                 while(names.hasNext ()) {
    913                     String name = (String) names.next ();
    914                     String value = (String) arguments.get (name); // Can be null
    915                     // The metadata argument gets added as the content attribute
    916             /*                   if (name.equals (StaticStrings.METADATA_ARGUMENT) && value != null) {
    917                         // Add the extracted namespace onto un-namespaced metadata names
    918                         StringTokenizer string_tokenizer = new StringTokenizer (value, ",");
    919                         value = "";
    920                         while (string_tokenizer.hasMoreElements ()) {
    921                             String token = (String) string_tokenizer.nextElement ();
    922                            
    923                             if (token.indexOf (StaticStrings.NS_SEP) == -1) {
    924                                 token = StaticStrings.EXTRACTED_NAMESPACE + token;
    925                             }
    926                             else {
    927                                 MetadataElement metadata_element = MetadataTools.getMetadataElementWithName (token);
    928                                 if (metadata_element != null) {
    929                                     token = metadata_element.getDisplayName ();
    930                                 }
    931                             }
    932                            
    933                             if (!value.equals ("")) {
    934                                 value = value + ",";
    935                             }
    936                             value = value + token;
    937                         }
    938             }*/
    939                     // Everything else is an Option Element
    940                     Element option_element = document.createElement (StaticStrings.OPTION_ELEMENT);
    941                     option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name.substring (1));
    942                     if(value != null) {
    943                         // Remove any speech marks appended in strings containing whitespace
    944                         if(value.startsWith (StaticStrings.SPEECH_CHARACTER) && value.endsWith (StaticStrings.SPEECH_CHARACTER)) {
    945                             value = value.substring (1, value.length () - 1);
    946                         }
    947                         XMLTools.setValue (option_element, value);
    948                     }
    949                     option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    950                     command_element.appendChild (option_element);
    951                     option_element = null;
    952                     name = null;
    953                     value = null;
    954                 }
    955                 names = null;
    956                 arguments = null;
    957             }
    958             tokenizer = null;
    959         }
    960         catch(Exception error) {
    961         }
    962         return command_element;
    963     }
    964    
    965     private Element parseFormat (CommandTokenizer tokenizer) {
    966         Element command_element = null;
    967         try {
    968             command_element = document.createElement (StaticStrings.FORMAT_ELEMENT);
    969             String name_str = tokenizer.nextToken ();
    970             String value_str = tokenizer.nextToken ();
    971             if(name_str != null && value_str != null) {
    972                 command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    973                 // If the value is true or false we add it as an attribute
    974                 if(value_str.equalsIgnoreCase (StaticStrings.TRUE_STR) || value_str.equalsIgnoreCase (StaticStrings.FALSE_STR)) {
    975                     command_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, value_str.toLowerCase ());
    976                 }
    977                 // Otherwise it gets added as a text node
    978                 else {
    979                     // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
    980                     value_str = Codec.transform (value_str, Codec.GREENSTONE_TO_DOM);
    981                     XMLTools.setValue (command_element, value_str);
    982                 }
    983             }
    984             else {
    985                 command_element = null;
    986             }
    987             name_str = null;
    988             value_str = null;
    989         }
    990         catch (Exception exception) {
    991             DebugStream.printStackTrace (exception);
    992             command_element = null;
    993         }
    994         return command_element;
    995     }
    996    
    997     private Element parseIndex (String command_str) {
    998         Element command_element = null;
    999         try {
    1000             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1001             String command = tokenizer.nextToken ();
    1002             command_element = document.createElement (StaticStrings.INDEXES_ELEMENT);
    1003             command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, (command.equals (StaticStrings.INDEX_STR) ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
    1004             command = null;
    1005             if(!tokenizer.hasMoreTokens ()) {
    1006                
    1007                 // there are no indexes
    1008                 command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
    1009                 command_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR); // for now
    1010                 tokenizer = null;
    1011                 return command_element;
    1012             }
    1013            
    1014             while(tokenizer.hasMoreTokens ()) {
    1015                 Element index_element = document.createElement (StaticStrings.INDEX_ELEMENT);
    1016                 String index_str = tokenizer.nextToken ();
    1017                 // 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.
    1018                 boolean old_index;
    1019                 if(index_str.indexOf (StaticStrings.COLON_CHARACTER) != -1) {
    1020                     old_index = true;
    1021                     index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE, index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER)));
    1022                     index_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
    1023                     command_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
    1024                 }
    1025                 else {
    1026                     command_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
    1027                     old_index = false;
    1028                 }
    1029                 StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
    1030                 while(content_tokenizer.hasMoreTokens ()) {
    1031                     Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
    1032                     String content_str = content_tokenizer.nextToken ();
    1033                     // 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.
    1034                     if(content_str.indexOf (StaticStrings.NS_SEP) == -1) {
    1035                         if(content_str.equals (StaticStrings.TEXT_STR) || (!old_index && content_str.equals (StaticStrings.ALLFIELDS_STR))) {
    1036                             // Our special strings are OK.
    1037                         }
    1038                         else {
    1039                             content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
    1040                         }
    1041                     }
    1042                     content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
    1043                     index_element.appendChild (content_element);
    1044                     content_element = null;
    1045                 }
    1046                 content_tokenizer = null;
    1047                 index_str = null;
    1048                 command_element.appendChild (index_element);
    1049                 index_element = null;
    1050             }
    1051             tokenizer = null;
    1052         }
    1053         catch (Exception exception) {
    1054             exception.printStackTrace ();
    1055         }
    1056         return command_element;
    1057     }
    1058    
    1059     private Element parseIndexDefault (String command_str) {
    1060         Element command_element = null;
    1061         try {
    1062             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1063             if(tokenizer.countTokens () >= 2) {
    1064                 command_element = document.createElement (StaticStrings.INDEX_DEFAULT_ELEMENT);
    1065                 command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken ()).equals (StaticStrings.INDEX_DEFAULT_STR) ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
    1066                 String index_str = tokenizer.nextToken ();
    1067                 String level="";
    1068                 if (index_str.indexOf (StaticStrings.COLON_CHARACTER) !=-1) {
    1069                     level =  index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER));
    1070                 }
    1071                
    1072                 command_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE,level);
    1073                
    1074                 String content_str = index_str;
    1075                
    1076                 if (index_str.indexOf (StaticStrings.COLON_CHARACTER) !=-1) {
    1077                     content_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
    1078                 }
    1079                
    1080                 StringTokenizer content_tokenizer = new StringTokenizer (content_str, StaticStrings.COMMA_CHARACTER);
    1081                 while(content_tokenizer.hasMoreTokens ()) {
    1082                     Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
    1083                     content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken ());
    1084                     command_element.appendChild (content_element);
    1085                     content_element = null;
    1086                 }
    1087                 content_tokenizer = null;
    1088                 content_str = null;
    1089                 content_str = null;
    1090                 index_str = null;
    1091             }
    1092             tokenizer = null;
    1093         }
    1094         catch (Exception exception) {
    1095         }
    1096         return command_element;
    1097     }
    1098    
    1099     private Element parseLanguage (String command_str) {
    1100         Element command_element = null;
    1101         try {
    1102             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1103             tokenizer.nextToken ();
    1104             if(tokenizer.hasMoreTokens ()) {
    1105                 command_element = document.createElement (StaticStrings.LANGUAGES_ELEMENT);
    1106                 while(tokenizer.hasMoreTokens ()) {
    1107                     Element language_element = document.createElement (StaticStrings.LANGUAGE_ELEMENT);
    1108                     language_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
    1109                     command_element.appendChild (language_element);
    1110                     language_element = null;
    1111                 }
    1112             }
    1113             tokenizer = null;
    1114         }
    1115         catch (Exception exception) {
    1116         }
    1117         return command_element;
    1118     }
    1119    
    1120     private Element parseLanguageDefault (String command_str) {
    1121         Element command_element = null;
    1122         try {
    1123             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1124             if(tokenizer.countTokens () >= 2) {
    1125                 command_element = document.createElement (StaticStrings.LANGUAGE_DEFAULT_ELEMENT);
    1126                 tokenizer.nextToken ();
    1127                 String default_language_str = tokenizer.nextToken ();
    1128                 command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, default_language_str);
    1129                 command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1130                 default_language_str = null;
    1131             }
    1132             tokenizer = null;
    1133         }
    1134         catch (Exception exception) {
    1135         }
    1136         return command_element;
    1137     }
    1138    
    1139     private Element parseLanguageMetadata (String command_str) {
    1140         Element command_element = null;
    1141         try {
    1142             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1143             if(tokenizer.countTokens () >= 2) {
    1144                 command_element = document.createElement (StaticStrings.LANGUAGE_METADATA_ELEMENT);
    1145                 tokenizer.nextToken ();
    1146                 String language_metadata_str = tokenizer.nextToken ();
    1147                 if (language_metadata_str.indexOf (StaticStrings.NS_SEP) == -1) {
    1148                     language_metadata_str = StaticStrings.EXTRACTED_NAMESPACE + language_metadata_str;
    1149                 }
    1150                 command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, language_metadata_str);
    1151                 command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1152                 language_metadata_str = null;
    1153             }
    1154             tokenizer = null;
    1155            
    1156         }
    1157         catch (Exception exception) {
    1158         }
    1159         return command_element;
    1160     }
    1161    
    1162     private Element parseIndexOptions (String command_str, String type, boolean assigned) {
    1163         Element command_element = null;
    1164         try {
    1165             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1166             // First token is command type
    1167             String command = tokenizer.nextToken ();
    1168             if(tokenizer.hasMoreTokens ()) {
    1169                 command_element = document.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
    1170                 command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE,type);
    1171                 command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
    1172                 while(tokenizer.hasMoreTokens ()) {
    1173                     Element option_element = document.createElement (StaticStrings.INDEXOPTION_ELEMENT);
    1174                     option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
    1175                     command_element.appendChild (option_element);
    1176                     option_element = null;
    1177                 }
    1178             }
    1179             command = null;
    1180         }
    1181         catch(Exception exception) {
    1182         }
    1183         return command_element;
    1184     }
    1185    
    1186     private Element parseIndexOptionDefault (String command_str, String type, boolean assigned) {
    1187         Element command_element = null;
    1188         try {
    1189             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1190             // First token is command type
    1191             String command = tokenizer.nextToken ();
    1192             if(tokenizer.hasMoreTokens ()) {
    1193                 command_element = document.createElement (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT);
    1194                 command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR)); // is it commented out or not?
    1195                 command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, type);
    1196                 command_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, tokenizer.nextToken ());
    1197             }
    1198            
    1199             tokenizer = null;
    1200         }
    1201         catch (Exception exception) {
    1202         }
    1203         return command_element;
    1204     }
    1205    
    1206     private Element parseMetadata (CommandTokenizer tokenizer) {
    1207         Element command_element = null;
    1208         try {
    1209             command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
    1210             String name_str = tokenizer.nextToken ();
    1211             String value_str = tokenizer.nextToken ();
    1212             if(name_str != null && value_str != null) {
    1213                 String language_str = Configuration.getLanguage ();
    1214                 // Check if the value string is actually a language string
    1215                 if(value_str.startsWith (StaticStrings.LBRACKET_CHARACTER) && value_str.endsWith (StaticStrings.RBRACKET_CHARACTER)) {
    1216                     language_str = value_str.substring (value_str.indexOf (StaticStrings.LANGUAGE_ARGUMENT) + 2, value_str.length () - 1);
    1217                     value_str = tokenizer.nextToken ();
    1218                 }
    1219                 if(value_str != null) {
    1220                     // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
    1221                     value_str = Codec.transform (value_str, Codec.GREENSTONE_TO_DOM);
    1222                     command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    1223                     command_element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, language_str);
    1224                     command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1225                     XMLTools.setValue (command_element, value_str);
    1226                 }
    1227                 else {
    1228                     command_element = null;
    1229                 }
    1230                 language_str = null;
    1231             }
    1232             else {
    1233                 command_element = null;
    1234             }
    1235             name_str = null;
    1236             value_str = null;
    1237         }
    1238         catch (Exception exception) {
    1239             DebugStream.printStackTrace (exception);
    1240             command_element = null;
    1241         }
    1242         return command_element;
    1243     }
    1244    
    1245     private Element parseMetadataSpecial (String command_str) {
    1246         Element command_element = null;
    1247         try {
    1248             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1249             if(tokenizer.countTokens () >= 2) {
    1250                 String name_str = tokenizer.nextToken ();
    1251                 String value_str = tokenizer.nextToken ();
    1252                 if (name_str.equals (StaticStrings.COLLECTIONMETADATA_CREATOR_STR)) {
    1253                     command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT);
    1254                 }
    1255                 else if(name_str.equals (StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR)) {
    1256                     command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT);
    1257                 }
    1258                 else if(name_str.equals (StaticStrings.COLLECTIONMETADATA_PUBLIC_STR)) {
    1259                     command_element = document.createElement (StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT);
    1260                 }
    1261                 else if (name_str.equals (StaticStrings.BUILDTYPE_STR)) {
    1262                     command_element = document.createElement (StaticStrings.BUILDTYPE_ELEMENT);
    1263                 }
    1264                 if(command_element != null) {
    1265                     command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    1266                     command_element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
    1267                     command_element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
    1268                     command_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1269                     if(value_str.startsWith (StaticStrings.SPEECH_CHARACTER) && value_str.endsWith (StaticStrings.SPEECH_CHARACTER)) {
    1270                         value_str = value_str.substring (1, value_str.length () - 1);
    1271                     }
    1272                     XMLTools.setValue (command_element, value_str);
    1273                 }
    1274                 value_str = null;
    1275                 name_str = null;
    1276             }
    1277             tokenizer = null;
    1278         }
    1279         catch (Exception exception) {
    1280         }
    1281         return command_element;
    1282     }
    1283    
    1284     private Element parsePlugin (String command_str) {
    1285         Element command_element = null;
    1286         try {
    1287             CommandTokenizer tokenizer = new CommandTokenizer (command_str);
    1288             // 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).
    1289             if(tokenizer.countTokens () >= 2) {
    1290                 command_element = document.createElement (StaticStrings.PLUGIN_ELEMENT);
    1291                 // First token is plugin
    1292                 tokenizer.nextToken ();
    1293                 // The next token is the type
    1294                 String type = tokenizer.nextToken ();
    1295         type = ensureNewPluginName(type);
    1296                 command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, type);
    1297                 // Now we parse out the remaining arguments into a hashmapping from name to value
    1298                 HashMap arguments = parseArguments (tokenizer);
    1299                 // Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
    1300                 // also watch out for the deprecated -use_metadata_files option to RecPlug and remove it
    1301                 Iterator names = arguments.keySet ().iterator ();
    1302                 while(names.hasNext ()) {
    1303                     String name = (String) names.next ();
    1304                     String value = (String) arguments.get (name); // Can be null
    1305                    
    1306                     if(type.equals (StaticStrings.RECPLUG_STR) && name.substring (1).equals (StaticStrings.USE_METADATA_FILES_ARGUMENT)) {
    1307                         continue; // ignore this option
    1308                     }
    1309                     Element option_element = document.createElement (StaticStrings.OPTION_ELEMENT);
    1310                     option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name.substring (1));
    1311                     option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1312                     if(value != null) {
    1313                         // Remove any speech marks appended in strings containing whitespace
    1314                         if(value.startsWith (StaticStrings.SPEECH_CHARACTER) && value.endsWith (StaticStrings.SPEECH_CHARACTER)) {
    1315                             value = value.substring (1, value.length () - 1);
    1316                         }
    1317                         if(name.equals (StaticStrings.METADATA_ARGUMENT)) {
    1318                             // 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.
    1319                             if(value.indexOf (StaticStrings.NS_SEP) == -1) {
    1320                                 value = StaticStrings.EXTRACTED_NAMESPACE + value;
    1321                             }
    1322                         }
    1323                         XMLTools.setValue (option_element, value);
    1324                     }
    1325                     command_element.appendChild (option_element);
    1326                     option_element = null;
    1327                     name = null;
    1328                     value = null;
    1329                 }
    1330                
    1331                 type = null;
    1332                 names = null;
    1333                 arguments = null;
    1334             }
    1335             tokenizer = null;
    1336         }
    1337         catch(Exception exception) {
    1338         // This catch clause had been left empty.  If this is deliberate then
    1339         // we should have a comment here explaining why there is no need to
    1340         // print anything out.  Am assuming this is mistake for now, and
    1341         // have added in a call to printStackTrace()
    1342         System.err.println("Malformed plugin statement");
    1343         exception.printStackTrace();
    1344         }
    1345         return command_element;
    1346     }
    1347    
    1348     /* search types are now handled as formats - leave this here to convert in case we have an old config file */
    1349     private Element parseSearchType (String command_str) {
    1350         Element command_element = null;
    1351         try {
    1352             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1353             // First token is command type (searchtype)
    1354             tokenizer.nextToken ();
    1355             if(tokenizer.hasMoreTokens ()) {
    1356                 command_element = document.createElement (StaticStrings.FORMAT_ELEMENT);
    1357                 command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, "SearchTypes");
    1358                 String value = tokenizer.nextToken ();
    1359                 while(tokenizer.hasMoreTokens ()) {
    1360                     value += ","+tokenizer.nextToken ();
    1361                 }
    1362                 value = Codec.transform (value, Codec.GREENSTONE_TO_DOM);
    1363                 XMLTools.setValue (command_element, value);
    1364             }
    1365         }
    1366         catch(Exception exception) {
    1367         }
    1368         return command_element;
    1369     }
    1370    
    1371     private Element parseSubCollection (String command_str) {
    1372         Element command_element = null;
    1373         try {
    1374             CommandTokenizer tokenizer = new CommandTokenizer (command_str);
    1375             if(tokenizer.countTokens () >= 3) {
    1376                 command_element = document.createElement (StaticStrings.SUBCOLLECTION_ELEMENT);
    1377                 // First token is command type
    1378                 tokenizer.nextToken ();
    1379                 // Then subcollection identifier
    1380                 command_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
    1381                 // Then finally the pattern used to build the subcollection partition
    1382                 String full_pattern_str = tokenizer.nextToken ();
    1383                 // Set inclusion/exclusion flag and remove any exclamation mark
    1384                 boolean exclusion = full_pattern_str.startsWith (StaticStrings.EXCLAMATION_CHARACTER);
    1385                 if (exclusion) {
    1386                     full_pattern_str = full_pattern_str.substring (1, full_pattern_str.length ());
    1387                     command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, StaticStrings.EXCLUDE_STR);
    1388                 }
    1389                 else {
    1390                     command_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, StaticStrings.INCLUDE_STR);
    1391                 }
    1392 
    1393                 // Let's make sure it is a valid Greenstone configuration line
    1394                 String[] results = full_pattern_str.split("\\" + StaticStrings.SEPARATOR_CHARACTER, 3);
    1395 
    1396                 if (results.length >= 2) {
    1397                     String content_str = results[0];
    1398                     // 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.
    1399                     if (!content_str.equals (StaticStrings.FILENAME_STR) && content_str.indexOf (StaticStrings.NS_SEP) == -1) {
    1400                         content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
    1401                     }
    1402                     command_element.setAttribute (StaticStrings.CONTENT_ATTRIBUTE, content_str);
    1403                     XMLTools.setValue (command_element, results[1]);
    1404                     if (results.length >= 3) {
    1405                         command_element.setAttribute (StaticStrings.OPTIONS_ATTRIBUTE, results[2]);
    1406                     }
    1407                 }
    1408             }
    1409         }
    1410         catch(Exception exception) {
    1411             exception.printStackTrace ();
    1412         }
    1413         return command_element;
    1414     }
    1415    
    1416     private Element parseSubCollectionDefaultIndex (String command_str) {
    1417         Element command_element = null;
    1418         try {
    1419             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1420             if(tokenizer.countTokens () == 2) {
    1421                 command_element = document.createElement (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
    1422                 tokenizer.nextToken ();
    1423                 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
    1424                 String content_str = tokenizer.nextToken ();
    1425                 StringTokenizer content_tokenizer = new StringTokenizer (content_str, StaticStrings.COMMA_CHARACTER);
    1426                 while(content_tokenizer.hasMoreTokens ()) {
    1427                     Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
    1428                     content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken ());
    1429                     command_element.appendChild (content_element);
    1430                     content_element = null;
    1431                 }
    1432                 content_tokenizer = null;
    1433                 content_str = null;
    1434             }
    1435             tokenizer = null;
    1436         }
    1437         catch(Exception exception) {
    1438         }
    1439         return command_element;
    1440     }
    1441    
    1442     private Element parseSubCollectionIndex (String command_str) {
    1443         Element command_element = null;
    1444         try {
    1445             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1446             tokenizer.nextToken ();
    1447             if(tokenizer.hasMoreTokens ()) {
    1448                 command_element = document.createElement (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT);
    1449             }
    1450             while(tokenizer.hasMoreTokens ()) {
    1451                 Element subcollectionindex_element = document.createElement (StaticStrings.INDEX_ELEMENT);
    1452                 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
    1453                 String content_str = tokenizer.nextToken ();
    1454                 StringTokenizer content_tokenizer = new StringTokenizer (content_str, StaticStrings.COMMA_CHARACTER);
    1455                 while(content_tokenizer.hasMoreTokens ()) {
    1456                     Element content_element = document.createElement (StaticStrings.CONTENT_ELEMENT);
    1457                     content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken ());
    1458                     subcollectionindex_element.appendChild (content_element);
    1459                     content_element = null;
    1460                 }
    1461                 content_tokenizer = null;
    1462                 content_str = null;
    1463                 command_element.appendChild (subcollectionindex_element);
    1464                 subcollectionindex_element = null;
    1465             }
    1466             tokenizer = null;
    1467         }
    1468         catch (Exception exception) {
    1469         }
    1470         return command_element;
    1471     }
    1472    
    1473     private Element parseSuperCollection (String command_str) {
    1474         Element command_element = null;
    1475         try {
    1476             StringTokenizer tokenizer = new StringTokenizer (command_str);
    1477             if(tokenizer.countTokens () >= 3) {
    1478                 command_element = document.createElement (StaticStrings.SUPERCOLLECTION_ELEMENT);
    1479                 tokenizer.nextToken ();
    1480                 while(tokenizer.hasMoreTokens ()) {
    1481                     Element collection_element = document.createElement (StaticStrings.COLLECTION_ELEMENT);
    1482                     collection_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken ());
    1483                     command_element.appendChild (collection_element);
    1484                     collection_element = null;
    1485                 }
    1486             }
    1487             tokenizer = null;
    1488         }
    1489         catch(Exception exception) {
    1490         }
    1491         return command_element;
    1492     }
    1493    
    1494     static private String pluginToString (Element command_element) {
    1495         if(command_element.getAttribute (StaticStrings.SEPARATOR_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    1496       return "";
    1497     }
    1498         StringBuffer text = new StringBuffer (StaticStrings.PLUGIN_STR);
    1499     text.append (StaticStrings.TAB_CHARACTER);
    1500     text.append (command_element.getAttribute (StaticStrings.TYPE_ATTRIBUTE));
    1501     // Retrieve, and output, the arguments
    1502     NodeList option_elements = command_element.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
    1503     int option_elements_length = option_elements.getLength ();
    1504     if(option_elements_length > 0) {
    1505       for(int j = 0; j < option_elements_length; j++) {
    1506         Element option_element = (Element) option_elements.item (j);
    1507         if(option_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    1508           text.append (StaticStrings.SPACE_CHARACTER);
    1509           text.append (StaticStrings.MINUS_CHARACTER);
    1510           text.append (option_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    1511           String value_str = XMLTools.getValue (option_element);
    1512           // turn display name into proper name
    1513           //value_str = modifyMetadataArgumentValue(value_str);
    1514           if (value_str.length () > 0) {
    1515         text.append (StaticStrings.SPACE_CHARACTER);
    1516         if(value_str.indexOf (StaticStrings.SPACE_CHARACTER) != -1) {
    1517             // enclose in quotes
    1518             text.append(StaticStrings.SPEECH_CHARACTER);
    1519             text.append(value_str);
    1520             text.append(StaticStrings.SPEECH_CHARACTER);
    1521         } else {
    1522            
    1523             text.append(value_str);
    1524         }
    1525           }
    1526          
    1527           value_str = null;
    1528         }
    1529         option_element = null;
    1530       }
    1531     }
    1532     option_elements = null;
    1533    
    1534     return text.toString ();
    1535     }
    1536 
    1537     // Convert metadata element names to internal names, and remove extracted metadata namespaces
    1538     /*  static private String modifyMetadataArgumentValue(String value_str) {
    1539     if (value_str.length () == 0) {
    1540       return value_str;
    1541     }
    1542    
    1543     // final true arg to return delims as tokens
    1544     StringTokenizer string_tokenizer = new StringTokenizer (value_str, ",;", true);
    1545     StringBuffer value_buffer = new StringBuffer ();
    1546     while (string_tokenizer.hasMoreElements ()) {
    1547       String raw_token = (String) string_tokenizer.nextElement ();
    1548       String token = raw_token.trim ();
    1549       boolean modified_token = false;
    1550       // not a delimiter token
    1551       if (!raw_token.equals(",") && !raw_token.equals(";")) {
    1552       //MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName (token);
    1553       //if (metadata_element != null) {
    1554       //token = metadata_element.getFullName ();
    1555       //modified_token = true;
    1556       //}
    1557    
    1558     //  if (token.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
    1559     // token = token.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
    1560     // modified_token = true;
    1561     //}
    1562       }
    1563       if (modified_token) {
    1564     value_buffer.append (token);
     160      }
     161      else {
     162    ///ystem.err.println("Not dealing with collection meta.");
     163    Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
     164    // 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)
     165    Node sibling_element = matched_element.getNextSibling ();
     166    if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
     167      Element newline_element = document.createElement (NEWLINE_ELEMENT);
     168      document_element.insertBefore (newline_element, sibling_element);
     169    }
     170    return sibling_element; // Note that this may be null
     171      }
     172    }
     173    ///ystem.err.println("No matching elements found.");
     174    // Locate where this command is in the ordering
     175    int command_index = -1;
     176    for(int i = 0; command_index == -1 && i < COMMAND_ORDER.length; i++) {
     177      if(COMMAND_ORDER[i].equals (target_element_name)) {
     178    command_index = i;
     179      }
     180    }
     181    ///ystem.err.println("Command index is: " + command_index);
     182    // Now move forward, checking for existing elements in each of the preceeding command orders.
     183    int preceeding_index = command_index - 1;
     184    ///ystem.err.println("Searching before the target command.");
     185    while(preceeding_index >= 0) {
     186      matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[preceeding_index]);
     187      // If we've found a match
     188      if(matching_elements.getLength () > 0) {
     189    // We add after the last element
     190    Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
     191    // 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)
     192    Node sibling_element = matched_element.getNextSibling ();
     193    if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
     194      Element newline_element = document.createElement (NEWLINE_ELEMENT);
     195      document_element.insertBefore (newline_element, sibling_element);
     196    }
     197    return sibling_element; // Note that this may be null
     198      }
     199      preceeding_index--;
     200    }
     201    // If all that fails, we now move backwards through the commands
     202    int susceeding_index = command_index + 1;
     203    ///ystem.err.println("Searching after the target command.");
     204    while(susceeding_index < COMMAND_ORDER.length) {
     205      matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[susceeding_index]);
     206      // If we've found a match
     207      if(matching_elements.getLength () > 0) {
     208    // We add before the first element
     209    Element matched_element = (Element) matching_elements.item (0);
     210    // 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)
     211    Node sibling_element = matched_element.getPreviousSibling ();
     212    if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
     213      Element newline_element = document.createElement (NEWLINE_ELEMENT);
     214      document_element.insertBefore (newline_element, sibling_element);
     215    }
     216    return sibling_element; // Note that this may be null
     217      }
     218      susceeding_index++;
     219    }
     220    // Well. Apparently there are no other commands in this collection configuration. So append away...
     221    return null;
     222  }
     223   
     224   
     225  static public NodeList getElementsByTagName (String element_name) {
     226    return document.getDocumentElement ().getElementsByTagName (element_name);
     227  }
     228       
     229  public Element getDocumentElement () {
     230    return document.getDocumentElement ();
     231  }
     232   
     233  /** This debug facility shows the currently loaded collect.cfg or CollectConfig.xml file as a DOM tree. */
     234  public void display () {
     235    JDialog dialog = new JDialog (Gatherer.g_man, "Collection Configuration", false);
     236    dialog.setSize (400,400);
     237    JPanel content_pane = (JPanel) dialog.getContentPane ();
     238    final DOMTree tree = new DOMTree (document);
     239    JButton refresh_button = new GLIButton ("Refresh Tree");
     240    refresh_button.addActionListener (new ActionListener () {
     241    public void actionPerformed (ActionEvent event) {
     242      tree.setDocument (document);
     243    }
     244      });
     245    content_pane.setBorder (BorderFactory.createEmptyBorder (5,5,5,5));
     246    content_pane.setLayout (new BorderLayout ());
     247    content_pane.add (new JScrollPane (tree), BorderLayout.CENTER);
     248    content_pane.add (refresh_button, BorderLayout.SOUTH);
     249    dialog.setVisible (true);
     250  }
     251   
     252       
     253   
     254  public File getFile () {
     255    return collect_config_file;
     256  }
     257   
     258  public Element getCreator () {
     259    Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, null, null);
     260    element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_CREATOR_STR);
     261    element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
     262    return element;
     263  }
     264
     265  public Element getMaintainer () {
     266    Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, null, null);
     267    element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR);
     268    element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
     269    return element;
     270  }
     271
     272  /** Retrieve or create the languages Element. */
     273  public Element getLanguages () {
     274    return getOrCreateElementByTagName (StaticStrings.LANGUAGES_ELEMENT, null, null);
     275  }
     276   
     277  public Element getLanguageMetadata () {
     278    return getOrCreateElementByTagName (StaticStrings.LANGUAGE_METADATA_ELEMENT, null, null);
     279  }
     280   
     281  public Element getLevels () {
     282    return getOrCreateElementByTagName (StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVELS_STR);
     283  }
     284   
     285  public Element getLevelDefault () {
     286    return getOrCreateElementByTagName (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVEL_DEFAULT_STR);
     287  }
     288   
     289  public Element getIndexOptions () {
     290    return getOrCreateElementByTagName (StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.INDEXOPTIONS_STR);
     291  }
     292   
     293       
     294  /** 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. */
     295  public Element getMGIndexes () {
     296    return getOrCreateElementByTagName (StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
     297  }
     298   
     299  public Element getMGPPIndexes () {
     300    return getOrCreateElementByTagName (StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
     301  }
     302   
     303  public Element getPublic () {
     304    Element element = getOrCreateElementByTagName (StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, null, null);
     305    element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_PUBLIC_STR);
     306    element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
     307    return element;
     308  }
     309   
     310  public Element getBuildType () {
     311    Element element = getOrCreateElementByTagName (StaticStrings.BUILDTYPE_ELEMENT, null, null);
     312    element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
     313    element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
     314    return element;
     315       
     316  }
     317   
     318  /** Retrieve or create the subindexes Element. */
     319  public Element getSubIndexes () {
     320    return getOrCreateElementByTagName (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, null, null);
     321  }
     322   
     323  /** Retrieve or create the supercollections Element. */
     324  public Element getSuperCollection () {
     325    return getOrCreateElementByTagName (StaticStrings.SUPERCOLLECTION_ELEMENT, null, null);
     326  }
     327   
     328  public boolean ready () {
     329    return document != null;
     330  }
     331   
     332   
     333   
     334   
     335  /** ************************** Private Methods ***************************/
     336   
     337 
     338  /** Retrieve or create the indexes Element. */
     339  static private Element getOrCreateElementByTagName (String name, String conditional_attribute, String required_value) {
     340    Element document_element = document.getDocumentElement ();
     341    NodeList elements = document_element.getElementsByTagName (name);
     342    int elements_length = elements.getLength ();
     343    if(elements_length > 0) {
     344      if(conditional_attribute == null) {
     345    document_element = null;
     346    return (Element) elements.item (0);
     347      }
     348      else {
     349    for(int i = 0; i < elements_length; i++) {
     350      Element element = (Element) elements.item (i);
     351      if(element.getAttribute (conditional_attribute).equals (required_value)) {
     352        document_element = null;
     353        return element;
     354      }
     355      element = null;
     356    }
     357      }
     358    }
     359    // Create the element
     360    Element element = document.createElement (name);
     361    // If there was a property set it
     362    if(conditional_attribute != null) {
     363      element.setAttribute (conditional_attribute, required_value);
     364    }
     365    Node target_node = findInsertionPoint (element);
     366    if(target_node != null) {
     367      document_element.insertBefore (element, target_node);
     368    }
     369    else {
     370      document_element.appendChild (element);
     371    }
     372    document_element = null;
     373    return element;
     374  }
     375   
     376
     377
     378 
     379
     380  /** 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.
     381   * @param writer the BufferedWriter to which the str will be written
     382   * @param str the String to be written
     383   */
     384  private void write (BufferedWriter writer, String str)
     385    throws IOException {
     386    writer.write (str, 0, str.length ());
     387  }
     388   
     389
     390  public void saveIfNecessary () {
     391   
     392    // Generate a string version of internal document
     393    String config_file_string = null;
     394    if (Gatherer.GS3) {
     395      config_file_string = CollectionConfigXMLReadWrite.generateStringVersion(document);
     396    } else {
     397      config_file_string = CollectCfgReadWrite.generateStringVersion(document);
     398    }
     399    // compare to saved version
     400    if (saved_config_file_string != null) {
     401      if (saved_config_file_string.equals(config_file_string)) {
     402    DebugStream.println (collect_config_filename +" file hasn't changed so no save necessary...");
     403    return;
     404      }
     405    }
     406   
     407    // We need to save...
     408    DebugStream.println (collect_config_filename +" file has changed, saving now...");
     409
     410       
     411    // If we're using the Local Library we must release the collection before writing to the collect.cfg file
     412    String collection_name = CollectionManager.getLoadedCollectionName ();
     413    boolean collection_released = false;
     414    if (Gatherer.c_man.built () && LocalLibraryServer.isRunning () == true) {
     415      // Release the collection
     416      LocalLibraryServer.releaseCollection (collection_name);
     417      collection_released = true;
     418    }
     419       
     420    // Make a backup of the existing config file
     421    if (collect_config_file.exists ()) {
     422      String config_filename;
     423      String backup_filename;
     424      if (Gatherer.GS3) {
     425    config_filename = Utility.COLLECTION_CONFIG_XML;
     426    backup_filename = Utility.COLLECTION_CONFIG_BAK;
    1565427      } else {
    1566     // we may have had whitespace etc that was part of the string
    1567     value_buffer.append (raw_token);
    1568       }
    1569     }
    1570    
    1571    
    1572     if(value_buffer.length () == 0) {
    1573       return "";
    1574     }
    1575     if(value_str.indexOf (StaticStrings.SPACE_CHARACTER) == -1) {
    1576       return value_buffer.toString();
    1577     }
    1578    
    1579     // it must contain a space, so we surround the value with quotes
    1580     value_buffer.insert(0, StaticStrings.SPEECH_CHARACTER);
    1581     value_buffer.append(StaticStrings.SPEECH_CHARACTER);
    1582     return value_buffer.toString();
    1583 
    1584     }*/
    1585    
    1586     static private String searchtypeToString (Element command_element) {
    1587         if(command_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    1588             StringBuffer text = new StringBuffer (StaticStrings.SEARCHTYPE_STR);
    1589             text.append (StaticStrings.TAB_CHARACTER);
    1590             NodeList search_elements = command_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
    1591             int search_elements_length = search_elements.getLength ();
    1592             for(int i = 0; i < search_elements_length; i++) {
    1593                 Element search_element = (Element) search_elements.item (i);
    1594                 text.append (search_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    1595                 text.append (StaticStrings.SPACE_CHARACTER);
    1596             }
    1597             return text.substring (0, text.length () - 1);
    1598         }
    1599         else {
    1600             return null;
    1601         }
    1602     }
    1603    
    1604     static private String subcollectionToString (Element command_element) {
    1605         StringBuffer text = new StringBuffer (StaticStrings.SUBCOLLECTION_STR);
    1606         text.append (StaticStrings.SPACE_CHARACTER);
    1607         text.append (command_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    1608         text.append (StaticStrings.SPACE_CHARACTER);
    1609         text.append (StaticStrings.TAB_CHARACTER);
    1610         text.append (StaticStrings.SPEECH_CHARACTER);
    1611         if(command_element.getAttribute (StaticStrings.TYPE_ATTRIBUTE).equals (StaticStrings.EXCLUDE_STR)) {
    1612             text.append (StaticStrings.EXCLAMATION_CHARACTER);
    1613         }
    1614         text.append (command_element.getAttribute (StaticStrings.CONTENT_ATTRIBUTE));
    1615         text.append (StaticStrings.SEPARATOR_CHARACTER);
    1616         text.append (XMLTools.getValue (command_element));
    1617         text.append (StaticStrings.SEPARATOR_CHARACTER);
    1618         String options_str = command_element.getAttribute (StaticStrings.OPTIONS_ATTRIBUTE);
    1619         if(options_str.length () > 0) {
    1620             text.append (options_str);
    1621         }
    1622         options_str = null;
    1623         text.append (StaticStrings.SPEECH_CHARACTER);
    1624         return text.toString ();
    1625     }
    1626    
    1627     static private String subcollectionDefaultIndexToString (Element command_element) {
    1628         StringBuffer text = new StringBuffer (StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_STR);
    1629         text.append (StaticStrings.TAB_CHARACTER);
    1630         NodeList content_elements = command_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
    1631         int content_elements_length = content_elements.getLength ();
    1632         for(int j = 0; j < content_elements_length; j++) {
    1633             Element content_element = (Element) content_elements.item (j);
    1634             text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    1635             if(j < content_elements_length - 1) {
    1636                 text.append (StaticStrings.COMMA_CHARACTER);
    1637             }
    1638         }
    1639         return text.toString ();
    1640     }
    1641    
    1642     static private String subcollectionIndexesToString (Element command_element) {
    1643         StringBuffer text = new StringBuffer (StaticStrings.SUBCOLLECTION_INDEX_STR);
    1644         text.append (StaticStrings.TAB_CHARACTER);
    1645         // Retrieve all of the subcollection index partitions
    1646         NodeList subcollectionindex_elements = command_element.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
    1647         int subcollectionindex_elements_length = subcollectionindex_elements.getLength ();
    1648         if(subcollectionindex_elements_length == 0) {
    1649             return null;
    1650         }
    1651         for(int j = 0; j < subcollectionindex_elements_length; j++) {
    1652             Element subcollectionindex_element = (Element) subcollectionindex_elements.item (j);
    1653             NodeList content_elements = subcollectionindex_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
    1654             int content_elements_length = content_elements.getLength ();
    1655             for(int k = 0; k < content_elements_length; k++) {
    1656                 Element content_element = (Element) content_elements.item (k);
    1657                 text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    1658                 if(k < content_elements_length - 1) {
    1659                     text.append (StaticStrings.COMMA_CHARACTER);
    1660                 }
    1661             }
    1662             if(j < subcollectionindex_elements_length - 1) {
    1663                 text.append (StaticStrings.SPACE_CHARACTER);
    1664             }
    1665         }
    1666         return text.toString ();
    1667     }
    1668    
    1669     static private String supercollectionToString (Element command_element) {
    1670         NodeList content_elements = command_element.getElementsByTagName (StaticStrings.COLLECTION_ELEMENT);
    1671         int content_elements_length = content_elements.getLength ();
    1672         if(content_elements_length > 1) {
    1673             StringBuffer text = new StringBuffer (StaticStrings.SUPERCOLLECTION_STR);
    1674             text.append (StaticStrings.TAB_CHARACTER);
    1675             for(int j = 0; j < content_elements_length; j++) {
    1676                 Element content_element = (Element) content_elements.item (j);
    1677                 text.append (content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE));
    1678                 if(j < content_elements_length - 1) {
    1679                     text.append (StaticStrings.SPACE_CHARACTER);
    1680                 }
    1681             }
    1682             return text.toString ();
    1683         }
    1684         return null;
    1685     }
    1686    
    1687     static private String unknownToString (Element command_element) {
    1688         return XMLTools.getValue (command_element);
    1689     }
    1690    
    1691     /** 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.
    1692      * @param writer the BufferedWriter to which the str will be written
    1693      * @param str the String to be written
    1694      */
    1695     private void write (BufferedWriter writer, String str)
    1696     throws IOException {
    1697         writer.write (str, 0, str.length ());
    1698     }
    1699    
    1700     /** ********************************************************************************************************
    1701         The code from this point below are used for greenstone 3 collection configuration, i.e., read ColletionConfig.xml
    1702      * into the internal DOM tree, and convert the internal DOM tree back to CollectionConfig.xml.
    1703      *
    1704     Methods named 'doXXXX' are for convert collectionConfig.xml into the internal configuration xml structure;
    1705     Methods named 'convertXXXX' are for convert the internal configuration xml structure back to collectionConfig.xml.
    1706     ************************************************************************************************************ */
    1707    
    1708     /**Arguments:  metadataListNode->the 'displayItemList' element in collectionConfig.xml
    1709                 name_value->the value of the 'name' attribute of 'index' element;
    1710                 att_value->the value of the 'name' attribute of 'displayItem' element
    1711     return:     an ArrayList of the contructed 'CollectionMetadata' elements
    1712     */
    1713     private ArrayList doDisplayItemList (Document to, Node displayListNode, String att_value, String name_value) {
    1714         Element toElement = to.getDocumentElement ();
    1715         ArrayList display_item_list = new ArrayList ();
    1716         ArrayList item_list = XMLTools.getNamedElementList ((Element)displayListNode,
    1717         StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, att_value);
    1718         if (item_list == null) {
    1719             return null;
    1720         }
    1721        
    1722         for (int i=0; i<item_list.size (); i++) {
    1723             Element item = (Element)item_list.get (i);
    1724             String text = XMLTools.getNodeText (item);
    1725            
    1726             //If there is nothing to display, don't bother creating the element
    1727             if (text == "") {
    1728                 continue;
    1729             }
    1730             //get the value in 'lang=value'
    1731             String lang = item.getAttribute (StaticStrings.LANG_STR);
    1732            
    1733             Element e = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
    1734             e.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1735             e.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_value);
    1736             e.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
    1737             XMLTools.setNodeText (e, text);
    1738             display_item_list.add (e);
    1739         }
    1740         return display_item_list;
    1741     }
    1742    
    1743     private ArrayList doMetadataList (Document to, Node metadataListNode, String ele_name, String att_value) {
    1744         Element toElement = to.getDocumentElement ();
    1745         ArrayList metadata_list = new ArrayList ();
    1746        
    1747         ArrayList item_list = XMLTools.getNamedElementList ((Element)metadataListNode,
    1748         StaticStrings.METADATA_STR, StaticStrings.NAME_ATTRIBUTE, att_value);
    1749         if (item_list == null) {
    1750             return null;
    1751         }
    1752        
    1753         for (int i=0; i<item_list.size (); i++) {
    1754             Element item = (Element)item_list.get (i);
    1755             String text = XMLTools.getNodeText (item);
    1756            
    1757             //If there is nothing to display, don't bother creating the element
    1758             if (text == "") {
    1759                 continue;
    1760             }
    1761             //get the value in 'lang=value'
    1762             String lang = item.getAttribute (StaticStrings.LANG_STR);
    1763            
    1764             Element element = to.createElement (ele_name);
    1765             element.setAttribute (StaticStrings.NAME_ATTRIBUTE, att_value);
    1766             element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
    1767             element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1768             element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
    1769             XMLTools.setNodeText (element, text);
    1770            
    1771             metadata_list.add (element);
    1772         }
    1773         return metadata_list;
    1774     }
    1775     // 'to' is the internal structure
    1776     private void doMGIndexes (Document to, Node searchNode) {
    1777         Element toElement = to.getDocumentElement ();
    1778         Element indexes_element = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
    1779         indexes_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1780         indexes_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
    1781        
    1782         NodeList index_children = ((Element)searchNode).getElementsByTagName (StaticStrings.INDEX_LOW_STR);//index
    1783         int num_nodes = index_children.getLength ();
    1784        
    1785         for (int i=0; i<num_nodes; i++) {
    1786             Element e = (Element)index_children.item (i);
    1787             String index_str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    1788             String index_str_display = index_str;//used for creating collectionmetadata for this index
    1789             Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
    1790            
    1791             // For mg, it's the 'Old G2.38 and earlier' that use level:source tuplets, but we double check it anyway
    1792             boolean old_index = true;
    1793             if(index_str.indexOf (StaticStrings.COLON_CHARACTER) == -1) {
    1794                 // It doesn't contain ':' character
    1795                 System.err.println ("Something is wrong! the index should be level:source tuplets.");
    1796                 old_index = false;
    1797             }
    1798             else {
    1799                 // Handling 'index' element
    1800                 index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE,
    1801                 index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER)));
    1802                 index_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
    1803                
    1804                 //Each index may have a list of comma-separated strings.
    1805                 //split them into 'content' elements in the internal structure
    1806                 StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
    1807                 //index_str = "";
    1808                 while(content_tokenizer.hasMoreTokens ()) {
    1809                     // Replace index_str to be qualified name, eg. dc.Subject and keywords insread of dc.Subject.
    1810                    
    1811                    
    1812                     Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
    1813                     String content_str = content_tokenizer.nextToken ();
    1814                     // Since the contents of indexes have to be certain keywords, or metadata elements,
    1815                     //if the content isn't a keyword and doesn't yet have a namespace, append the extracted metadata namespace.
    1816                     if(content_str.indexOf (StaticStrings.NS_SEP) == -1) {
    1817                         if(content_str.equals (StaticStrings.TEXT_STR) ||
    1818                         (!old_index && content_str.equals (StaticStrings.ALLFIELDS_STR))) {
    1819                             // in this case, do nothing
    1820                         }
    1821                         else {
    1822                             content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
    1823                         }
    1824                     }
    1825                    
    1826                     content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
    1827                     index_element.appendChild (content_element);
    1828                     content_element = null;
    1829                 }   // while ends
    1830                
    1831                 indexes_element.appendChild (index_element);
    1832                
    1833                 // Handling 'displayItem' elements and Constructing 'collectionmetadata' elements
    1834                 // Use the fully qualified index names
    1835                 ArrayList collectionmetadata_list = doDisplayItemList (to, e, StaticStrings.NAME_ATTRIBUTE, index_str_display);
    1836                 appendArrayList (toElement, collectionmetadata_list);
    1837             } //else ends
    1838         } //for loop ends
    1839         appendProperly (toElement, indexes_element);
    1840        
    1841         //***//
    1842         // create another set of <indexes> which will be used when user switches to MGPP/LUCENE
    1843         // i.e. we build a default index set for a start
    1844        
    1845         String []index_strs =
    1846         {StaticStrings.TEXT_STR,
    1847          StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.TITLE_ELEMENT,
    1848          StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.SOURCE_ELEMENT};
    1849          
    1850          Element mgpp_indexes = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
    1851          mgpp_indexes.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
    1852          mgpp_indexes.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
    1853          for (int i=0; i<index_strs.length; i++) {
    1854              Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
    1855              Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
    1856              content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_strs[i]);
    1857              index_element.appendChild (content_element);
    1858              mgpp_indexes.appendChild (index_element);
    1859              
    1860              // Contructing 'collectionmetadata' elements for 'mgpp' indexes
    1861              Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
    1862              collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1863              collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_strs[i]);
    1864              collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
    1865              if (index_strs[i].indexOf (StaticStrings.NS_SEP) != -1) {
    1866                  index_strs[i] = index_strs[i].substring (index_strs[i].indexOf (StaticStrings.NS_SEP) + 1);
    1867              }
    1868              XMLTools.setNodeText (collectionmetadata, index_strs[i]);
    1869              
    1870              appendProperly (toElement, collectionmetadata);
    1871              
    1872          }
    1873          appendProperly (toElement, mgpp_indexes);
    1874     }
    1875    
    1876     //This is actually doing indexes for both mgpp and lucene
    1877     private void doMGPPIndexes (Document to, Node searchNode) {
    1878         Element toElement = to.getDocumentElement ();
    1879         Element indexes_element = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
    1880         indexes_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1881         indexes_element.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
    1882        
    1883         NodeList index_children = ((Element)searchNode).getElementsByTagName (StaticStrings.INDEX_LOW_STR);//index
    1884         int num_nodes = index_children.getLength ();
    1885        
    1886         for (int i=0; i<num_nodes; i++) {
    1887            
    1888             Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
    1889             Element e = (Element)index_children.item (i);
    1890             String index_str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    1891             String index_str_display = index_str;//for creating collectionmetadata for this index
    1892            
    1893             // Handling 'index' element
    1894             // Double check to make sure it's not colon separated style index.
    1895             boolean old_index = false;
    1896             if(index_str.indexOf (StaticStrings.COLON_CHARACTER) != -1) {
    1897                 System.err.println ("Something is wrong! the index should NOT be level:source tuplets style.");
    1898                 old_index = true;
    1899             }
    1900             //Each index may have a list of comma-separated strings.
    1901             //split them into 'content' elements in the internal structure
    1902             StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
    1903             //index_str = "";
    1904             while(content_tokenizer.hasMoreTokens ()) {
    1905                 // Replace index_str to be qualified name, eg. dc.Subject and keywords insread of dc.Subject.             
    1906                
    1907                 Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
    1908                 String content_str = content_tokenizer.nextToken ();
    1909                 // 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.
    1910                 if(content_str.indexOf (StaticStrings.NS_SEP) == -1) {
    1911                     if(content_str.equals (StaticStrings.TEXT_STR)) {
    1912                         // in this case, do nothing
    1913                     }
    1914                     else {
    1915                         content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
    1916                     }
    1917                 }
    1918                 content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
    1919                 index_element.appendChild (content_element);
    1920                 content_element = null;
    1921             } //while ends
    1922            
    1923             indexes_element.appendChild (index_element);
    1924            
    1925            
    1926             index_element = null;
    1927            
    1928             // Handling 'displayItem' element of this 'index' element
    1929             // 'e' is the parent element 'index' of 'displayItem' element
    1930             ArrayList collectionmetadata_list = doDisplayItemList (to, e, StaticStrings.NAME_ATTRIBUTE, index_str_display);
    1931             appendArrayList (toElement, collectionmetadata_list);
    1932            
    1933            
    1934         } // for loop ends
    1935         toElement.appendChild (indexes_element);
    1936        
    1937         // create another set of <indexes> which will be used when user switches to MG
    1938         // i.e. we build a default index set for a start
    1939         Element mg_indexes = to.createElement (StaticStrings.INDEXES_ELEMENT);//<Indexes>
    1940         mg_indexes.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
    1941         mg_indexes.setAttribute (StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
    1942        
    1943         //put the namespace '.ex' as prefix to the indexes
    1944         String []index_strs =
    1945         {StaticStrings.TEXT_STR,
    1946          StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.TITLE_ELEMENT,
    1947          StaticStrings.EXTRACTED_NAMESPACE + StaticStrings.SOURCE_ELEMENT};
    1948          for (int i=0; i<index_strs.length; i++) {
    1949              Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);//<Index>
    1950              index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE, StaticStrings.DOCUMENT_STR);
    1951              Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
    1952              content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_strs[i]);
    1953              index_element.appendChild (content_element);
    1954              
    1955              mg_indexes.appendChild (index_element);
    1956              
    1957              // Contructing 'collectionmetadata' elements for 'mg' indexes
    1958              Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
    1959              collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1960              String temp = StaticStrings.DOCUMENT_STR.concat (StaticStrings.COLON_CHARACTER).concat (index_strs[i]);
    1961              collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, temp);
    1962              collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
    1963              if (index_strs[i].indexOf (StaticStrings.NS_SEP) != -1) {
    1964                  index_strs[i] = index_strs[i].substring (index_strs[i].indexOf (StaticStrings.NS_SEP) + 1);
    1965              }
    1966              XMLTools.setNodeText (collectionmetadata, index_strs[i]);
    1967              
    1968              appendProperly (toElement, collectionmetadata);
    1969              
    1970          }
    1971          toElement.appendChild (mg_indexes);
    1972          
    1973     }
    1974    
    1975     private void doDisplayFormat (Document to, Element from) {
    1976         //display element in the xml file
    1977         Element de = (Element)XMLTools.getChildByTagName (from, StaticStrings.DISPLAY_STR);
    1978         if (de == null) {
    1979             return;
    1980         }
    1981         //format element in the display element
    1982         Element fe = (Element)XMLTools.getChildByTagName (de, StaticStrings.FORMAT_STR);
    1983 
    1984         to.getDocumentElement ().appendChild (doFormat(to, fe, StaticStrings.DISPLAY_STR));
    1985     }
    1986 
    1987     //construct 'DefaultIndex' element in the internal structure from collectionConfig.xml
    1988     private void doDefaultIndex (Document to, Node searchNode) {
    1989         Element toElement = to.getDocumentElement ();
    1990         Element default_index_element = to.createElement (StaticStrings.INDEX_DEFAULT_ELEMENT);
    1991         default_index_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    1992        
    1993         Element e = (Element)XMLTools.getChildByTagName (searchNode, StaticStrings.INDEX_DEFAULT_ELEMENT_LOWERCASE);//defaultIndex
    1994         if (e == null) {
    1995             return;
    1996         }
    1997         String index_str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    1998        
    1999         boolean old_index = false;
    2000         if(index_str.indexOf (StaticStrings.COLON_CHARACTER) != -1) {
    2001             //The index is 'level:source tuplets' which is for mg. Take out 'level'
    2002             old_index = true;
    2003             default_index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE,
    2004             index_str.substring (0, index_str.indexOf (StaticStrings.COLON_CHARACTER)));
    2005             index_str = index_str.substring (index_str.indexOf (StaticStrings.COLON_CHARACTER) + 1);
    2006         } else {
    2007             default_index_element.setAttribute (StaticStrings.LEVEL_ATTRIBUTE, "");
    2008         }
    2009        
    2010         //Each index may have a list of comma-separated strings.
    2011         //split them into 'content' elements in the internal structure
    2012         StringTokenizer content_tokenizer = new StringTokenizer (index_str, StaticStrings.COMMA_CHARACTER);
    2013         while(content_tokenizer.hasMoreTokens ()) {
    2014             Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
    2015             String content_str = content_tokenizer.nextToken ();
    2016             // 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.
    2017             if(content_str.indexOf (StaticStrings.NS_SEP) == -1) {
    2018                 if(content_str.equals (StaticStrings.TEXT_STR) ||
    2019                 (!old_index && content_str.equals (StaticStrings.ALLFIELDS_STR))) {
    2020                     // in this case, do nothing
    2021                 }
    2022                 else {
    2023                     content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
    2024                 }
    2025             }
    2026 
    2027             content_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, content_str);
    2028             default_index_element.appendChild (content_element);
    2029             content_element = null;
    2030         }
    2031         appendProperly (toElement, default_index_element);
    2032     }
    2033     // For mg, this method is still called, but make it 'assigned=false'
    2034     private void doDefaultLevel (Document to, Node searchNode) {
    2035         Element toElement = to.getDocumentElement ();
    2036         Element default_index_option = to.createElement (StaticStrings.INDEXOPTION_DEFAULT_ELEMENT);
    2037         default_index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.LEVEL_DEFAULT_STR);
    2038        
    2039         Element e = (Element)XMLTools.getChildByTagName (searchNode, StaticStrings.LEVEL_DEFAULT_ELEMENT);
    2040         if (e != null) {
    2041             default_index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2042             String level = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2043             default_index_option.setAttribute (StaticStrings.VALUE_ATTRIBUTE, level);
    2044         } else {
    2045             //In the case of mg, there's no level! build a default one using 'assigned=false value=document'
    2046             default_index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
    2047             default_index_option.setAttribute (StaticStrings.VALUE_ATTRIBUTE, StaticStrings.DOCUMENT_STR);
    2048         }
    2049         appendProperly (toElement, default_index_option);
    2050     }
    2051    
    2052     // Transform plugins (pluginListNode) of collectionConfig.xml into the internal structure (i.e. Document to)
    2053     private void doPlugin (Document to, Node pluginListNode) {
    2054         Element toElement = to.getDocumentElement ();
    2055         NodeList plugin_children = ((Element)pluginListNode).getElementsByTagName (StaticStrings.PLUGIN_STR);
    2056         int plugin_nodes = plugin_children.getLength ();
    2057        
    2058         if (plugin_nodes < 1) {
    2059             return;
    2060         }
    2061        
    2062         for (int i=0; i<plugin_nodes; i++) {
    2063             Element e = (Element)plugin_children.item (i);
    2064             String str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2065         str = ensureNewPluginName(str);
    2066             Element plugin_element = to.createElement (StaticStrings.PLUGIN_ELEMENT);
    2067             plugin_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, str);
    2068            
    2069            
    2070             NodeList option_children = e.getElementsByTagName (StaticStrings.OPTION_STR);
    2071            
    2072             for (int j=0; j<option_children.getLength (); j++) {
    2073                 Element el = (Element)option_children.item (j);
    2074                 String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2075                 if (name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
    2076                     name_str = name_str.substring (1);
    2077                 }
    2078                 String value_str = el.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
    2079                 Element option_element = null;
    2080                
    2081                 if (name_str.equals ("") && !value_str.equals ("")) {
    2082                     continue;
    2083                 }
    2084                
    2085                
    2086                 option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
    2087                 option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2088                 if(name_str.equals (StaticStrings.RECPLUG_STR) && value_str.equals (StaticStrings.USE_METADATA_FILES_ARGUMENT)) {
    2089                     continue; // ignore this option
    2090                 }
    2091                
    2092                 if(value_str != null) {
    2093                     // Remove any speech marks appended in strings containing whitespace
    2094                     if(value_str.startsWith (StaticStrings.SPEECH_CHARACTER) && value_str.endsWith (StaticStrings.SPEECH_CHARACTER)) {
    2095                         value_str = value_str.substring (1, value_str.length () - 1);
    2096                     }
    2097                     if(name_str.equals (StaticStrings.METADATA_STR)) {
    2098                         // 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.
    2099                         String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
    2100                         value_str = "";
    2101                         for (int k=0; k<=values.length-1; k++) {
    2102                             if (values[k].indexOf (StaticStrings.NS_SEP) == -1) {
    2103                                 values[k] = StaticStrings.EXTRACTED_NAMESPACE + values[k];
    2104                             }
    2105 
    2106                             if (k < values.length-1) {
    2107                                 value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
    2108                                
    2109                             } else {
    2110                                 value_str = value_str + values[k];
    2111                             }
    2112                         }
    2113                     }
    2114                 }
    2115                 if (!name_str.equals ("")) {
    2116                     option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    2117                 }
    2118                 if (!value_str.equals ("")) {
    2119                     XMLTools.setNodeText (option_element, value_str);
    2120                 }
    2121                 plugin_element.appendChild (option_element);
    2122                
    2123             }
    2124            
    2125             appendProperly (toElement, plugin_element);
    2126         }
    2127        
    2128     }
    2129    
    2130     //Handle classifiers
    2131     private void doClassifier (Document to, Node browseNode) {
    2132         Element toElement = to.getDocumentElement ();
    2133         NodeList classifier_children = ((Element)browseNode).getElementsByTagName (StaticStrings.CLASSIFIER_STR);
    2134         int num_nodes = classifier_children.getLength ();
    2135        
    2136         if (num_nodes < 1) {
    2137             return;
    2138         }
    2139        
    2140         for (int i=0; i<num_nodes; i++) {
    2141             Element e = (Element)classifier_children.item (i);
    2142             String str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2143             Element classify_element = to.createElement (StaticStrings.CLASSIFY_ELEMENT);
    2144             classify_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, str);
    2145            
    2146             String options_str = "";
    2147             NodeList option_children = e.getElementsByTagName (StaticStrings.OPTION_STR);
    2148             for (int j=0; j<option_children.getLength (); j++) {
    2149                 Element el = (Element)option_children.item (j);
    2150                 String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2151                 options_str = options_str + ((name_str.equals(""))? "" : (" " + name_str));
    2152                 if (name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
    2153                     name_str = name_str.substring (1);
    2154                 }
    2155                 String value_str = el.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
    2156                 options_str = options_str + ((name_str.equals(""))? "" : (" " + value_str));
    2157                 Element option_element = null;
    2158                
    2159                 if (name_str.equals ("") && !value_str.equals ("")) {
    2160                     continue; //invalid condition
    2161                 }
    2162                
    2163                 option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
    2164                 option_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2165                
    2166                 if (!name_str.equals ("")) {
    2167                     option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    2168                 }
    2169                
    2170                 if (!value_str.equals ("") && name_str.equals (StaticStrings.METADATA_STR)) {
    2171                     // 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.
    2172             String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
    2173             value_str = "";
    2174                     for (int k=0; k<=values.length-1; k++) {
    2175                         if (values[k].indexOf (StaticStrings.NS_SEP) == -1) {
    2176                             values[k] = StaticStrings.EXTRACTED_NAMESPACE + values[k];
    2177                         }
    2178                         else {
    2179                             MetadataElement metadata_element = MetadataTools.getMetadataElementWithName (values[k]);
    2180                             if (metadata_element != null) {
    2181                                 values[k] = metadata_element.getDisplayName ();
    2182                             }
    2183                         }
    2184                         if (k < values.length-1) {
    2185                             value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
    2186                         } else {
    2187                             value_str = value_str + values[k];
    2188                         }
    2189                     }
    2190                 }
    2191                
    2192                 if (value_str != null && !value_str.equals ("")) {
    2193                     XMLTools.setNodeText (option_element, value_str);
    2194                 }
    2195                 classify_element.appendChild (option_element);
    2196             }
    2197             //format element for this classifier
    2198             Element format = (Element)XMLTools.getChildByTagName (e, StaticStrings.FORMAT_STR);
    2199             if(format != null) {
    2200                 classify_element.appendChild (doFormat(to, format, null));
    2201             }
    2202             appendProperly (toElement, classify_element);
    2203         }
    2204        
    2205         // default format statement for all classifiers
    2206         Element default_classifier_format = (Element)XMLTools.getChildByTagName (browseNode, StaticStrings.FORMAT_STR);
    2207 
    2208         to.getDocumentElement ().appendChild (doFormat(to, default_classifier_format, StaticStrings.BROWSE_STR));
    2209     }
    2210     private Element doFormat(Document to, Element format, String name_str) {
    2211             Element format_element = to.createElement (StaticStrings.FORMAT_STR);
    2212             if (name_str != null) {
    2213                 format_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    2214             }
    2215             if (format != null) {
    2216                 String gsf_text = XMLTools.xmlNodeToStringWithoutIndenting(format);
    2217                
    2218                 if (gsf_text.startsWith("<") && (gsf_text.indexOf("<") != gsf_text.lastIndexOf("<"))) {
    2219                     gsf_text = gsf_text.substring(gsf_text.indexOf("<gsf"),
    2220                                           gsf_text.indexOf(StaticStrings.FORMAT_END_TAG));
    2221                 }
    2222                
    2223                 XMLTools.setNodeText(format_element, gsf_text);
    2224             }
    2225             return format_element;
    2226     }
    2227     // Handling 'subcollection' elements in 'search' element of 'collectionConfig.xml'
    2228     private void doSubcollection (Document to, Node searchNode) {
    2229         Element toElement = to.getDocumentElement ();
    2230         NodeList sub_children = ((Element)searchNode).getElementsByTagName (StaticStrings.SUBCOLLECTION_STR);
    2231         int sub_nodes = sub_children.getLength ();
    2232        
    2233         // There is no subcollection
    2234         if (sub_nodes < 1) {
    2235             return;
    2236         }
    2237        
    2238         for (int i=0; i<sub_nodes; i++) {
    2239             Element sub_child = (Element)sub_children.item (i);
    2240             String name_str = sub_child.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2241             String filter_str = sub_child.getAttribute (StaticStrings.FILTER_ATTRIBUTE);
    2242            
    2243             // filter_str is in the form '<! (if set)><metadata>/<metadata value>/<flag (if any)>'
    2244            
    2245             int pos = filter_str.indexOf (StaticStrings.SEPARATOR_CHARACTER);
    2246             String meta_str = "";
    2247             String meta_value_str = "";
    2248             String clude_str = "";
    2249             String flag_str = "";
    2250             if (pos == -1) {
    2251                
    2252                 meta_str = meta_value_str = filter_str;
    2253                 clude_str = StaticStrings.INCLUDE_STR;
    2254             } else {
    2255                 clude_str = StaticStrings.INCLUDE_STR;
    2256                 if (filter_str.startsWith (StaticStrings.EXCLAMATION_CHARACTER)) {
    2257                     clude_str = StaticStrings.EXCLUDE_STR;
    2258                     // Peel off "!"
    2259                     filter_str = filter_str.substring (StaticStrings.EXCLAMATION_CHARACTER.length ());
    2260                 }
    2261                
    2262                 String[] strs = filter_str.split (StaticStrings.SEPARATOR_CHARACTER);
    2263                 if (strs[0] != null && strs[0] != "") {
    2264                     meta_str = strs[0];
    2265                 }
    2266                 if(!meta_str.equals (StaticStrings.FILENAME_STR) && meta_str.indexOf (StaticStrings.NS_SEP) == -1) {
    2267                     meta_str = StaticStrings.EXTRACTED_NAMESPACE + meta_str;
    2268                 }
    2269                
    2270                 if (strs[1] != null && strs[1] != "") {
    2271                     meta_value_str = strs[1];
    2272                 }
    2273                 if (strs.length > 2) {
    2274                     //This means there has been set a flag
    2275                     if (strs[2] != null && strs[2] != "") {
    2276                         flag_str = strs[2];
    2277                     }
    2278                 }
    2279             }
    2280             Element subcollection_element = to.createElement (StaticStrings.SUBCOLLECTION_ELEMENT);
    2281             subcollection_element.setAttribute (StaticStrings.NAME_STR, name_str);
    2282             subcollection_element.setAttribute (StaticStrings.CONTENT_ATTRIBUTE, meta_str);
    2283             subcollection_element.setAttribute (StaticStrings.TYPE_ATTRIBUTE, clude_str);
    2284             if (flag_str != "") {
    2285                 subcollection_element.setAttribute (StaticStrings.OPTIONS_ATTRIBUTE, flag_str);
    2286             }
    2287             XMLTools.setNodeText (subcollection_element, meta_value_str);
    2288            
    2289             toElement.appendChild (subcollection_element);
    2290         }
    2291     }
    2292     //Handle levels (document, section). In the internal structure, the element is called 'IndexOption'
    2293     private void doLevel (Document to, Node searchNode) {
    2294         Element toElement = to.getDocumentElement ();
    2295         NodeList level_children = ((Element)searchNode).getElementsByTagName (StaticStrings.LEVEL_ATTRIBUTE);
    2296         int level_nodes = level_children.getLength ();
    2297        
    2298         // it's mg, there's no level. So we construct a default 'indexOption' in the internal structure
    2299         if (level_nodes < 1) {
    2300             Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
    2301             index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
    2302             index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.LEVELS_STR);
    2303            
    2304             Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
    2305             option_element.setAttribute (StaticStrings.NAME_STR, StaticStrings.DOCUMENT_STR);
    2306             index_option.appendChild (option_element);
    2307            
    2308             appendProperly (toElement, index_option);
    2309            
    2310             return;
    2311         }
    2312        
    2313         Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
    2314         index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2315         index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.LEVELS_STR);
    2316        
    2317         for (int i=0; i<level_nodes; i++) {
    2318             Element level_element = (Element)level_children.item (i);
    2319             String level_str = level_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2320             Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
    2321             option_element.setAttribute (StaticStrings.NAME_STR, level_str);
    2322             index_option.appendChild (option_element);
    2323            
    2324            
    2325             // Contructing 'collectionmetadata' elements from the 'displayItem' of this 'level' element
    2326             ArrayList displayItem_list = XMLTools.getNamedElementList (level_element,
    2327             StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_STR);
    2328             if (displayItem_list == null) {
    2329                 return ;
    2330             }
    2331             for (int j=0; j<displayItem_list.size (); j++) {
    2332                 Element item = (Element)displayItem_list.get (j);
    2333                 String text = XMLTools.getNodeText (item);
    2334                 String lang = item.getAttribute (StaticStrings.LANG_ATTRIBUTE);
    2335                
    2336                 //If there is nothing to display, don't bother creating the element
    2337                 if (text == "") {
    2338                     continue;
    2339                 }
    2340                 Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
    2341                 collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2342                 collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, level_str);
    2343                 collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
    2344                 XMLTools.setNodeText (collectionmetadata, text);
    2345                
    2346                 appendProperly (toElement, collectionmetadata);
    2347             }
    2348         }
    2349         appendProperly (toElement, index_option);
    2350     }
    2351     //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.
    2352     private void doIndexSubcollection (Document to, Node searchNode) {
    2353         Element toElement = to.getDocumentElement ();
    2354         NodeList index_sub_children = ((Element)searchNode).getElementsByTagName (StaticStrings.SUBCOLLECTION_INDEX_ELEMENT);
    2355         int num_nodes = index_sub_children.getLength ();
    2356        
    2357         // there is no subcollection index
    2358         if (num_nodes < 1) {
    2359             return;
    2360         }
    2361        
    2362         Element subcollection_indexes = to.createElement (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT);
    2363        
    2364         for (int i=0; i<num_nodes; i++) {
    2365             Element index_element = to.createElement (StaticStrings.INDEX_ELEMENT);
    2366             Element index_sub_child = (Element)index_sub_children.item (i);
    2367             String name_str = index_sub_child.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2368            
    2369             // name_str is in the form of comma separated strings, each of which is a subcollection filter name
    2370             String[] filters = name_str.split (StaticStrings.COMMA_CHARACTER);
    2371             for (int j=0; j<filters.length; j++) {
    2372                
    2373                 Element content_element = to.createElement (StaticStrings.CONTENT_ELEMENT);
    2374                 content_element.setAttribute (StaticStrings.NAME_STR, filters[j]);
    2375                 index_element.appendChild (content_element);
    2376             }
    2377             subcollection_indexes.appendChild (index_element);
    2378            
    2379             // Contructing 'collectionmetadata' elements from the 'displayItem' of this 'indexSubcollection' element
    2380             ArrayList displayItem_list = XMLTools.getNamedElementList (index_sub_child,
    2381             StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_STR);
    2382             if (displayItem_list == null) {
    2383                 // there is no display item for this element
    2384                 continue;
    2385             }
    2386             for (int j=0; j<displayItem_list.size (); j++) {
    2387                 Element item = (Element)displayItem_list.get (j);
    2388                 String text = XMLTools.getNodeText (item);
    2389                 String lang = item.getAttribute (StaticStrings.LANG_ATTRIBUTE);
    2390                
    2391                 //If there is nothing to display, don't bother creating the element
    2392                 if (text == "") {
    2393                     continue;
    2394                 }
    2395                 Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
    2396                 collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2397                 collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    2398                 collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
    2399                 XMLTools.setNodeText (collectionmetadata, text);
    2400                
    2401                 appendProperly (toElement, collectionmetadata);
    2402             }
    2403         }
    2404         appendProperly (toElement, subcollection_indexes);
    2405     }
    2406     //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.
    2407     private void doIndexLanguage (Document to, Node searchNode) {
    2408         Element toElement = to.getDocumentElement ();
    2409         NodeList index_sub_children = ((Element)searchNode).getElementsByTagName (StaticStrings.LANGUAGE_INDEX_ELEMENT);
    2410         int num_nodes = index_sub_children.getLength ();
    2411        
    2412         // there is no subcollection index
    2413         if (num_nodes < 1) {
    2414             return;
    2415         }
    2416        
    2417         Element language_indexes = to.createElement (StaticStrings.LANGUAGES_ELEMENT);
    2418        
    2419         for (int i=0; i<num_nodes; i++) {
    2420             Element language_element = to.createElement (StaticStrings.LANGUAGE_ELEMENT);
    2421             Element index_sub_child = (Element)index_sub_children.item (i);
    2422             String name_str = index_sub_child.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2423             language_element.setAttribute (StaticStrings.NAME_STR, name_str);
    2424             language_indexes.appendChild (language_element);
    2425            
    2426             // Contructing 'collectionmetadata' elements from the 'displayItem' of this 'indexLanguage' element
    2427             ArrayList displayItem_list = XMLTools.getNamedElementList (index_sub_child,
    2428             StaticStrings.DISPLAYITEM_STR, StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_STR);
    2429             if (displayItem_list == null) {
    2430                 // there is no display item for this element
    2431                 continue;
    2432             }
    2433             for (int j=0; j<displayItem_list.size (); j++) {
    2434                 Element item = (Element)displayItem_list.get (j);
    2435                 String text = XMLTools.getNodeText (item);
    2436                 String lang = item.getAttribute (StaticStrings.LANG_ATTRIBUTE);
    2437                
    2438                 //If there is nothing to display, don't bother creating the element
    2439                 if (text == "") {
    2440                     continue;
    2441                 }
    2442                 Element collectionmetadata = to.createElement (StaticStrings.COLLECTIONMETADATA_ELEMENT);
    2443                 collectionmetadata.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2444                 collectionmetadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    2445                 collectionmetadata.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, lang);
    2446                 XMLTools.setNodeText (collectionmetadata, text);
    2447                
    2448                 appendProperly (toElement, collectionmetadata);
    2449             }
    2450         }
    2451         toElement.appendChild (language_indexes);
    2452     }
    2453     // Handling both searchType and search format statement
    2454     private void doSearchFormat (Document to, Node searchNode) {
    2455         //There are two elements called <format> in <search>: one is for searchType; another is for format statement
    2456         NodeList format_children = ((Element)searchNode).getElementsByTagName (StaticStrings.FORMAT_STR);
    2457         int format_nodes = format_children.getLength ();
    2458         if (format_nodes < 1) {
    2459             return;
    2460         }
    2461         Element format = null;
    2462         Element search_type = null;
    2463         for(int i=0; i<format_nodes; i++) {
    2464             Node e = format_children.item (i);
    2465             if (e.hasAttributes () == false) {
    2466                 //The format element for format statement has no any attribute
    2467                 format = (Element)e;
    2468             }
    2469             else if (((Element)e).getAttribute (StaticStrings.NAME_ATTRIBUTE).equals(StaticStrings.SEARCHTYPE_ELEMENT)) {
    2470                 search_type = (Element)e;
    2471             }
    2472         }
    2473         //format statement for search
    2474         if (format != null) {           
    2475             (to.getDocumentElement ()).appendChild (doFormat(to, format, StaticStrings.SEARCH_STR));
    2476         }
    2477         // searchType in search
    2478         if(search_type != null) {
    2479             String searchtype_str = XMLTools.getNodeText(search_type);
    2480        
    2481             Element search_type_element = to.createElement (StaticStrings.FORMAT_STR);
    2482             search_type_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.SEARCHTYPE_ELEMENT);
    2483             XMLTools.setNodeText(search_type_element, searchtype_str);
    2484        
    2485        
    2486             appendProperly (to.getDocumentElement (), search_type_element);
    2487         }
    2488     }
    2489     // Handling defaultIndexLanguage and languageMetadata in collectionConfig.xml ('elementNameFrom'); in the internal structure, they are called 'DefaultLanguage' and 'LanguageMetadata' ('elementNameTo') respectively.
    2490     // Converting from collectionConfig.xml to the internal xml structure.
    2491     private void doLanguageMetadata (Document to, Node searchNode) {
    2492         Element toElement = to.getDocumentElement ();
    2493         String elementNameFrom = StaticStrings.LANGUAGE_METADATA_ELEMENT_STR;
    2494         String elementNameTo = StaticStrings.LANGUAGE_METADATA_ELEMENT;
    2495         Node from_element = XMLTools.getChildByTagName (searchNode, elementNameFrom);
    2496         if (from_element == null) {
    2497             return; // such an element not found
    2498         }
    2499        
    2500         Element to_element = to.createElement (elementNameTo);
    2501        
    2502         String name_str = ((Element)from_element).getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2503         if (name_str.indexOf (StaticStrings.NS_SEP) == -1) {
    2504             name_str = StaticStrings.EXTRACTED_NAMESPACE + name_str;
    2505         }
    2506         to_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    2507         to_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2508        
    2509         toElement.appendChild (to_element);
    2510     }
    2511     private void doReplaceListRef (Document to, Element from) {
    2512         Element toElement = to.getDocumentElement ();
    2513        
    2514         Node replace_element = XMLTools.getChildByTagName (from, StaticStrings.REPLACELISTREF_STR);
    2515         if (replace_element == null) {
    2516             return; // such an element not found
    2517         }
    2518        
    2519         Element to_element = XMLTools.duplicateElement (to, (Element)replace_element, true);
    2520         toElement.appendChild (to_element);
    2521     }
    2522     private void convertReplaceListRef (Document from, Document to) {
    2523         Element toElement = to.getDocumentElement ();
    2524        
    2525         Node replace_element = XMLTools.getChildByTagName (from.getDocumentElement (), StaticStrings.REPLACELISTREF_STR);
    2526         if (replace_element == null) {
    2527             return; // such an element not found
    2528         }
    2529        
    2530         Element to_element = XMLTools.duplicateElement (to, (Element)replace_element, true);
    2531         toElement.appendChild (to_element);
    2532     }
    2533     private void doOAIElement (Document to, Element from) {
    2534         Element toElement = to.getDocumentElement ();
    2535        
    2536         Node oai_element = XMLTools.getChildByTagName (from, StaticStrings.OAI_ELEMENT);
    2537         if (oai_element == null) {
    2538             return; // such an element not found
    2539         }
    2540        
    2541         Element to_element = XMLTools.duplicateElement (to, (Element)oai_element, true);
    2542         toElement.appendChild (to_element);
    2543     }
    2544     private void convertOAIElement (Document from, Document to) {
    2545         Element toElement = to.getDocumentElement ();
    2546        
    2547         Node oai_element = XMLTools.getChildByTagName (from.getDocumentElement (), StaticStrings.OAI_ELEMENT);
    2548         if (oai_element == null) {
    2549             return; // such an element not found
    2550         }
    2551        
    2552         Element to_element = XMLTools.duplicateElement (to, (Element)oai_element, true);
    2553         toElement.appendChild (to_element);
    2554     }
    2555     private void doDefaultIndexLanguage (Document to, Node searchNode) {
    2556         Element toElement = to.getDocumentElement ();
    2557         String elementNameFrom = StaticStrings.LANGUAGE_DEFAULT_INDEX_ELEMENT;
    2558         String elementNameTo = StaticStrings.LANGUAGE_DEFAULT_ELEMENT;
    2559         Node from_element = XMLTools.getChildByTagName (searchNode, elementNameFrom);
    2560         if (from_element == null) {
    2561             return; // such an element not found
    2562         }
    2563        
    2564         Element to_element = to.createElement (elementNameTo);
    2565        
    2566         String name_str = ((Element)from_element).getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2567         to_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    2568         to_element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2569        
    2570         toElement.appendChild (to_element);
    2571     }
    2572    
    2573     //Handle 'indexOption' (i.e. casefold, stem etc). In the internal structure, the element is called 'IndexOption'
    2574     private void doIndexOption (Document to, Node searchNode) {
    2575         Element toElement = to.getDocumentElement ();
    2576         Node index_option_node = XMLTools.getChildByTagName (searchNode, StaticStrings.INDEXOPTION_STR);
    2577         if (index_option_node == null) {
    2578             return;
    2579         }
    2580         NodeList option_children = ((Element)index_option_node).getElementsByTagName (StaticStrings.OPTION_STR);
    2581         int option_nodes = option_children.getLength ();
    2582        
    2583         // for lucene, there is no 'indexOption'. We build a default 'indexOption' and 'assigned=false' in case the user switches to mg or mgpp
    2584         if (option_nodes < 1) {
    2585             Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
    2586             index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
    2587             index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.INDEXOPTIONS_STR);
    2588             String[] option_str =
    2589             { StaticStrings.CASEFOLD_OPTION_STR, StaticStrings.STEM_OPTION_STR };
    2590             for (int i=0; i<option_str.length; i++) {
    2591                 Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
    2592                 option_element.setAttribute (StaticStrings.NAME_STR, option_str[i]);
    2593                 index_option.appendChild (option_element);
    2594             }
    2595             appendProperly (toElement, index_option);
    2596             return;
    2597         }
    2598        
    2599         Element index_option = to.createElement (StaticStrings.INDEXOPTIONS_ELEMENT);
    2600         index_option.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2601         index_option.setAttribute (StaticStrings.NAME_STR, StaticStrings.INDEXOPTIONS_STR);
    2602        
    2603         for (int i=0; i<option_nodes; i++) {
    2604             String option_str = ((Element)option_children.item (i)).getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2605             Element option_element = to.createElement (StaticStrings.OPTION_ELEMENT);
    2606             option_element.setAttribute (StaticStrings.NAME_STR, option_str);
    2607             index_option.appendChild (option_element);
    2608         }
    2609         appendProperly (toElement, index_option);
    2610     }
    2611    
    2612     private Element doBuildType (Document to, String att_value) {
    2613        
    2614         //construct 'BuildType' element
    2615         Element element = to.createElement (StaticStrings.BUILDTYPE_ELEMENT);
    2616         element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
    2617         element.setAttribute (StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
    2618         element.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2619         element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
    2620 
    2621         XMLTools.setNodeText (element, att_value);
    2622        
    2623         return element;
    2624     }
    2625    
    2626     // Convert 'description', 'smallicon' etc.
    2627     private void convertDisplayItemList (Document from, Document to) {
    2628         Element displayItemList = to.createElement (StaticStrings.DISPLAYITEMLIST_STR);
    2629         Element destination = to.getDocumentElement ();
    2630        
    2631         String []att_values =
    2632         {StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR,
    2633          StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR,
    2634          StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR,
    2635          StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR};
    2636          
    2637          String []map_attrs =
    2638          {StaticStrings.DESCRIPTION_STR,
    2639           StaticStrings.SMALLICON_STR,
    2640           StaticStrings.ICON_STR,
    2641           StaticStrings.NAME_STR};
    2642          
    2643           for (int i=0; i<att_values.length; i++) {
    2644              
    2645               //dOc
    2646               ArrayList e_list = XMLTools.getNamedElementList (from.getDocumentElement (),
    2647               StaticStrings.COLLECTIONMETADATA_ELEMENT,
    2648               StaticStrings.NAME_ATTRIBUTE, att_values[i]);
    2649               // if such elements don't exist, don't bother
    2650               if (e_list == null) {
    2651                   continue;
    2652               }
    2653               for (int j=0; j<e_list.size (); j++) {
    2654                   Element e = (Element)e_list.get (j);
    2655                   if (e.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    2656                       continue;
    2657                   }
    2658                   String text = XMLTools.getNodeText (e);
    2659                   String lang = e.getAttribute (StaticStrings.LANGUAGE_ATTRIBUTE);
    2660                  
    2661                   Element displayItem = constructElement (StaticStrings.DISPLAYITEM_STR, map_attrs[i],
    2662                   StaticStrings.LANG_STR, lang, text, to);
    2663                   displayItemList.appendChild (displayItem);
    2664               }
    2665              
    2666           }
    2667           destination.appendChild (displayItemList);
    2668     }
    2669     // This method creates a DisplayItem element of the type of 'to' by using the ingredients from the element 'e'
    2670     private Element constructDisplayItem (Element e, Document to) {
    2671         String lang_string = e.getAttribute (StaticStrings.LANGUAGE_ATTRIBUTE);
    2672         String text = XMLTools.getNodeText (e);
    2673         Element displayItem = to.createElement (StaticStrings.DISPLAYITEM_STR);
    2674         displayItem.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.NAME_ATTRIBUTE);
    2675         displayItem.setAttribute (StaticStrings.LANG_STR, lang_string);
    2676         XMLTools.setNodeText (displayItem, text);
    2677         return displayItem;
    2678     }
    2679     private void convertMetadataList (Document from, Document to) {
    2680         Element metadataList = to.createElement (StaticStrings.METADATALIST_STR);
    2681         Element destination = to.getDocumentElement ();
    2682        
    2683         String []ele_names =
    2684         {StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT,
    2685          StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT,
    2686          StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT};
    2687          String []att_names =
    2688          {StaticStrings.COLLECTIONMETADATA_CREATOR_STR,
    2689           StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR,
    2690           StaticStrings.COLLECTIONMETADATA_PUBLIC_STR};
    2691           for (int i=0; i<ele_names.length; i++) {
    2692               Element e = XMLTools.getNamedElement (from.getDocumentElement (),
    2693               ele_names[i], StaticStrings.NAME_ATTRIBUTE, att_names[i]);
    2694               if (e == null) {
    2695                   continue;
    2696               }
    2697               String text = XMLTools.getNodeText (e);
    2698               Element metadata = to.createElement (StaticStrings.METADATA_STR);
    2699               metadata.setAttribute (StaticStrings.NAME_ATTRIBUTE, att_names[i]);
    2700               metadata.setAttribute (StaticStrings.LANG_STR, StaticStrings.ENGLISH_LANGUAGE_STR);
    2701               XMLTools.setNodeText (metadata, text);
    2702               metadataList.appendChild (metadata);
    2703           }
    2704 
    2705           destination.appendChild (metadataList);
    2706     }
    2707     // This method creates an element with the name 'element_name' of the type of 'to' by using the other three strings
    2708     private Element constructElement (String element_name, String name_value, String lang_att, String lang_value, String text, Document to) {
    2709         Element e = to.createElement (element_name);
    2710         e.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    2711         e.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_value);
    2712         e.setAttribute (lang_att, lang_value);
    2713         XMLTools.setNodeText (e, text);
    2714        
    2715         return e;
    2716     }
    2717     // Convert classify in the internal(i.e. Document from) to collectionconfig.xml (i.e. Document to)
    2718     private void convertClassifier (Document from, Document to) {
    2719         Element browse_element = to.createElement (StaticStrings.BROWSE_STR);
    2720         NodeList children = from.getDocumentElement ().getElementsByTagName (StaticStrings.CLASSIFY_ELEMENT);
    2721        
    2722         int num_children = (children == null)? 0 : children.getLength ();
    2723        
    2724         if (num_children == 0) {
    2725             return ;
    2726         }
    2727        
    2728         for (int i=0; i<num_children; i++) {
    2729            
    2730             Element child =  (Element)children.item (i);
    2731             if (child.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    2732                 continue;
    2733             }
    2734             String str = child.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
    2735             Element classifier_element = to.createElement (StaticStrings.CLASSIFIER_STR);
    2736             classifier_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, str);
    2737            
    2738             NodeList option_children = child.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
    2739             for (int j=0; j<option_children.getLength (); j++) {
    2740                 Element el = (Element)option_children.item (j);
    2741                 if (el.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    2742                     continue;
    2743                 }
    2744                 String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2745                 String value_str = XMLTools.getNodeText (el);
    2746                
    2747                
    2748                 if (name_str == null && value_str == null) {
    2749                     continue;
    2750                 }
    2751                 Element option_element = to.createElement (StaticStrings.OPTION_STR);
    2752                 if (name_str != null && name_str.equals (StaticStrings.METADATA_STR)) {
    2753                    
    2754                     // 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.
    2755             String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
    2756             value_str = "";
    2757                     for (int k=0; k<=values.length-1; k++) {
    2758                         if(values[k].startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
    2759                             values[k] = values[k].substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
    2760                         }
    2761                         else {
    2762                             MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName (values[k]);
    2763                             if (metadata_element != null) {
    2764                                 values[k] = metadata_element.getFullName ();
    2765                             }
    2766                         }
    2767                         if (k < values.length-1) {
    2768                             value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
    2769                         } else {
    2770                             value_str = value_str + values[k];
    2771                         }
    2772                     }
    2773                 }
    2774                
    2775                 if (!name_str.equals ("")) {
    2776                     if (!name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
    2777                         name_str = StaticStrings.MINUS_CHARACTER + name_str;
    2778                     }
    2779                     option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    2780                 }
    2781                
    2782                 if (!value_str.equals ("")) {
    2783                     option_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, value_str);
    2784                 }
    2785                
    2786                 classifier_element.appendChild (option_element);
    2787             }
    2788            
    2789             //format element for this classifier
    2790             Element e = (Element)XMLTools.getChildByTagName (child, StaticStrings.FORMAT_STR);
    2791            
    2792             if (e != null) {
    2793                 classifier_element.appendChild (convertFormat(to, e));
    2794             }
    2795             browse_element.appendChild (classifier_element);
    2796         }
    2797        
    2798         //convert default classifier format
    2799         Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
    2800                                                 StaticStrings.NAME_ATTRIBUTE,  StaticStrings.BROWSE_STR);
    2801         browse_element.appendChild (convertFormat(to, e));
    2802        
    2803         to.getDocumentElement ().appendChild (browse_element);
    2804     }
    2805     private Element convertFormat(Document to, Element e) {
    2806         String format_str = XMLTools.getNodeText(e);
    2807         Element format = to.createElement (StaticStrings.FORMAT_STR);
    2808         //XMLTools.copyAllChildren (format, e);
    2809         XMLTools.setNodeText(format, format_str);
    2810         return format;
    2811     }
    2812     //convert format statement for search
    2813     private void convertSearchFormat (Document from, Document to) {
    2814         Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
    2815         Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
    2816                                                 StaticStrings.NAME_ATTRIBUTE,  StaticStrings.SEARCH_STR);
    2817                                                
    2818         search.appendChild (convertFormat(to, e));
    2819        
    2820     }
    2821     //convert format statement for display of the documents
    2822     private void convertDisplayFormat (Document from, Document to) {
    2823         Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
    2824                                                 StaticStrings.NAME_ATTRIBUTE,  StaticStrings.DISPLAY_STR);
    2825         if (e == null) {
    2826             return;
    2827         }
    2828         Element display = to.createElement (StaticStrings.DISPLAY_STR);
    2829         display.appendChild (convertFormat(to, e));
    2830         to.getDocumentElement ().appendChild (display);
    2831     }
    2832     // Convert plugins in the internal(i.e. Document from) to collectionconfig.xml (i.e. Document to)
    2833     private void convertPlugin (Document from, Document to) {
    2834         Element import_element = to.createElement (StaticStrings.IMPORT_STR);
    2835         Element plugin_list_element = to.createElement (StaticStrings.PLUGINLIST_STR);
    2836        
    2837         NodeList children = from.getDocumentElement ().getElementsByTagName (StaticStrings.PLUGIN_ELEMENT);
    2838         int num_children = (children == null)? 0 : children.getLength ();
    2839         if (num_children == 0) {
    2840             return ;
    2841         }
    2842        
    2843         for (int i=0; i<num_children; i++) {
    2844            
    2845             Element child =  (Element)children.item (i);
    2846             if (child.getAttribute (StaticStrings.SEPARATOR_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    2847                 continue;
    2848             }
    2849             if (child.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    2850                 continue;
    2851             }
    2852            
    2853             String str = child.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
    2854             Element plugin_element = to.createElement (StaticStrings.PLUGIN_STR);
    2855             plugin_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, str);
    2856            
    2857             NodeList option_children = child.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
    2858             for (int j=0; j<option_children.getLength (); j++) {
    2859                 Element el = (Element)option_children.item (j);
    2860                 if(!el.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    2861                     continue;
    2862                 }
    2863                 String name_str = el.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2864                 String value_str = XMLTools.getNodeText (el);
    2865                
    2866                
    2867                 if (name_str == null && value_str == null) {
    2868                     continue;
    2869                 }
    2870                 Element option_element = to.createElement (StaticStrings.OPTION_STR);
    2871                 if (name_str != null && name_str.equals (StaticStrings.METADATA_STR)) {
    2872                    
    2873                     // 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.
    2874                     String[] values = value_str.split (StaticStrings.COMMA_CHARACTER);
    2875                     value_str = "";
    2876                     for (int k=0; k<=values.length-1; k++) {
    2877                         if(values[k].startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
    2878                             values[k] = values[k].substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
    2879                         }
    2880 
    2881                         if (k < values.length-1) {
    2882                             value_str = value_str + values[k] + StaticStrings.COMMA_CHARACTER;
    2883                         } else {
    2884                             value_str = value_str + values[k];
    2885                         }
    2886                     }
    2887                 }
    2888                
    2889                 if (!name_str.equals ("")) {
    2890                     if (!name_str.startsWith (StaticStrings.MINUS_CHARACTER)) {
    2891                         name_str = StaticStrings.MINUS_CHARACTER + name_str;
    2892                     }
    2893                     option_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    2894                 }
    2895                
    2896                 if (!value_str.equals ("")) {
    2897                     option_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, value_str);
    2898                 }
    2899                
    2900                 plugin_element.appendChild (option_element);
    2901             }//for loop ends
    2902            
    2903             plugin_list_element.appendChild (plugin_element);
    2904         }//for loop ends
    2905        
    2906         import_element.appendChild (plugin_list_element);
    2907        
    2908         //do the plugout element (used by building flax collections)
    2909         Node plugout = XMLTools.getChildByTagNameIndexed (from.getDocumentElement (), PLUGOUT_ELEMENT, 0);
    2910         if (plugout != null) {
    2911             Element to_element = XMLTools.duplicateElement (to, (Element)plugout, true);
    2912             import_element.appendChild (to_element);
    2913         }
    2914        
    2915         to.getDocumentElement ().appendChild (import_element);
    2916     }
    2917 
    2918     //Handle 'searchType' of collectionConfig.xml. In the internal structure, its also called 'searchType', eg. plain, form
    2919     private void convertSearchType (Document from, Document to) {
    2920         Element e = XMLTools.getNamedElement (from.getDocumentElement (), StaticStrings.FORMAT_STR,
    2921                 StaticStrings.NAME_ATTRIBUTE,  StaticStrings.SEARCHTYPE_ELEMENT);//searchType
    2922        
    2923         if (e == null) {
    2924             return;
    2925         }
    2926         Element search_type_element = to.createElement (StaticStrings.FORMAT_STR);
    2927        
    2928 //        String searchtype_str = e.getAttribute (StaticStrings.VALUE_ATTRIBUTE);       
    2929 //        search_type_element.setAttribute (StaticStrings.VALUE_ATTRIBUTE, searchtype_str);
    2930         String searchtype_str = XMLTools.getNodeText(e);       
    2931         XMLTools.setNodeText(search_type_element, searchtype_str);
    2932        
    2933         search_type_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.SEARCHTYPE_ELEMENT);
    2934         //Get the 'search' element from 'to'
    2935         Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
    2936         search.appendChild (search_type_element);
    2937     }
    2938    
    2939     private void convertBuildType (Document from, Document to) {
    2940         Element e = XMLTools.getNamedElement (from.getDocumentElement (),
    2941         StaticStrings.BUILDTYPE_ELEMENT,
    2942         StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
    2943         if (e == null) {
    2944             return;
    2945         }
    2946         String indexer = XMLTools.getNodeText (e);
    2947         Element search = to.createElement (StaticStrings.SEARCH_STR);
    2948         search.setAttribute (StaticStrings.TYPE_ATTRIBUTE, indexer);
    2949         to.getDocumentElement ().appendChild (search);
    2950     }
    2951     private void convertDefaultIndex (Document from, Document to, Element search) {
    2952         Element source = from.getDocumentElement ();
    2953        
    2954         Element default_index_element = (Element)XMLTools.getChildByTagName (source, StaticStrings.INDEX_DEFAULT_ELEMENT);
    2955         if (default_index_element == null) {
    2956             return;
    2957         }
    2958        
    2959         String indexer = search.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
    2960         String level_str = default_index_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE);
    2961         // Debugging purposes
    2962         if (level_str.equals ("") && indexer.equals (StaticStrings.MG_STR) ) {
    2963             System.out.println ("Bug: DefaultIndex should have its level attribute not empty.");
    2964         }
    2965        
    2966         NodeList content_elements = default_index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
    2967         int content_elements_length = content_elements.getLength ();
    2968        
    2969         // Don't output anything if no indexes are set
    2970         if(content_elements_length == 0) {
    2971             return ;//
    2972         }
    2973        
    2974         String index_str = "";
    2975        
    2976         if (indexer.equals (StaticStrings.MG_STR)) {
    2977             //combine level with indexes
    2978             index_str = level_str + StaticStrings.COLON_CHARACTER;
    2979         }
    2980         else { //for mgpp/lucene, just take index
    2981             //do nothing
    2982         }
    2983        
    2984         for(int k = 0; k < content_elements_length; k++) {
    2985             Element content_element = (Element) content_elements.item (k);
    2986             if (content_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    2987                 continue;
    2988             }
    2989             String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    2990            
    2991             if(name_str.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
    2992                 name_str = name_str.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
    2993             }
    2994 
    2995             index_str = index_str + name_str;
    2996            
    2997             // Make it comma separated string
    2998             if(k < content_elements_length - 1) {
    2999                 index_str = index_str + StaticStrings.COMMA_CHARACTER;
    3000             }
    3001             content_element = null;
    3002         }//for loop ends
    3003        
    3004        
    3005         Element default_index = to.createElement (StaticStrings.INDEX_DEFAULT_ELEMENT_LOWERCASE);
    3006         default_index.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_str);
    3007         search.appendChild (default_index);
    3008        
    3009     }
    3010     private void convertSubcollection (Document from, Document to) {
    3011         Element source = from.getDocumentElement ();
    3012         //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
    3013         Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
    3014        
    3015         // Get the Subcollection element from the internal structure
    3016         NodeList subcollection_elements = source.getElementsByTagName (StaticStrings.SUBCOLLECTION_ELEMENT);
    3017         if (subcollection_elements == null) {
    3018             return;
    3019         }
    3020         int subcollection_elements_length = subcollection_elements.getLength ();
    3021        
    3022         if (subcollection_elements_length == 0) { // no
    3023             return ;
    3024         }
    3025        
    3026         for(int j = 0; j < subcollection_elements_length; j++) {
    3027            
    3028             Element e = (Element) subcollection_elements.item (j);
    3029             if (e.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    3030                 continue;
    3031             }
    3032             String content = e.getAttribute (StaticStrings.CONTENT_ATTRIBUTE);
    3033             String name = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    3034             String options = e.getAttribute (StaticStrings.OPTIONS_ATTRIBUTE);
    3035             String type = e.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
    3036             String text = XMLTools.getNodeText (e);
    3037            
    3038             String filter = "";
    3039             if (type.equals (StaticStrings.EXCLUDE_STR)) {
    3040                 filter = StaticStrings.EXCLAMATION_CHARACTER;
    3041             }
    3042            
    3043             if(content.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
    3044                 content = content.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
    3045             }
    3046             filter = filter + content + StaticStrings.SEPARATOR_CHARACTER + text;
    3047             if (options != null && options != "") {
    3048                 filter = filter + StaticStrings.SEPARATOR_CHARACTER + options;
    3049             }
    3050             Element subcollection = to.createElement (StaticStrings.SUBCOLLECTION_STR);
    3051             subcollection.setAttribute (StaticStrings.FILTER_ATTRIBUTE, filter);
    3052             subcollection.setAttribute (StaticStrings.NAME_ATTRIBUTE, name);
    3053            
    3054             search.appendChild (subcollection);
    3055         }
    3056     }
    3057     private void convertSubcollectionIndexes (Document from, Document to) {
    3058         Element source = from.getDocumentElement ();
    3059         //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
    3060         Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
    3061        
    3062         // Get the SubcollectionIndexes element from the internal structure
    3063         Element subcollection_indexes = (Element)XMLTools.getChildByTagName (source, StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT);
    3064         if (subcollection_indexes == null) {
    3065             return;
    3066         }
    3067         NodeList index_elements = subcollection_indexes.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
    3068         int index_elements_length = index_elements.getLength ();
    3069        
    3070         if (index_elements_length == 0) { // no indexes
    3071             return ;
    3072         }
    3073        
    3074         for(int j = 0; j < index_elements_length; j++) {
    3075             Element index_element = (Element) index_elements.item (j);
    3076             if (index_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    3077                 continue;
    3078             }
    3079            
    3080             Element index = to.createElement (StaticStrings.SUBCOLLECTION_INDEX_ELEMENT);
    3081            
    3082             String index_value = "";
    3083            
    3084             NodeList content_elements = index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
    3085             int content_elements_length = content_elements.getLength ();
    3086            
    3087             for(int k = 0; k < content_elements_length; k++) {
    3088                 Element content_element = (Element) content_elements.item (k);
    3089                 if (content_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    3090                     continue;
    3091                 }
    3092                 String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    3093                 index_value += name_str;
    3094                 // Make it comma separated string
    3095                 if(k < content_elements_length - 1) {
    3096                     index_value += StaticStrings.COMMA_CHARACTER;
    3097                 }
    3098                 content_element = null;
    3099             }//for loop ends
    3100            
    3101             index.setAttribute (StaticStrings.NAME_ATTRIBUTE, index_value);
    3102            
    3103             // Now constructing 'displayItem' element for this 'indexSubcollection' element
    3104             // from the collectionmetadata element
    3105             ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
    3106             StaticStrings.COLLECTIONMETADATA_ELEMENT,
    3107             StaticStrings.NAME_ATTRIBUTE, index_value);
    3108            
    3109             if (collectionmetadata_list != null) {
    3110                
    3111                 for(int k = 0; k < collectionmetadata_list.size (); k++) {
    3112                     Element collectionmetadata = (Element)collectionmetadata_list.get (k);
    3113                     if (collectionmetadata.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    3114                         continue;
    3115                     }
    3116                     Element displayItem = constructDisplayItem (collectionmetadata, to);
    3117                     index.appendChild (displayItem);
    3118                 }
    3119             }
    3120            
    3121             search.appendChild (index);
    3122            
    3123         } //for loop ends
    3124     }
    3125    
    3126     private void convertLanguages (Document from, Document to) {
    3127         Element source = from.getDocumentElement ();
    3128         //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
    3129         Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
    3130        
    3131         // Get the Languages element from the internal structure
    3132         Element languages = (Element)XMLTools.getChildByTagName (source, StaticStrings.LANGUAGES_ELEMENT);
    3133         if (languages == null) {
    3134             return;
    3135         }
    3136         NodeList language_elements = languages.getElementsByTagName (StaticStrings.LANGUAGE_ELEMENT);
    3137         int language_elements_length = language_elements.getLength ();
    3138        
    3139         if (language_elements_length == 0) {
    3140             return ;
    3141         }
    3142        
    3143         for(int j = 0; j < language_elements_length; j++) {
    3144             Element element = (Element) language_elements.item (j);
    3145             if (element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    3146                 continue;
    3147             }
    3148            
    3149             // Create indexLanguage element
    3150             Element index_language = to.createElement (StaticStrings.LANGUAGE_INDEX_ELEMENT);
    3151            
    3152             String name_str = element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    3153             index_language.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    3154            
    3155             // Now constructing 'displayItem' element for this 'indexLanguage' element
    3156             // from the collectionmetadata element
    3157             ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
    3158             StaticStrings.COLLECTIONMETADATA_ELEMENT,
    3159             StaticStrings.NAME_ATTRIBUTE, name_str);
    3160            
    3161             if (collectionmetadata_list != null) {
    3162                
    3163                 for(int k = 0; k < collectionmetadata_list.size (); k++) {
    3164                     Element collectionmetadata = (Element)collectionmetadata_list.get (k);
    3165                     if (collectionmetadata.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    3166                         continue;
    3167                     }
    3168                     Element displayItem = constructDisplayItem (collectionmetadata, to);
    3169                     index_language.appendChild (displayItem);
    3170                 }
    3171             }
    3172            
    3173             search.appendChild (index_language);
    3174            
    3175         } //for loop ends
    3176        
    3177         // Convert DefaultLanguage
    3178         // Get the DefaultLanguage element from the internal structure
    3179         Element default_language = (Element)XMLTools.getChildByTagName (source, StaticStrings.LANGUAGE_DEFAULT_ELEMENT);
    3180         if(default_language != null) {
    3181             String lang_name = default_language.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    3182             Element default_index_language = to.createElement (StaticStrings.LANGUAGE_DEFAULT_INDEX_ELEMENT);
    3183             default_index_language.setAttribute (StaticStrings.NAME_ATTRIBUTE, lang_name);
    3184             search.appendChild (default_index_language);
    3185         }
    3186         // Convert LanguageMetadata
    3187         // Get the LanguageMetadata element from the internal structure
    3188         Element language_metadata = (Element)XMLTools.getChildByTagName (source, StaticStrings.LANGUAGE_METADATA_ELEMENT);
    3189         if(language_metadata != null) {
    3190             String meta_name = language_metadata.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    3191             Element language_meta = to.createElement (StaticStrings.LANGUAGE_METADATA_ELEMENT_STR);
    3192             if(meta_name.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
    3193                 meta_name = meta_name.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
    3194             }
    3195             language_meta.setAttribute (StaticStrings.NAME_ATTRIBUTE, meta_name);
    3196             search.appendChild (language_meta);
    3197         }
    3198     }
    3199    
    3200     //convert indexes and their displayItems, which go in 'search' element in collectionConfig.xml
    3201     //parameter 'to' is the document to be saved as collectionConfig.xml
    3202     //parameter 'from' is the internal xml structure
    3203     private void convertIndex (Document from, Document to) {
    3204         Element source = from.getDocumentElement ();
    3205         //Get the 'search' element from 'to' which has already been created in 'convertBuildType'
    3206         Element search = (Element)XMLTools.getChildByTagName (to.getDocumentElement (), StaticStrings.SEARCH_STR);
    3207        
    3208         //THere are two sets of indexes elements, find the one which is assigned 'true'
    3209         Element indexes = XMLTools.getNamedElement (source,
    3210         StaticStrings.INDEXES_ELEMENT,
    3211         StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
    3212         if (indexes == null) {
    3213             return;
    3214         }
    3215         NodeList index_elements = indexes.getElementsByTagName (StaticStrings.INDEX_ELEMENT);
    3216         int index_elements_length = index_elements.getLength ();
    3217        
    3218         if (index_elements_length == 0) { // no indexes
    3219             return ;
    3220         }
    3221        
    3222         //find out it's mg or mgpp/lucene
    3223         String mg = search.getAttribute (StaticStrings.TYPE_ATTRIBUTE);
    3224         boolean mg_indexer = false;
    3225         if (mg.equals (StaticStrings.MG_STR)) {
    3226             mg_indexer = true;//it's mg, then the level is set as attribute of
    3227         }
    3228         if (mg_indexer == false) {
    3229             // It's mgpp. Construct 'level' and 'defaultLevel' elements separately.
    3230             convertLevels (from, to, search);
    3231         }
    3232        
    3233         for(int j = 0; j < index_elements_length; j++) {
    3234             Element index_element = (Element) index_elements.item (j);
    3235             if (index_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    3236                 continue;
    3237             }
    3238            
    3239             Element index_ele = to.createElement (StaticStrings.INDEX_LOW_STR);//index
    3240            
    3241             // Used for creating displayItem for this element 'index_ele' further below
    3242             // full_index_names contain 'ex.'
    3243             String full_index_name = "";
    3244             String level_str = "";
    3245            
    3246             StringBuffer index_value = new StringBuffer ();
    3247             if (mg_indexer == true) {
    3248                 // For mg indexer, there is a 'level' attribute in the index element of the internal structure
    3249                 // But mgpp/lucene don't
    3250                 level_str = index_element.getAttribute (StaticStrings.LEVEL_ATTRIBUTE);
    3251                 if(level_str.length () > 0) {
    3252                     index_value.append (level_str).append (StaticStrings.COLON_CHARACTER);
    3253                     //index_value = index_value.StaticStrings.COLON_CHARACTER;
    3254                 }
    3255             }
    3256            
    3257             NodeList content_elements = index_element.getElementsByTagName (StaticStrings.CONTENT_ELEMENT);
    3258             int content_elements_length = content_elements.getLength ();
    3259            
    3260             for(int k = 0; k < content_elements_length; k++) {
    3261                 Element content_element = (Element) content_elements.item (k);
    3262                 if (content_element.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    3263                     continue;
    3264                 }
    3265                 String name_str = content_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    3266                
    3267                 full_index_name = full_index_name + name_str;
    3268                 if (k < content_elements_length - 1) {
    3269                     full_index_name = full_index_name + StaticStrings.COMMA_CHARACTER;
    3270                 }
    3271                
    3272                 if(name_str.startsWith (StaticStrings.EXTRACTED_NAMESPACE)) {
    3273                     name_str = name_str.substring (StaticStrings.EXTRACTED_NAMESPACE.length ());
    3274                 }
    3275 
    3276                 index_value.append (name_str);
    3277                 name_str = null;
    3278                 // Make it comma separated string
    3279                 if(k < content_elements_length - 1) {
    3280                     index_value.append (StaticStrings.COMMA_CHARACTER);
    3281                 }
    3282                 content_element = null;
    3283             }//for loop ends
    3284            
    3285             String temp_str = index_value.toString ();
    3286             index_ele.setAttribute (StaticStrings.NAME_ATTRIBUTE, temp_str);
    3287            
    3288             // Now constructing 'displayItem' element for this 'index_ele' element
    3289             // The index names in the collectionmetadata elements in the internal structure are not the names that
    3290             // are used in the content elements (i.e. ex.Source or dc.Subject and keywords), but the names that are
    3291             // in the configuration files (i.e. Source or dc.Subject)
    3292             ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
    3293             StaticStrings.COLLECTIONMETADATA_ELEMENT,
    3294             StaticStrings.NAME_ATTRIBUTE, temp_str);
    3295            
    3296         if (collectionmetadata_list == null) {
    3297           //try the full name, i.e. with 'ex.'
    3298           if (mg_indexer == true) {
    3299         // but first append level info if we are mg
    3300         full_index_name = level_str+StaticStrings.COLON_CHARACTER+full_index_name;
    3301           }
    3302           collectionmetadata_list = XMLTools.getNamedElementList (source,
    3303                  StaticStrings.COLLECTIONMETADATA_ELEMENT,
    3304                  StaticStrings.NAME_ATTRIBUTE, full_index_name);
    3305         }
    3306    
    3307             if (collectionmetadata_list != null) {
    3308                
    3309                 for(int k = 0; k < collectionmetadata_list.size (); k++) {
    3310                     Element collectionmetadata = (Element)collectionmetadata_list.get (k);
    3311                     if (collectionmetadata.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    3312                         continue;
    3313                     }
    3314                     Element displayItem = constructDisplayItem (collectionmetadata, to);
    3315                    
    3316                     index_ele.appendChild (displayItem);
    3317                 }
    3318             }
    3319            
    3320             search.appendChild (index_ele);
    3321            
    3322         } //for loop ends
    3323        
    3324         //Convert default index
    3325         convertDefaultIndex (from, to, search);
    3326         convertIndexOptions(from, to, search);
    3327     }
    3328     // Convert levels for mgpp/lucene. This method is called by converIndex() when mgpp indexer is detected.
    3329     private void convertLevels (Document from, Document to, Element search) {
    3330         Element source = from.getDocumentElement ();
    3331         Element index_option = XMLTools.getNamedElement (source,
    3332         StaticStrings.INDEXOPTIONS_ELEMENT,
    3333         StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVELS_STR);
    3334         if (index_option == null) {
    3335             return;
    3336         }
    3337         //Debugging purposes
    3338         if (index_option.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    3339             DebugStream.println ("For mgpp, there should be an IndexOption element for levels which is assigned 'true': possible bug.");
    3340         }
    3341        
    3342         NodeList option_elements = index_option.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
    3343         int num_elements = option_elements.getLength ();
    3344        
    3345         // Don't output anything if no indexes are set
    3346         if(num_elements == 0) {
    3347             return ;//
    3348         }
    3349        
    3350         for(int k = 0; k < num_elements; k++) {
    3351             Element e = (Element) option_elements.item (k);
    3352             String name_str = e.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    3353             Element level_element = to.createElement (StaticStrings.LEVEL_ELEMENT);
    3354             level_element.setAttribute (StaticStrings.NAME_ATTRIBUTE, name_str);
    3355            
    3356             //Now construct displayItem for this level element from collectionmetadata
    3357             ArrayList collectionmetadata_list = XMLTools.getNamedElementList (source,
    3358             StaticStrings.COLLECTIONMETADATA_ELEMENT,
    3359             StaticStrings.NAME_ATTRIBUTE, name_str);
    3360            
    3361             if (collectionmetadata_list != null) {
    3362                
    3363                 for(int j = 0; j < collectionmetadata_list.size (); j++) {
    3364                     Element collectionmetadata = (Element)collectionmetadata_list.get (j);
    3365                    
    3366                     Element displayItem = constructDisplayItem (collectionmetadata, to);
    3367                     level_element.appendChild (displayItem);
    3368                 }
    3369             }
    3370             search.appendChild (level_element);
    3371         }
    3372        
    3373         //Convert default level
    3374         Element default_index_option = XMLTools.getNamedElement (source,
    3375         StaticStrings.INDEXOPTION_DEFAULT_ELEMENT,
    3376         StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVEL_DEFAULT_STR);
    3377         if (default_index_option == null) {
    3378             return;
    3379         }
    3380         Element default_level = to.createElement (StaticStrings.LEVEL_DEFAULT_ELEMENT);
    3381         String default_level_str = default_index_option.getAttribute (StaticStrings.VALUE_ATTRIBUTE);
    3382         default_level.setAttribute (StaticStrings.NAME_ATTRIBUTE, default_level_str);
    3383         search.appendChild (default_level);
    3384        
    3385     }
    3386     // Convert indexoptions for mg/mgpp/lucene. This method is called by convertIndex().
    3387     private void convertIndexOptions (Document from, Document to, Element search) {
    3388         Element source = from.getDocumentElement ();
    3389         Element index_option = XMLTools.getNamedElement (source,
    3390         StaticStrings.INDEXOPTIONS_ELEMENT,
    3391         StaticStrings.NAME_ATTRIBUTE, StaticStrings.INDEXOPTIONS_STR);
    3392         if (index_option == null) {
    3393             return;
    3394         }
    3395         //Debugging purposes
    3396         if (index_option.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.FALSE_STR)) {
    3397             DebugStream.println ("There should be an IndexOption element which is assigned 'true': possible bug.");
    3398         }
    3399         Element indexOptionEl = to.createElement(StaticStrings.INDEXOPTION_STR);
    3400         NodeList option_elements = index_option.getElementsByTagName (StaticStrings.OPTION_ELEMENT);
    3401         int num_elements = option_elements.getLength ();       
    3402         // Don't output anything if no index
    3403         if(num_elements == 0) {
    3404             return ;//
    3405         }
    3406         search.appendChild (indexOptionEl);
    3407        
    3408         for(int k = 0; k < num_elements; k++) {
    3409             Element e = (Element) option_elements.item (k);
    3410             String name_att = e.getAttribute(StaticStrings.NAME_ATTRIBUTE);
    3411             Element optionEl = to.createElement(StaticStrings.OPTION_STR);
    3412             optionEl.setAttribute(StaticStrings.NAME_ATTRIBUTE, name_att);
    3413             indexOptionEl.appendChild(optionEl);
    3414         }
    3415            
    3416     }
    3417     // Append the element son to the element mother in the appropriate position.
    3418     static public void appendProperly (Element mother, Element son) {
    3419         if (son == null)
    3420             return;
    3421        
    3422         Node reference_node = findInsertionPoint (mother, son);
    3423         if(reference_node != null) {
    3424             mother.insertBefore (son, reference_node);
    3425         }
    3426         else {
    3427             mother.appendChild (son);
    3428         }
    3429     }
    3430     /** 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.
    3431      * @param target_element the command Element to be inserted
    3432      * @return the Element which the given command should be inserted before, or null to append to end of list
    3433      */
    3434     static public Node findInsertionPoint (Element document_element, Element target_element) {
    3435         ///ystem.err.println("Find insertion point: " + target_element.getNodeName());
    3436         String target_element_name = target_element.getNodeName ();
    3437        
    3438         // Try to find commands with the same tag.
    3439         NodeList matching_elements = document_element.getElementsByTagName (target_element_name);
    3440         // If we found matching elements, then we have our most likely insertion location, so check within for groupings
    3441         if(matching_elements.getLength () != 0) {
    3442             ///ystem.err.println("Found matching elements.");
    3443             // Only CollectionMeta are grouped.
    3444             if(target_element_name.equals (StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
    3445                 ///ystem.err.println("Dealing with collection metadata");
    3446                 // 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.
    3447                 // So if the command to be added is special add it immediately after any other special command
    3448                 if(target_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    3449                     int index = 0;
    3450                     Element matched_element = (Element) matching_elements.item (index);
    3451                     Element sibling_element = (Element) matched_element.getNextSibling ();
    3452                     while(sibling_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    3453                         index++;
    3454                         matched_element = (Element) matching_elements.item (index);
    3455                         sibling_element = (Element) matched_element.getNextSibling ();
    3456                     }
    3457                     if(sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
    3458                         Element newline_element = document.createElement (NEWLINE_ELEMENT);
    3459                         document_element.insertBefore (newline_element, sibling_element);
    3460                     }
    3461                     return sibling_element;
    3462                 }
    3463                 // Otherwise try to find a matching 'name' and add after the last one in that group.
    3464                 else {
    3465                     int index = 0;
    3466                     target_element_name = target_element.getAttribute (StaticStrings.NAME_ATTRIBUTE);
    3467                     boolean found = false;
    3468                     // Skip all of the special metadata
    3469                     Element matched_element = (Element) matching_elements.item (index);
    3470                     while(matched_element.getAttribute (StaticStrings.SPECIAL_ATTRIBUTE).equals (StaticStrings.TRUE_STR)) {
    3471                         index++;
    3472                         matched_element = (Element) matching_elements.item (index);
    3473                     }
    3474                     // Begin search
    3475                     while(!found && matched_element != null) {
    3476                         if(matched_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
    3477                             found = true;
    3478                         }
    3479                         else {
    3480                             index++;
    3481                             matched_element = (Element) matching_elements.item (index);
    3482                         }
    3483                     }
    3484                     // If we found a match, we need to continue checking until we find the last name match.
    3485                     if(found) {
    3486                         index++;
    3487                         Element previous_sibling = matched_element;
    3488                         Element sibling_element = (Element) matching_elements.item (index);
    3489                         while(sibling_element != null && sibling_element.getAttribute (StaticStrings.NAME_ATTRIBUTE).equals (target_element_name)) {
    3490                             previous_sibling = sibling_element;
    3491                             index++;
    3492                             sibling_element = (Element) matching_elements.item (index);
    3493                         }
    3494                         // 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!
    3495                         return previous_sibling.getNextSibling ();
    3496                     }
    3497                     // If not found we just add after last metadata element
    3498                     else {
    3499                         Element last_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
    3500                         return last_element.getNextSibling ();
    3501                     }
    3502                 }
    3503                
    3504             }
    3505             else {
    3506                 ///ystem.err.println("Not dealing with collection meta.");
    3507                 Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
    3508                 // 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)
    3509                 Node sibling_element = matched_element.getNextSibling ();
    3510                 if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
    3511                     Element newline_element = document.createElement (NEWLINE_ELEMENT);
    3512                     document_element.insertBefore (newline_element, sibling_element);
    3513                 }
    3514                 return sibling_element; // Note that this may be null
    3515             }
    3516         }
    3517         ///ystem.err.println("No matching elements found.");
    3518         // Locate where this command is in the ordering
    3519         int command_index = -1;
    3520         for(int i = 0; command_index == -1 && i < COMMAND_ORDER.length; i++) {
    3521             if(COMMAND_ORDER[i].equals (target_element_name)) {
    3522                 command_index = i;
    3523             }
    3524         }
    3525         ///ystem.err.println("Command index is: " + command_index);
    3526         // Now move forward, checking for existing elements in each of the preceeding command orders.
    3527         int preceeding_index = command_index - 1;
    3528         ///ystem.err.println("Searching before the target command.");
    3529         while(preceeding_index >= 0) {
    3530             matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[preceeding_index]);
    3531             // If we've found a match
    3532             if(matching_elements.getLength () > 0) {
    3533                 // We add after the last element
    3534                 Element matched_element = (Element) matching_elements.item (matching_elements.getLength () - 1);
    3535                 // 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)
    3536                 Node sibling_element = matched_element.getNextSibling ();
    3537                 if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
    3538                     Element newline_element = document.createElement (NEWLINE_ELEMENT);
    3539                     document_element.insertBefore (newline_element, sibling_element);
    3540                 }
    3541                 return sibling_element; // Note that this may be null
    3542             }
    3543             preceeding_index--;
    3544         }
    3545         // If all that fails, we now move backwards through the commands
    3546         int susceeding_index = command_index + 1;
    3547         ///ystem.err.println("Searching after the target command.");
    3548         while(susceeding_index < COMMAND_ORDER.length) {
    3549             matching_elements = document_element.getElementsByTagName (COMMAND_ORDER[susceeding_index]);
    3550             // If we've found a match
    3551             if(matching_elements.getLength () > 0) {
    3552                 // We add before the first element
    3553                 Element matched_element = (Element) matching_elements.item (0);
    3554                 // 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)
    3555                 Node sibling_element = matched_element.getPreviousSibling ();
    3556                 if(sibling_element != null && sibling_element.getNodeName ().equals (NEWLINE_ELEMENT)) {
    3557                     Element newline_element = document.createElement (NEWLINE_ELEMENT);
    3558                     document_element.insertBefore (newline_element, sibling_element);
    3559                 }
    3560                 return sibling_element; // Note that this may be null
    3561             }
    3562             susceeding_index++;
    3563         }
    3564         // Well. Apparently there are no other commands in this collection configuration. So append away...
    3565         return null;
    3566     }
    3567     // From collectionConfig.xml to internal structure:add 'ex.' namespace (if none).
    3568     // From internal structure to collectionConfig.xml:always peel off 'ex.' namespace (if any), except for format statement
    3569     //This method parses 'xml_file_doc' into 'dOc'
    3570     public void parseCollectionConfigXML (File xml_file, Document dOc) {
    3571        
    3572         Document xml_file_doc = XMLTools.parseXMLFile (xml_file);
    3573         Element fromElement = xml_file_doc.getDocumentElement ();
    3574         Element toElement = dOc.getDocumentElement ();
    3575        
    3576         // It's deliberately set that 'creator', 'maintainer', and 'public' are only in English (as they are just names).
    3577         // So the following ArrayList have only one element.
    3578         Node metadataListNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.METADATALIST_STR, 0);
    3579         if (metadataListNode != null) {
    3580             ArrayList creator = doMetadataList (dOc, metadataListNode, StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT,
    3581             StaticStrings.COLLECTIONMETADATA_CREATOR_STR);
    3582             ArrayList maintainer = doMetadataList (dOc, metadataListNode,
    3583             StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT,
    3584             StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR);
    3585             ArrayList is_public = doMetadataList (dOc, metadataListNode, StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT,
    3586             StaticStrings.COLLECTIONMETADATA_PUBLIC_STR);
    3587            
    3588             appendArrayList (toElement, creator);
    3589             appendArrayList (toElement, maintainer);
    3590             appendArrayList (toElement, is_public);
    3591         }
    3592        
    3593         Node searchNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.SEARCH_STR, 0);
    3594         String buildtype_value = ((Element)searchNode).getAttribute (StaticStrings.TYPE_ATTRIBUTE);//might be mg|mgpp|lucene
    3595         Element buildtype = doBuildType (dOc, buildtype_value);
    3596         appendProperly (toElement, buildtype);
    3597        
    3598        
    3599         Node importNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.IMPORT_STR, 0);
    3600         if (importNode == null) {
    3601             System.out.println ("There is no content in the 'import' block.");
    3602         }
    3603         if (importNode != null) {
    3604             //do plugin list nodes
    3605             Node pluginListNode = XMLTools.getChildByTagNameIndexed ((Element)importNode, StaticStrings.PLUGINLIST_STR, 0);           
    3606             if (pluginListNode == null) {
    3607                 System.out.println ("There is no pluginlist set.");
    3608             }
    3609             if (pluginListNode != null) {
    3610                
    3611                 doPlugin (dOc, pluginListNode);
    3612             }
    3613            
    3614             //do the plugout element (used by building flax collections)
    3615             Node plugout = XMLTools.getChildByTagNameIndexed ((Element)importNode, PLUGOUT_ELEMENT, 0);
    3616             if (plugout != null) {
    3617                 Element to_element = XMLTools.duplicateElement (dOc, (Element)plugout, true);
    3618                 toElement.appendChild (to_element);
    3619             }
    3620         }
    3621        
    3622         Node browseNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.BROWSE_STR, 0);
    3623         if (browseNode != null) {
    3624             if (browseNode == null) {
    3625                 System.out.println ("There is no classifier.");
    3626             }
    3627             doClassifier (dOc, browseNode);
    3628         }
    3629        
    3630         Node displayItemListNode = XMLTools.getChildByTagNameIndexed (fromElement, StaticStrings.DISPLAYITEMLIST_STR, 0);
    3631         if (displayItemListNode != null) {
    3632             ArrayList description = doDisplayItemList (dOc, displayItemListNode, StaticStrings.DESCRIPTION_STR,
    3633             StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR);
    3634             ArrayList smallicon = doDisplayItemList (dOc, displayItemListNode, StaticStrings.SMALLICON_STR,
    3635             StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR);
    3636             ArrayList icon = doDisplayItemList (dOc, displayItemListNode, StaticStrings.ICON_STR,
    3637             StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR);
    3638             ArrayList name = doDisplayItemList (dOc, displayItemListNode, StaticStrings.NAME_STR,
    3639             StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR);
    3640            
    3641             appendArrayList (toElement, description);
    3642             appendArrayList (toElement, smallicon);
    3643             appendArrayList (toElement, icon);
    3644             appendArrayList (toElement, name);
    3645         }
    3646        
    3647         if (buildtype_value.equalsIgnoreCase ("mg")) {
    3648             doMGIndexes (dOc, searchNode);
    3649         }
    3650         else {
    3651             doMGPPIndexes (dOc, searchNode);
    3652         }
    3653        
    3654         doDefaultIndex (dOc, searchNode);
    3655         //doSearchType (dOc, searchNode);
    3656         doDefaultLevel (dOc, searchNode);
    3657         doLevel (dOc, searchNode);
    3658         doIndexOption (dOc, searchNode);
    3659         doSubcollection (dOc, searchNode);
    3660         doIndexSubcollection (dOc, searchNode);
    3661         doIndexLanguage (dOc, searchNode);
    3662         doDefaultIndexLanguage (dOc, searchNode);
    3663         doLanguageMetadata (dOc, searchNode);
    3664         doSearchFormat (dOc, searchNode);
    3665         doDisplayFormat (dOc, fromElement);
    3666         doReplaceListRef (dOc, fromElement);
    3667         doOAIElement (dOc, fromElement);
    3668        
    3669     }
    3670    
    3671    
    3672     public void saveCollectionConfigXML (File collect_cfg_file, Document doc) {
    3673         //In this method, the file collect_cfg_file must be 'collectionConfig.xml'
    3674        
    3675        
    3676         //Compare the internal structure (doc) with the saved structure from collectionConfig.xml and see if it has changed
    3677         StringBuffer collect_cfg_string_buffer = new StringBuffer (XMLTools.xmlNodeToString (doc));
    3678         String collect_cfg_string = collect_cfg_string_buffer.toString ();
    3679         if (saved_collect_cfg_string_buffer != null) {
    3680             String saved_collect_cfg_string = saved_collect_cfg_string_buffer.toString ();
    3681             if (collect_cfg_string.equals (saved_collect_cfg_string)) {
    3682                 DebugStream.println ("'collectionConfig.xml' file hasn't changed so no save necessary...");
    3683                 return;
    3684             }
    3685         }
    3686        
    3687         DebugStream.println ("'collectionConfig.xml' file has changed, saving now...");
    3688        
    3689         // If we're using the Local Library we must release the collection before writing to the collect.cfg file
    3690         String collection_name = Gatherer.c_man.getCollection ().getName ();
    3691         boolean collection_released = false;
    3692         if (Gatherer.c_man.built () && LocalLibraryServer.isRunning () == true) {
    3693             // Release the collection
    3694             LocalLibraryServer.releaseCollection (collection_name);
    3695             collection_released = true;
    3696         }
    3697        
    3698         // Make a backup of the collectionConfig.xml file so that the user can manully change back
    3699         if (collect_cfg_file.exists ()) {
    3700            
    3701             File original_file = new File (collect_cfg_file.getParentFile (), Utility.COLLECTION_CONFIG_XML);
    3702             File backup_file = new File (collect_cfg_file.getParentFile (), Utility.COLLECTION_CONFIG_BAK);
    3703             if (backup_file.exists ()) {
    3704                 backup_file.delete ();
    3705             }
    3706             if (!original_file.renameTo (backup_file)) {
    3707                 System.err.println ("Warning: can't rename collectionConfig.xml to collectionConfig.bak.");
    3708             }
    3709         }
    3710        
    3711         Document collection_config_xml_document = convertInternalToCollectionConfig (doc);
    3712         String[] nonEscapingTagNames = {StaticStrings.FORMAT_STR};
    3713         XMLTools.writeXMLFile (collect_cfg_file, collection_config_xml_document, nonEscapingTagNames);
    3714         saved_collect_cfg_string_buffer = collect_cfg_string_buffer;
    3715        
    3716         // If we're using a remote Greenstone server, upload the new 'collectionConfig.xml' file
    3717         if (Gatherer.isGsdlRemote) {
    3718             Gatherer.remoteGreenstoneServer.uploadCollectionFile (collection_name, collect_cfg_file);
    3719         }
    3720        
    3721         // Now re-add the collection to the Local Library server
    3722         if (collection_released) {
    3723             LocalLibraryServer.addCollection (collection_name);
    3724         }
    3725        
    3726     }
    3727     public void saveIfNecessary () {
    3728         if (Gatherer.GS3 == true) {
    3729             saveCollectionConfigXML (collect_cfg_file, document);
    3730             return;
    3731         }
    3732         // Convert the collection configuration XML tree to the collect.cfg version
    3733         StringBuffer collect_cfg_string_buffer = new StringBuffer ();
    3734         NodeList command_elements = document.getDocumentElement ().getChildNodes ();
    3735         boolean just_wrote_blank_line = false;  // Prevent two or more blank lines in a row
    3736         for (int i = 0; i < command_elements.getLength (); i++) {
    3737             Node command_node = command_elements.item (i);
    3738             if (!(command_node instanceof Element)) {
    3739                 // We're only interested in Elements
    3740                 continue;
    3741             }
    3742             Element command_element = (Element) command_node;
    3743            
    3744             // Handle NewLine elements (blank lines)
    3745             if (command_element.getNodeName ().equals (NEWLINE_ELEMENT) && !just_wrote_blank_line) {
    3746                 collect_cfg_string_buffer.append ("\n");
    3747                 just_wrote_blank_line = true;
    3748             }
    3749            
    3750             // Anything else we write to file, but only if it has been assigned, except for index and level commands
    3751             // (which just get commented out if unassigned -- a side effect of MG & MGPP compatibility)
    3752             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)) {
    3753           String command = toString(command_element);
    3754 //                 if (command_element.getNodeName ().equals (StaticStrings.FORMAT_ELEMENT)) {
    3755 //                     // Format statements we write out with ex. still present
    3756 //        command = toString (command_element); //, true);
    3757 //                 }
    3758 //                 else {
    3759 //        command = toString (command_element);//, false);
    3760 //                 }
    3761                
    3762                 if (command != null && command.length ()> 0 ) {
    3763                     collect_cfg_string_buffer.append (command + "\n");
    3764                     just_wrote_blank_line = false;
    3765                 }
    3766             }
    3767         }
    3768        
    3769         String collect_cfg_string = collect_cfg_string_buffer.toString ();
    3770         String saved_collect_cfg_string = saved_collect_cfg_string_buffer.toString ();
    3771         if (collect_cfg_string.equals (saved_collect_cfg_string)) {
    3772             DebugStream.println ("Collect.cfg file hasn't changed so no save necessary...");
    3773             return;
    3774         }
    3775        
    3776         DebugStream.println ("Collect.cfg file has changed, saving now...");
    3777        
    3778         // If we're using the Local Library we must release the collection before writing to the collect.cfg file
    3779         String collection_name = CollectionManager.getLoadedCollectionName ();
    3780         boolean collection_released = false;
    3781         if (Gatherer.c_man.built () && LocalLibraryServer.isRunning () == true) {
    3782             // Release the collection
    3783             LocalLibraryServer.releaseCollection (collection_name);
    3784             collection_released = true;
    3785         }
    3786        
    3787         // Make a backup of the collect.cfg file
    3788         if (collect_cfg_file.exists ()) {
    3789             File original_file = new File (collect_cfg_file.getParentFile (), StaticStrings.COLLECT_CFG);
    3790             File backup_file = new File (collect_cfg_file.getParentFile (), Utility.COLLECT_BAK);
    3791             if (backup_file.exists ()) {
    3792                 backup_file.delete ();
    3793             }
    3794             if (!original_file.renameTo (backup_file)) {
    3795                 System.err.println ("Warning: can't rename collect.cfg to collect.bak.");
    3796             }
    3797         }
    3798        
    3799         try {
    3800             OutputStream ostream = new FileOutputStream (collect_cfg_file);
    3801             Writer file_writer = new OutputStreamWriter (ostream, ENCODING);
    3802             BufferedWriter buffered_writer = new BufferedWriter (file_writer);
    3803             buffered_writer.write (collect_cfg_string);
    3804             buffered_writer.close ();
    3805            
    3806             saved_collect_cfg_string_buffer = collect_cfg_string_buffer;
    3807            
    3808             // If we're using a remote Greenstone server, upload the new collect.cfg file
    3809             if (Gatherer.isGsdlRemote) {
    3810                 Gatherer.remoteGreenstoneServer.uploadCollectionFile (collection_name, collect_cfg_file);
    3811             }
    3812         }
    3813         catch (Exception exception) {
    3814             DebugStream.println ("Error in CollectionConfiguration.save(): " + exception);
    3815             DebugStream.printStackTrace (exception);
    3816         }
    3817        
    3818         // Now re-add the collection to the Local Library server
    3819         if (collection_released) {
    3820             LocalLibraryServer.addCollection (collection_name);
    3821         }
    3822     }
    3823     // This method is initilised in CollectionDesignManager.java constructor
    3824     public CollectionConfiguration (File collect_cfg_file) {
    3825         this.collect_cfg_file = collect_cfg_file;
    3826        
    3827         // parse the XML template
    3828         document = XMLTools.parseXMLFile ("xml/CollectionConfig.xml", true);
    3829         String filename = collect_cfg_file.getName ().toLowerCase ();
    3830        
    3831         if (filename.endsWith (".cfg")) {
    3832             parse (collect_cfg_file);
    3833         }
    3834         if (filename.endsWith (".xml")) {
    3835             parseCollectionConfigXML (collect_cfg_file, document);
    3836         }
    3837        
    3838         //XMLTools.printXMLNode(document.getDocumentElement());
    3839     }
    3840    
    3841     // Append the elements, which are of Element type, in 'list' to Element 'to'
    3842     private void appendArrayList (Element to, ArrayList list) {
    3843         if (list == null) return;
    3844        
    3845         for (int i=0; i<list.size (); i++) {
    3846             appendProperly (to, (Element)list.get (i));
    3847         }
    3848     }
    3849     //Convert the internal XML DOM tree (dOc) into that of collectionConfig.xml (skeleton)
    3850     public Document convertInternalToCollectionConfig (Document dOc) {
    3851         //first parse an empty skeleton of xml config file
    3852         //The aim is to convert the internal structure into this skeleton
    3853         Document skeleton = XMLTools.parseXMLFile ("xml/CollectionConfig.xml", true);
    3854         //Element internal = dOc.getDocumentElement();
    3855         convertMetadataList (dOc, skeleton);
    3856         convertDisplayItemList (dOc, skeleton);
    3857         convertBuildType (dOc, skeleton);
    3858         convertIndex (dOc, skeleton);
    3859         convertPlugin (dOc, skeleton);//also do the plugout element
    3860         convertClassifier (dOc, skeleton);
    3861         convertSubcollectionIndexes (dOc, skeleton);
    3862         convertLanguages (dOc, skeleton);
    3863         convertSubcollection (dOc, skeleton);
    3864         convertSearchType (dOc, skeleton);
    3865         convertSearchFormat (dOc, skeleton);
    3866         convertDisplayFormat (dOc, skeleton);
    3867         convertReplaceListRef (dOc, skeleton);
    3868         convertOAIElement(dOc, skeleton);
    3869 
    3870         return skeleton;
    3871     }
    3872 
    3873   static private HashMap plugin_map = null;
     428    config_filename = StaticStrings.COLLECT_CFG;
     429    backup_filename = Utility.COLLECT_BAK;
     430      }
     431      File original_file = new File (collect_config_file.getParentFile (), config_filename);
     432      File backup_file = new File (collect_config_file.getParentFile (), backup_filename);
     433      if (backup_file.exists ()) {
     434    backup_file.delete ();
     435      }
     436      if (!original_file.renameTo (backup_file)) {
     437    System.err.println ("Warning: can't rename "+config_filename + " to "+ backup_filename);
     438      }
     439    }
     440
     441    // now save the file
     442    if (Gatherer.GS3) {
     443      CollectionConfigXMLReadWrite.save(collect_config_file, document);
     444    } else {
     445      // we have already converted to string, so save here
     446      try {
     447    OutputStream ostream = new FileOutputStream (collect_config_file);
     448    Writer file_writer = new OutputStreamWriter (ostream, ENCODING);
     449    BufferedWriter buffered_writer = new BufferedWriter (file_writer);
     450    buffered_writer.write (config_file_string);
     451    buffered_writer.close ();
     452      }
     453      catch (Exception exception) {
     454    DebugStream.println ("Error in CollectionConfiguration.save(): " + exception);
     455    DebugStream.printStackTrace (exception);
     456      }
     457     
     458    }
     459
     460    // save the string version
     461    saved_config_file_string = config_file_string;
     462   
     463    // If we're using a remote Greenstone server, upload the new collect.cfg file
     464    if (Gatherer.isGsdlRemote) {
     465      Gatherer.remoteGreenstoneServer.uploadCollectionFile (collection_name, collect_config_file);
     466    }
    3874467 
    3875   private void setUpPluginNameMap() {
    3876     plugin_map = new HashMap();
    3877     plugin_map.put("GAPlug", "GreenstoneXMLPlugin");
    3878     plugin_map.put("RecPlug", "DirectoryPlugin");
    3879     plugin_map.put("ArcPlug","ArchivesInfPlugin");
    3880     plugin_map.put("TEXTPlug","TextPlugin");
    3881     plugin_map.put("XMLPlug","ReadXMLFile");
    3882     plugin_map.put("EMAILPlug","EmailPlugin");
    3883     plugin_map.put("SRCPlug","SourceCodePlugin");
    3884     plugin_map.put("NULPlug","NulPlugin");
    3885     plugin_map.put("W3ImgPlug","HTMLImagePlugin");
    3886     plugin_map.put("PagedImgPlug","PagedImagePlugin");
    3887     plugin_map.put("METSPlug", "GreenstoneMETSPlugin");
    3888     plugin_map.put("DBPlug", "DatabasePlugin");
    3889     plugin_map.put("PPTPlug", "PowerPointPlugin");
    3890     plugin_map.put("PSPlug", "PostScriptPlugin");
    3891   }
    3892 
    3893   private String ensureNewPluginName(String plugin) {
    3894     if (plugin.endsWith("Plugin")) return plugin;
    3895     if (plugin_map == null) {
    3896       setUpPluginNameMap();
    3897     }
    3898     String new_name = (String)plugin_map.get(plugin);
    3899     if (new_name != null) return new_name;
    3900     new_name = plugin.replaceAll("Plug", "Plugin");
    3901     return new_name;
    3902   }
    3903    
    3904 
    3905     ///*********************************************************************************************************///
     468       
     469    // Now re-add the collection to the Local Library server
     470    if (collection_released) {
     471      LocalLibraryServer.addCollection (collection_name);
     472    }
     473  }
     474
     475 
     476   
    3906477}
    3907478
     479
Note: See TracChangeset for help on using the changeset viewer.