Changeset 24824 for main/trunk/gli


Ignore:
Timestamp:
2011-11-30T15:36:35+13:00 (12 years ago)
Author:
sjm84
Message:

Reformatting this file ahead of some changes

File:
1 edited

Legend:

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

    r22970 r24824  
    4444import org.w3c.dom.*;
    4545
    46 /** 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).
     46/**
     47 * This class provides access to an xml-type view of the collect.cfg file. This
     48 * is useful as it allows the manipulation and free form editing of a
     49 * collect.cfg file while still allowing the various CDM data managers to base
     50 * themselves directly on this model (whereas they used to be independant
     51 * ListModels which clobbered the ordering of unparsed commands).
     52 *
    4753 * @author John Thompson, Greenstone Digital Library, University of Waikato
    4854 */
    49 public class CollectionConfiguration {
    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     }
    159                
    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 public Element getDatabaseType () {
    319     Element element = getOrCreateElementByTagName (StaticStrings.DATABASETYPE_ELEMENT, null, null);
    320     element.setAttribute (StaticStrings.NAME_ATTRIBUTE, StaticStrings.DATABASETYPE_STR);
    321     element.setAttribute (StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
    322     return element;
    323        
    324   }
    325    
    326   /** Retrieve or create the subindexes Element. */
    327   public Element getSubIndexes () {
    328     return getOrCreateElementByTagName (StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, null, null);
    329   }
    330    
    331   /** Retrieve or create the supercollections Element. */
    332   public Element getSuperCollection () {
    333     return getOrCreateElementByTagName (StaticStrings.SUPERCOLLECTION_ELEMENT, null, null);
    334   }
    335    
    336   public boolean ready () {
    337     return document != null;
    338   }
    339    
    340    
    341    
    342    
    343   /** ************************** Private Methods ***************************/
    344    
    345  
    346   /** Retrieve or create the indexes Element. */
    347   static private Element getOrCreateElementByTagName (String name, String conditional_attribute, String required_value) {
    348     Element document_element = document.getDocumentElement ();
    349     NodeList elements = document_element.getElementsByTagName (name);
    350     int elements_length = elements.getLength ();
    351     if(elements_length > 0) {
    352       if(conditional_attribute == null) {
    353     document_element = null;
    354     return (Element) elements.item (0);
    355       }
    356       else {
    357     for(int i = 0; i < elements_length; i++) {
    358       Element element = (Element) elements.item (i);
    359       if(element.getAttribute (conditional_attribute).equals (required_value)) {
    360         document_element = null;
    361         return element;
    362       }
    363       element = null;
    364     }
    365       }
    366     }
    367     // Create the element
    368     Element element = document.createElement (name);
    369     // If there was a property set it
    370     if(conditional_attribute != null) {
    371       element.setAttribute (conditional_attribute, required_value);
    372     }
    373     Node target_node = findInsertionPoint (element);
    374     if(target_node != null) {
    375       document_element.insertBefore (element, target_node);
    376     }
    377     else {
    378       document_element.appendChild (element);
    379     }
    380     document_element = null;
    381     return element;
    382   }
    383    
    384 
    385 
    386  
    387 
    388   /** 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.
    389    * @param writer the BufferedWriter to which the str will be written
    390    * @param str the String to be written
    391    */
    392   private void write (BufferedWriter writer, String str)
    393     throws IOException {
    394     writer.write (str, 0, str.length ());
    395   }
    396    
    397 
    398   public void saveIfNecessary () {
    399    
    400     // Generate a string version of internal document
    401     String config_file_string = null;
    402     if (Gatherer.GS3) {
    403       config_file_string = CollectionConfigXMLReadWrite.generateStringVersion(document);
    404     } else {
    405       config_file_string = CollectCfgReadWrite.generateStringVersion(document);
    406     }
    407     // compare to saved version
    408     if (saved_config_file_string != null) {
    409       if (saved_config_file_string.equals(config_file_string)) {
    410     DebugStream.println (collect_config_filename +" file hasn't changed so no save necessary...");
    411     return;
    412       }
    413     }
    414    
    415     // We need to save...
    416     DebugStream.println (collect_config_filename +" file has changed, saving now...");
    417 
    418        
    419     // If we're using the Local Library we must release the collection before writing to the collect.cfg file
    420     String collection_name = CollectionManager.getLoadedCollectionName (true); // url style slash
    421     boolean collection_released = false;
    422     if (Gatherer.c_man.built () && LocalLibraryServer.isRunning () == true) {
    423       // Release the collection
    424       LocalLibraryServer.releaseCollection (collection_name);
    425       collection_released = true;
    426     }
    427        
    428     // Make a backup of the existing config file
    429     if (collect_config_file.exists ()) {
    430       String config_filename;
    431       String backup_filename;
    432       if (Gatherer.GS3) {
    433     config_filename = Utility.COLLECTION_CONFIG_XML;
    434     backup_filename = Utility.COLLECTION_CONFIG_BAK;
    435       } else {
    436     config_filename = StaticStrings.COLLECT_CFG;
    437     backup_filename = Utility.COLLECT_BAK;
    438       }
    439       File original_file = new File (collect_config_file.getParentFile (), config_filename);
    440       File backup_file = new File (collect_config_file.getParentFile (), backup_filename);
    441       if (backup_file.exists ()) {
    442     backup_file.delete ();
    443       }
    444       if (!original_file.renameTo (backup_file)) {
    445     System.err.println ("Warning: can't rename "+config_filename + " to "+ backup_filename);
    446       }
    447     }
    448 
    449     // now save the file
    450     if (Gatherer.GS3) {
    451       CollectionConfigXMLReadWrite.save(collect_config_file, document);
    452     } else {
    453       // we have already converted to string, so save here
    454       try {
    455     OutputStream ostream = new FileOutputStream (collect_config_file);
    456     Writer file_writer = new OutputStreamWriter (ostream, ENCODING);
    457     BufferedWriter buffered_writer = new BufferedWriter (file_writer);
    458     buffered_writer.write (config_file_string);
    459     buffered_writer.close ();
    460       }
    461       catch (Exception exception) {
    462     DebugStream.println ("Error in CollectionConfiguration.save(): " + exception);
    463     DebugStream.printStackTrace (exception);
    464       }
    465      
    466     }
    467 
    468     // save the string version
    469     saved_config_file_string = config_file_string;
    470    
    471     // If we're using a remote Greenstone server, upload the new collect.cfg file
    472     if (Gatherer.isGsdlRemote) {
    473       Gatherer.remoteGreenstoneServer.uploadCollectionFile (collection_name, collect_config_file);
    474     }
    475  
    476        
    477     // Now re-add the collection to the Local Library server
    478     if (collection_released) {
    479       LocalLibraryServer.addCollection (collection_name);
    480     }
    481   }
    482 
    483  
    484    
     55public class CollectionConfiguration
     56{
     57    static final public String ENCODING = "UTF-8";
     58    static final public String NEWLINE_ELEMENT = "NewLine";
     59
     60    static private Document document;
     61    static private String saved_config_file_string = null;
     62
     63    // may be collec.cfg (GS2) or collectionConfig.xml (GS3)
     64    private File collect_config_file;
     65    private String collect_config_filename;
     66
     67    // This method is initilised in CollectionDesignManager.java constructor
     68    public CollectionConfiguration(File collect_config_file)
     69    {
     70        this.collect_config_file = collect_config_file;
     71        this.collect_config_filename = collect_config_file.getName();
     72        // parse the XML template
     73        document = XMLTools.parseXMLFile("xml/CollectionConfig.xml", true);
     74        String filename = collect_config_filename.toLowerCase();
     75
     76        if (filename.endsWith(".cfg"))
     77        {
     78            saved_config_file_string = CollectCfgReadWrite.parse(collect_config_file, document);
     79        }
     80        else if (filename.endsWith(".xml"))
     81        {
     82            CollectionConfigXMLReadWrite.parse(collect_config_file, document);
     83        }
     84
     85        //XMLTools.printXMLNode(document.getDocumentElement());
     86    }
     87
     88    static public Element createElement(String element_name)
     89    {
     90        return document.createElement(element_name);
     91    }
     92
     93    /** Gives the preferred ordering of commands */
     94    static final public String[] COMMAND_ORDER = { StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, StaticStrings.BUILDTYPE_ELEMENT, StaticStrings.PLUGIN_ELEMENT, StaticStrings.INDEXES_ELEMENT, StaticStrings.INDEX_DEFAULT_ELEMENT, StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.INDEXOPTION_DEFAULT_ELEMENT, StaticStrings.LANGUAGES_ELEMENT, StaticStrings.LANGUAGE_DEFAULT_ELEMENT, StaticStrings.LANGUAGE_METADATA_ELEMENT, StaticStrings.SUBCOLLECTION_ELEMENT, StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT, StaticStrings.SUPERCOLLECTION_ELEMENT, StaticStrings.CLASSIFY_ELEMENT, StaticStrings.FORMAT_ELEMENT, StaticStrings.COLLECTIONMETADATA_ELEMENT };
     95
     96    /**
     97     * Find the best insertion position for the given DOM Element. This should
     98     * try to match command tag, and if found should then try to group by name
     99     * or type (eg CollectionMeta), or append to end is no such grouping exists
     100     * (eg Plugins). Failing a command match it will check against the command
     101     * order for the best insertion location.
     102     *
     103     * @param target_element
     104     *            the command Element to be inserted
     105     * @return the Element which the given command should be inserted before, or
     106     *         null to append to end of list
     107     */
     108    static public Node findInsertionPoint(Element target_element)
     109    {
     110        ///ystem.err.println("Find insertion point: " + target_element.getNodeName());
     111        String target_element_name = target_element.getNodeName();
     112        Element document_element = document.getDocumentElement();
     113        // Try to find commands with the same tag.
     114        NodeList matching_elements = document_element.getElementsByTagName(target_element_name);
     115        // If we found matching elements, then we have our most likely insertion location, so check within for groupings
     116        if (matching_elements.getLength() != 0)
     117        {
     118            ///ystem.err.println("Found matching elements.");
     119            // Only CollectionMeta are grouped.
     120            if (target_element_name.equals(StaticStrings.COLLECTIONMETADATA_ELEMENT))
     121            {
     122                ///ystem.err.println("Dealing with collection metadata");
     123                // 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.
     124                // So if the command to be added is special add it immediately after any other special command
     125                if (target_element.getAttribute(StaticStrings.SPECIAL_ATTRIBUTE).equals(StaticStrings.TRUE_STR))
     126                {
     127                    int index = 0;
     128                    Element matched_element = (Element) matching_elements.item(index);
     129                    Element sibling_element = (Element) matched_element.getNextSibling();
     130                    while (sibling_element.getAttribute(StaticStrings.SPECIAL_ATTRIBUTE).equals(StaticStrings.TRUE_STR))
     131                    {
     132                        index++;
     133                        matched_element = (Element) matching_elements.item(index);
     134                        sibling_element = (Element) matched_element.getNextSibling();
     135                    }
     136                    if (sibling_element.getNodeName().equals(NEWLINE_ELEMENT))
     137                    {
     138                        Element newline_element = document.createElement(NEWLINE_ELEMENT);
     139                        document_element.insertBefore(newline_element, sibling_element);
     140                    }
     141                    return sibling_element;
     142                }
     143                // Otherwise try to find a matching 'name' and add after the last one in that group.
     144                else
     145                {
     146                    int index = 0;
     147                    target_element_name = target_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
     148                    boolean found = false;
     149                    // Skip all of the special metadata
     150                    Element matched_element = (Element) matching_elements.item(index);
     151                    while (matched_element.getAttribute(StaticStrings.SPECIAL_ATTRIBUTE).equals(StaticStrings.TRUE_STR))
     152                    {
     153                        index++;
     154                        matched_element = (Element) matching_elements.item(index);
     155                    }
     156                    // Begin search
     157                    while (!found && matched_element != null)
     158                    {
     159                        if (matched_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equals(target_element_name))
     160                        {
     161                            found = true;
     162                        }
     163                        else
     164                        {
     165                            index++;
     166                            matched_element = (Element) matching_elements.item(index);
     167                        }
     168                    }
     169                    // If we found a match, we need to continue checking until we find the last name match.
     170                    if (found)
     171                    {
     172                        index++;
     173                        Element previous_sibling = matched_element;
     174                        Element sibling_element = (Element) matching_elements.item(index);
     175                        while (sibling_element != null && sibling_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equals(target_element_name))
     176                        {
     177                            previous_sibling = sibling_element;
     178                            index++;
     179                            sibling_element = (Element) matching_elements.item(index);
     180                        }
     181                        // 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!
     182                        return previous_sibling.getNextSibling();
     183                    }
     184                    // If not found we just add after last metadata element
     185                    else
     186                    {
     187                        Element last_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
     188                        return last_element.getNextSibling();
     189                    }
     190                }
     191
     192            }
     193            else
     194            {
     195                ///ystem.err.println("Not dealing with collection meta.");
     196                Element matched_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
     197                // 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)
     198                Node sibling_element = matched_element.getNextSibling();
     199                if (sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT))
     200                {
     201                    Element newline_element = document.createElement(NEWLINE_ELEMENT);
     202                    document_element.insertBefore(newline_element, sibling_element);
     203                }
     204                return sibling_element; // Note that this may be null
     205            }
     206        }
     207        ///ystem.err.println("No matching elements found.");
     208        // Locate where this command is in the ordering
     209        int command_index = -1;
     210        for (int i = 0; command_index == -1 && i < COMMAND_ORDER.length; i++)
     211        {
     212            if (COMMAND_ORDER[i].equals(target_element_name))
     213            {
     214                command_index = i;
     215            }
     216        }
     217        ///ystem.err.println("Command index is: " + command_index);
     218        // Now move forward, checking for existing elements in each of the preceeding command orders.
     219        int preceeding_index = command_index - 1;
     220        ///ystem.err.println("Searching before the target command.");
     221        while (preceeding_index >= 0)
     222        {
     223            matching_elements = document_element.getElementsByTagName(COMMAND_ORDER[preceeding_index]);
     224            // If we've found a match
     225            if (matching_elements.getLength() > 0)
     226            {
     227                // We add after the last element
     228                Element matched_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
     229                // 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)
     230                Node sibling_element = matched_element.getNextSibling();
     231                if (sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT))
     232                {
     233                    Element newline_element = document.createElement(NEWLINE_ELEMENT);
     234                    document_element.insertBefore(newline_element, sibling_element);
     235                }
     236                return sibling_element; // Note that this may be null
     237            }
     238            preceeding_index--;
     239        }
     240        // If all that fails, we now move backwards through the commands
     241        int susceeding_index = command_index + 1;
     242        ///ystem.err.println("Searching after the target command.");
     243        while (susceeding_index < COMMAND_ORDER.length)
     244        {
     245            matching_elements = document_element.getElementsByTagName(COMMAND_ORDER[susceeding_index]);
     246            // If we've found a match
     247            if (matching_elements.getLength() > 0)
     248            {
     249                // We add before the first element
     250                Element matched_element = (Element) matching_elements.item(0);
     251                // 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)
     252                Node sibling_element = matched_element.getPreviousSibling();
     253                if (sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT))
     254                {
     255                    Element newline_element = document.createElement(NEWLINE_ELEMENT);
     256                    document_element.insertBefore(newline_element, sibling_element);
     257                }
     258                return sibling_element; // Note that this may be null
     259            }
     260            susceeding_index++;
     261        }
     262        // Well. Apparently there are no other commands in this collection configuration. So append away...
     263        return null;
     264    }
     265
     266    static public NodeList getElementsByTagName(String element_name)
     267    {
     268        return document.getDocumentElement().getElementsByTagName(element_name);
     269    }
     270
     271    public Element getDocumentElement()
     272    {
     273        return document.getDocumentElement();
     274    }
     275
     276    /**
     277     * This debug facility shows the currently loaded collect.cfg or
     278     * CollectConfig.xml file as a DOM tree.
     279     */
     280    public void display()
     281    {
     282        JDialog dialog = new JDialog(Gatherer.g_man, "Collection Configuration", false);
     283        dialog.setSize(400, 400);
     284        JPanel content_pane = (JPanel) dialog.getContentPane();
     285        final DOMTree tree = new DOMTree(document);
     286        JButton refresh_button = new GLIButton("Refresh Tree");
     287        refresh_button.addActionListener(new ActionListener()
     288        {
     289            public void actionPerformed(ActionEvent event)
     290            {
     291                tree.setDocument(document);
     292            }
     293        });
     294        content_pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
     295        content_pane.setLayout(new BorderLayout());
     296        content_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
     297        content_pane.add(refresh_button, BorderLayout.SOUTH);
     298        dialog.setVisible(true);
     299    }
     300
     301    public File getFile()
     302    {
     303        return collect_config_file;
     304    }
     305
     306    public Element getCreator()
     307    {
     308        Element element = getOrCreateElementByTagName(StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, null, null);
     309        element.setAttribute(StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_CREATOR_STR);
     310        element.setAttribute(StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
     311        return element;
     312    }
     313
     314    public Element getMaintainer()
     315    {
     316        Element element = getOrCreateElementByTagName(StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, null, null);
     317        element.setAttribute(StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR);
     318        element.setAttribute(StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
     319        return element;
     320    }
     321
     322    /** Retrieve or create the languages Element. */
     323    public Element getLanguages()
     324    {
     325        return getOrCreateElementByTagName(StaticStrings.LANGUAGES_ELEMENT, null, null);
     326    }
     327
     328    public Element getLanguageMetadata()
     329    {
     330        return getOrCreateElementByTagName(StaticStrings.LANGUAGE_METADATA_ELEMENT, null, null);
     331    }
     332
     333    public Element getLevels()
     334    {
     335        return getOrCreateElementByTagName(StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVELS_STR);
     336    }
     337
     338    public Element getLevelDefault()
     339    {
     340        return getOrCreateElementByTagName(StaticStrings.INDEXOPTION_DEFAULT_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVEL_DEFAULT_STR);
     341    }
     342
     343    public Element getIndexOptions()
     344    {
     345        return getOrCreateElementByTagName(StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.INDEXOPTIONS_STR);
     346    }
     347
     348    /**
     349     * Retrieve or create the indexes Element. Note that this method behaves
     350     * differently from the other getBlah methods, in that it also has to keep
     351     * in mind that indexes come in two flavours, MG and MGPP.
     352     */
     353    public Element getMGIndexes()
     354    {
     355        return getOrCreateElementByTagName(StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
     356    }
     357
     358    public Element getMGPPIndexes()
     359    {
     360        return getOrCreateElementByTagName(StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
     361    }
     362
     363    public Element getPublic()
     364    {
     365        Element element = getOrCreateElementByTagName(StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, null, null);
     366        element.setAttribute(StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_PUBLIC_STR);
     367        element.setAttribute(StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
     368        return element;
     369    }
     370
     371    public Element getBuildType()
     372    {
     373        Element element = getOrCreateElementByTagName(StaticStrings.BUILDTYPE_ELEMENT, null, null);
     374        element.setAttribute(StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
     375        element.setAttribute(StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
     376        return element;
     377
     378    }
     379
     380    public Element getDatabaseType()
     381    {
     382        Element element = getOrCreateElementByTagName(StaticStrings.DATABASETYPE_ELEMENT, null, null);
     383        element.setAttribute(StaticStrings.NAME_ATTRIBUTE, StaticStrings.DATABASETYPE_STR);
     384        element.setAttribute(StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
     385        return element;
     386
     387    }
     388
     389    /** Retrieve or create the subindexes Element. */
     390    public Element getSubIndexes()
     391    {
     392        return getOrCreateElementByTagName(StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, null, null);
     393    }
     394
     395    /** Retrieve or create the supercollections Element. */
     396    public Element getSuperCollection()
     397    {
     398        return getOrCreateElementByTagName(StaticStrings.SUPERCOLLECTION_ELEMENT, null, null);
     399    }
     400
     401    public boolean ready()
     402    {
     403        return document != null;
     404    }
     405
     406    /** ************************** Private Methods ***************************/
     407
     408    /** Retrieve or create the indexes Element. */
     409    static private Element getOrCreateElementByTagName(String name, String conditional_attribute, String required_value)
     410    {
     411        Element document_element = document.getDocumentElement();
     412        NodeList elements = document_element.getElementsByTagName(name);
     413        int elements_length = elements.getLength();
     414        if (elements_length > 0)
     415        {
     416            if (conditional_attribute == null)
     417            {
     418                document_element = null;
     419                return (Element) elements.item(0);
     420            }
     421            else
     422            {
     423                for (int i = 0; i < elements_length; i++)
     424                {
     425                    Element element = (Element) elements.item(i);
     426                    if (element.getAttribute(conditional_attribute).equals(required_value))
     427                    {
     428                        document_element = null;
     429                        return element;
     430                    }
     431                    element = null;
     432                }
     433            }
     434        }
     435        // Create the element
     436        Element element = document.createElement(name);
     437        // If there was a property set it
     438        if (conditional_attribute != null)
     439        {
     440            element.setAttribute(conditional_attribute, required_value);
     441        }
     442        Node target_node = findInsertionPoint(element);
     443        if (target_node != null)
     444        {
     445            document_element.insertBefore(element, target_node);
     446        }
     447        else
     448        {
     449            document_element.appendChild(element);
     450        }
     451        document_element = null;
     452        return element;
     453    }
     454
     455    /**
     456     * Write the text to the buffer. This is used so we don't have to worry
     457     * about storing intermediate String values just so we can calaulate length
     458     * and offset.
     459     *
     460     * @param writer
     461     *            the BufferedWriter to which the str will be written
     462     * @param str
     463     *            the String to be written
     464     */
     465    private void write(BufferedWriter writer, String str) throws IOException
     466    {
     467        writer.write(str, 0, str.length());
     468    }
     469
     470    public void saveIfNecessary()
     471    {
     472
     473        // Generate a string version of internal document
     474        String config_file_string = null;
     475        if (Gatherer.GS3)
     476        {
     477            config_file_string = CollectionConfigXMLReadWrite.generateStringVersion(document);
     478        }
     479        else
     480        {
     481            config_file_string = CollectCfgReadWrite.generateStringVersion(document);
     482        }
     483        // compare to saved version
     484        if (saved_config_file_string != null)
     485        {
     486            if (saved_config_file_string.equals(config_file_string))
     487            {
     488                DebugStream.println(collect_config_filename + " file hasn't changed so no save necessary...");
     489                return;
     490            }
     491        }
     492
     493        // We need to save...
     494        DebugStream.println(collect_config_filename + " file has changed, saving now...");
     495
     496        // If we're using the Local Library we must release the collection before writing to the collect.cfg file
     497        String collection_name = CollectionManager.getLoadedCollectionName(true); // url style slash
     498        boolean collection_released = false;
     499        if (Gatherer.c_man.built() && LocalLibraryServer.isRunning() == true)
     500        {
     501            // Release the collection
     502            LocalLibraryServer.releaseCollection(collection_name);
     503            collection_released = true;
     504        }
     505
     506        // Make a backup of the existing config file
     507        if (collect_config_file.exists())
     508        {
     509            String config_filename;
     510            String backup_filename;
     511            if (Gatherer.GS3)
     512            {
     513                config_filename = Utility.COLLECTION_CONFIG_XML;
     514                backup_filename = Utility.COLLECTION_CONFIG_BAK;
     515            }
     516            else
     517            {
     518                config_filename = StaticStrings.COLLECT_CFG;
     519                backup_filename = Utility.COLLECT_BAK;
     520            }
     521            File original_file = new File(collect_config_file.getParentFile(), config_filename);
     522            File backup_file = new File(collect_config_file.getParentFile(), backup_filename);
     523            if (backup_file.exists())
     524            {
     525                backup_file.delete();
     526            }
     527            if (!original_file.renameTo(backup_file))
     528            {
     529                System.err.println("Warning: can't rename " + config_filename + " to " + backup_filename);
     530            }
     531        }
     532
     533        // now save the file
     534        if (Gatherer.GS3)
     535        {
     536            CollectionConfigXMLReadWrite.save(collect_config_file, document);
     537        }
     538        else
     539        {
     540            // we have already converted to string, so save here
     541            try
     542            {
     543                OutputStream ostream = new FileOutputStream(collect_config_file);
     544                Writer file_writer = new OutputStreamWriter(ostream, ENCODING);
     545                BufferedWriter buffered_writer = new BufferedWriter(file_writer);
     546                buffered_writer.write(config_file_string);
     547                buffered_writer.close();
     548            }
     549            catch (Exception exception)
     550            {
     551                DebugStream.println("Error in CollectionConfiguration.save(): " + exception);
     552                DebugStream.printStackTrace(exception);
     553            }
     554
     555        }
     556
     557        // save the string version
     558        saved_config_file_string = config_file_string;
     559
     560        // If we're using a remote Greenstone server, upload the new collect.cfg file
     561        if (Gatherer.isGsdlRemote)
     562        {
     563            Gatherer.remoteGreenstoneServer.uploadCollectionFile(collection_name, collect_config_file);
     564        }
     565
     566        // Now re-add the collection to the Local Library server
     567        if (collection_released)
     568        {
     569            LocalLibraryServer.addCollection(collection_name);
     570        }
     571    }
     572
    485573}
    486 
    487 
Note: See TracChangeset for help on using the changeset viewer.