Changeset 24824
- Timestamp:
- 2011-11-30T15:36:35+13:00 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/gli/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java
r22970 r24824 44 44 import org.w3c.dom.*; 45 45 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 * 47 53 * @author John Thompson, Greenstone Digital Library, University of Waikato 48 54 */ 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 55 public 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 485 573 } 486 487
Note:
See TracChangeset
for help on using the changeset viewer.