Changeset 6051
- Timestamp:
- 2003-11-30T21:43:23+13:00 (20 years ago)
- Location:
- trunk/gli
- Files:
-
- 1 added
- 32 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gli/buglist/status.txt
r6038 r6051 29 29 3.2 30 30 Fixed (16-10-03) 31 Metadata importing should have happened automatically. To investigate further. 31 Metadata importing should have happened automatically. To investigate further.<br>Tracked down an error in ElementWrapper that was causing a NPE when attempting to import metadata with files - but only if you hadn't based your collection on a previous one. Its possible that is what was causing the problem/confusion here 32 32 33 33 203B005 … … 140 140 Unknown 141 141 6 142 Fixed 22-10-2003143 Default strings for all features to be added by way of a combobox containing currently/commonly used format strings .Turns out that one multipurpose default format string can be used. Added 'Use Default Format' button to format manager which becomes active when a part is selected that has a default format string available142 Fixed - 22-10-03 143 Default strings for all features to be added by way of a combobox containing currently/commonly used format strings<br>Turns out that one multipurpose default format string can be used. Added 'Use Default Format' button to format manager which becomes active when a part is selected that has a default format string available 144 144 145 145 203F019 … … 205 205 5 206 206 Fixed 207 Adding suggested information to help. Tooltips also being added .Tooltips complete. Section on basic functionality removed from help documents due to translation constraints207 Adding suggested information to help. Tooltips also being added<br>Tooltips complete. Section on basic functionality removed from help documents due to translation constraints 208 208 209 209 203F027 … … 324 324 Linux, Win98, WinXP 325 325 NA 326 Fixed 22-10- 2003327 Include 'expand text' button for extracted metadata. Investigate other methods for displaying HTML based information .Expand text button in place326 Fixed 22-10-03 327 Include 'expand text' button for extracted metadata. Investigate other methods for displaying HTML based information<br>Expand text button in place 328 328 329 329 203B042 … … 396 396 Win98, Win2000 397 397 6 398 Fixed 22-10-2003399 Ensure GLI correctly detects when it needs to produce hfiles .Elements in metadata sets can now be told if they are to generate hfiles as necessary, however of the three mentioned above only AZList was a bug. Organization has a flat structure so doesn't really need a Hierarchy classifier (a AZCompactList would do)398 Fixed - 22-10-03 399 Ensure GLI correctly detects when it needs to produce hfiles<br>Elements in metadata sets can now be told if they are to generate hfiles as necessary, however of the three mentioned above only AZList was a bug. Organization has a flat structure so doesn't really need a Hierarchy classifier (a AZCompactList would do) 400 400 401 401 203F051 … … 428 428 Win98, Win2000 429 429 6 430 Fixed 16-10-2003431 Ensure that selecting a fixed feature clears component selection and adjusts output state appropriately .It was, the problem lay in trying to change the gui from within the EventThread again - SwingUtilities to the rescue.430 Fixed (16-10-03) 431 Ensure that selecting a fixed feature clears component selection and adjusts output state appropriately<br>It was, the problem lay in trying to change the gui from within the EventThread again - SwingUtilities to the rescue. 432 432 433 433 203B055 … … 436 436 Win98, Win2000 437 437 6 438 Fixed 16-10-2003439 First index should be the default if none other is selected. 438 Fixed (16-10-03) 439 First index should be the default if none other is selected.<br>Fixed as part of the redesign of the indexes page 440 440 441 441 203B056 … … 1428 1428 All 1429 1429 NA 1430 Fixed 11-11-20031431 Something to do with Codec transform not being applied at the right place<br>Actually the whole idea of using double escapes is flawed as this just causing further problems during building. Instead replace escape with some 'safe' character (What about newline?). Of course, this would be transparent to the user as they have been explicitly told in several help documents to use escape.<br> Why CVS didn't update when I changed the status of this bug before I don't know - but it is now officially, completely and finally fixed.1430 Fixed 05-11-03 1431 Something to do with Codec transform not being applied at the right place<br>Actually the whole idea of using double escapes is flawed as this just causing further problems during building. Instead replace escape with some 'safe' character (What about newline?). Of course, this would be transparent to the user as they have been explicitly told in several help documents to use escape.<br>Have now used the '|' character behind the scenes as it doesn't seem to cause problems in GLI and Greenstone. Of course the user still sees and uses '\' to denote hierarchical paths. 1432 1432 1433 1433 203B180 … … 1444 1444 All 1445 1445 NA 1446 Fixed 27-11-20031447 OK<br>Gone. The 'alias' was the unique identifier of a particular row in the hfile - perhaps key would have been a more descriptive name - anyhow I now just use the full-path of the metadata value which is gareunteed to be unique (whereas allowing people to enter their own 'alias' would have required GLI to test this). 1446 Fixed - 05-11-03 1447 The value alias is meant to be a unique identifier for a certain hierarchy path - this isn't made clear in the documents, and is far less of an issue for computer generate documents as it would've been for hand written ones 1448 1448 1449 1449 203B182 … … 1996 1996 All 1997 1997 NA 1998 Pending 1998 Fixed 13-11-03 1999 1999 Ensure description metadata extracted from plugins/classifiers and utilized by the comboboxes 2000 2000 … … 2012 2012 All 2013 2013 NA 2014 Fixed 2014 Fixed 13-11-03 2015 2015 Increase empty string checking 2016 2016 … … 2124 2124 All 2125 2125 NA 2126 Pending Again 2127 Make memory use reasonable<br> Reinstated the idea of caching metadata.xml files rather than trying to load them all2126 Fixed - 06-11-03 2127 Make memory use reasonable<br>I've made memory savings in two ways (hopefully). First I've re-activated the idea of only caching a certain number of MDSDocuments in memory (its currently arbitarily set at twenty five), as one of the causes of this problem was hundreds of small MDSDocuments being loaded. The second problem is that the threaded task that loaded all of the documents initially never released the tree nodes after creating them - thus if your collection contains hundreds of folder nodes, each with a small mds, you'd blow your memory allowance. Since caching has been re-enabled I've simply disabled the loader thread (which used to be necessary for hierarchies when I had to depend on the stupid numbering scheme - this however has hopefully been addressed with the hvalue attribute in MDS documents). 2128 2128 2129 2129 203B320 -
trunk/gli/classes/dictionary.properties
r6050 r6051 348 348 # 349 349 #***** Collection ***** 350 Collection.Collection:{32}Collection: {0}{34}350 Collection.Collection:{32}Collection:{34} 351 351 Collection.Delete_Tooltip:Delete selected files and folders 352 352 Collection.Filter_Tooltip:Restrict the files shown in the file tree … … 555 555 General.Apply:Apply 556 556 General.Apply_Tooltip:Apply the current settings but do not exit the dialog 557 General.Browse:Browse 557 General.Browse:Browse... 558 558 General.Browse_Tooltip:Choose a filepath on your computer 559 559 General.Cancel:Cancel … … 698 698 # 699 699 #***** Menu Options ***** 700 Menu.Collapse:Close Folder 700 701 Menu.Edit:Edit 701 702 Menu.Edit_Copy:Copy (ctrl-c) … … 706 707 Menu.Edit_Search:Search 707 708 Menu.Edit_Undo:Undo 709 Menu.Expand:Open Folder 708 710 Menu.File:File 709 711 Menu.File_Associations:File Associations... … … 899 901 NewCollectionPrompt.Collection_Description:Description of content: 900 902 #NewCollectionPrompt.Collection_Email:Author's Email: 901 #NewCollectionPrompt.Collection_Name:Short Name:903 NewCollectionPrompt.Collection_Name:Short Name: 902 904 #NewCollectionPrompt.Collection_Name_Tooltip:Short collection name, used internally (must be 8 characters or less) 903 905 NewCollectionPrompt.Description_Error:The description field must be filled out. Please correct. … … 909 911 NewCollectionPrompt.Metadata_Instructions2:(Note: You can add new ones later). 910 912 NewCollectionPrompt.Metadata_Title_Existing:Select metadata sets. 911 NewCollectionPrompt.Name_Error:You have either failed to enter a name for the collection, or the name you have choosen is already in use. Please correct.913 #NewCollectionPrompt.Name_Error:You have either failed to enter a name for the collection, or the name you have choosen is already in use. Please correct. 912 914 NewCollectionPrompt.NewCollection:-- New Collection -- 913 915 NewCollectionPrompt.Select_MDS:Available metadata sets: 914 916 NewCollectionPrompt.Set_Contains:This metadata set contains the elements 915 917 NewCollectionPrompt.Title:Create a new Collection. 918 NewCollectionPrompt.Title_Clash:The title you have choosen for your collection is already in use. Please correct. 916 919 NewCollectionPrompt.Title_Error:The title field must be filled out. Please correct. 917 920 #***** New Folder Prompt ***** … … 962 965 Preferences.General:General 963 966 Preferences.General_Tooltip:Set some general preferences 967 Preferences.General.Email:Users Email: 968 Preferences.General.Email_Tooltip:The email address automatically used for any collection created with the GLI 964 969 Preferences.General.Interface_Language:Interface Language: 965 970 Preferences.General.Interface_Language_Tooltip:Select the language you wish the interface and its controls to be displayed in. -
trunk/gli/src/org/greenstone/gatherer/Configuration.java
r6025 r6051 453 453 public void set(String property, boolean general, boolean value) { 454 454 if(property.startsWith("workflow")) { 455 System.err.println("Set property: " + property + ", general=" + general + ", value=" + value);455 Gatherer.println("Set property: " + property + ", general=" + general + ", value=" + value); 456 456 } 457 457 setString(property, general, (value ? "true" : "false")); -
trunk/gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java
r5936 r6051 400 400 case Argument.METADATUM: 401 401 value = new JComboBox(Gatherer.c_man.getCollection().msm.getAssignedElements()); 402 ((JComboBox)value).setEditable(true);402 //((JComboBox)value).setEditable(true); 403 403 // Now ensure we have the existing value or default value selected if either exist. 404 404 if(existing_value != null) { -
trunk/gli/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java
r5994 r6051 46 46 */ 47 47 public class CollectionConfiguration 48 49 50 51 52 48 extends StaticStrings { 49 50 static public Document document; 51 52 static public void main(String[] args) { 53 53 if(args.length >= 1) { 54 55 56 57 58 54 File file = new File(args[0]); 55 CollectionConfiguration collect_cfg = new CollectionConfiguration(file); 56 collect_cfg.save(true); 57 collect_cfg.save(false); 58 collect_cfg = null; 59 59 } 60 60 else { 61 62 } 63 64 65 66 67 68 69 61 System.out.println("Usage: CollectionConfiguration <filename>"); 62 } 63 } 64 65 /** 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. 66 * @param element the command Element to be inserted 67 * @return the Element which the given command should be inserted before, or null to append to end of list 68 */ 69 static public Node findInsertionPoint(Element target_element) { 70 70 ///ystem.err.println("Find insertion point: " + target_element.getNodeName()); 71 71 String target_element_name = target_element.getNodeName(); … … 75 75 // If we found matching elements, then we have our most likely insertion location, so check within for groupings 76 76 if(matching_elements.getLength() != 0) { 77 78 79 77 ///ystem.err.println("Found matching elements."); 78 // Only CollectionMeta are grouped. 79 if(target_element_name.equals(COLLECTIONMETADATA_ELEMENT)) { 80 80 ///ystem.err.println("Dealing with collection metadata"); 81 81 // 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. 82 82 // So if the command to be added is special add it immediately after any other special command 83 83 if(target_element.getAttribute(SPECIAL_ATTRIBUTE).equals(TRUE_STR)) { 84 85 86 87 84 int index = 0; 85 Element matched_element = (Element) matching_elements.item(index); 86 Element sibling_element = (Element) matched_element.getNextSibling(); 87 while(sibling_element.getAttribute(SPECIAL_ATTRIBUTE).equals(TRUE_STR)) { 88 88 index++; 89 89 matched_element = (Element) matching_elements.item(index); 90 90 sibling_element = (Element) matched_element.getNextSibling(); 91 92 91 } 92 if(sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) { 93 93 Element newline_element = document.createElement(NEWLINE_ELEMENT); 94 94 document_element.insertBefore(newline_element, sibling_element); 95 96 95 } 96 return sibling_element; 97 97 } 98 98 // Otherwise try to find a matching 'name' and add after the last one in that group. 99 99 else { 100 101 102 103 104 105 100 int index = 0; 101 target_element_name = target_element.getAttribute(NAME_ATTRIBUTE); 102 boolean found = false; 103 // Skip all of the special metadata 104 Element matched_element = (Element) matching_elements.item(index); 105 while(matched_element.getAttribute(SPECIAL_ATTRIBUTE).equals(TRUE_STR)) { 106 106 index++; 107 107 matched_element = (Element) matching_elements.item(index); 108 109 110 108 } 109 // Begin search 110 while(!found && matched_element != null) { 111 111 if(matched_element.getAttribute(NAME_ATTRIBUTE).equals(target_element_name)) { 112 112 found = true; 113 113 } 114 114 else { 115 116 117 } 118 119 120 115 index++; 116 matched_element = (Element) matching_elements.item(index); 117 } 118 } 119 // If we found a match, we need to continue checking until we find the last name match. 120 if(found) { 121 121 index++; 122 122 Element previous_sibling = matched_element; 123 123 Element sibling_element = (Element) matching_elements.item(index); 124 124 while(sibling_element != null && sibling_element.getAttribute(NAME_ATTRIBUTE).equals(target_element_name)) { 125 126 127 125 previous_sibling = sibling_element; 126 index++; 127 sibling_element = (Element) matching_elements.item(index); 128 128 } 129 129 // 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! 130 130 return previous_sibling.getNextSibling(); 131 132 133 131 } 132 // If not found we just add after last metadata element 133 else { 134 134 Element last_element = (Element) matching_elements.item(matching_elements.getLength() - 1); 135 135 return last_element.getNextSibling(); 136 137 } 138 139 140 136 } 137 } 138 139 } 140 else { 141 141 ///ystem.err.println("Not dealing with collection meta."); 142 142 Element matched_element = (Element) matching_elements.item(matching_elements.getLength() - 1); … … 144 144 Node sibling_element = matched_element.getNextSibling(); 145 145 if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) { 146 147 146 Element newline_element = document.createElement(NEWLINE_ELEMENT); 147 document_element.insertBefore(newline_element, sibling_element); 148 148 } 149 149 return sibling_element; // Note that this may be null 150 150 } 151 151 } 152 152 ///ystem.err.println("No matching elements found."); … … 154 154 int command_index = -1; 155 155 for(int i = 0; command_index == -1 && i < COMMAND_ORDER.length; i++) { 156 156 if(COMMAND_ORDER[i].equals(target_element_name)) { 157 157 command_index = i; 158 158 } 159 159 } 160 160 ///ystem.err.println("Command index is: " + command_index); … … 163 163 ///ystem.err.println("Searching before the target command."); 164 164 while(preceeding_index >= 0) { 165 166 167 165 matching_elements = document_element.getElementsByTagName(COMMAND_ORDER[preceeding_index]); 166 // If we've found a match 167 if(matching_elements.getLength() > 0) { 168 168 // We add after the last element 169 169 Element matched_element = (Element) matching_elements.item(matching_elements.getLength() - 1); … … 171 171 Node sibling_element = matched_element.getNextSibling(); 172 172 if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) { 173 174 173 Element newline_element = document.createElement(NEWLINE_ELEMENT); 174 document_element.insertBefore(newline_element, sibling_element); 175 175 } 176 176 return sibling_element; // Note that this may be null 177 178 177 } 178 preceeding_index--; 179 179 } 180 180 // If all that fails, we now move backwards through the commands … … 182 182 ///ystem.err.println("Searching after the target command."); 183 183 while(susceeding_index < COMMAND_ORDER.length) { 184 185 186 184 matching_elements = document_element.getElementsByTagName(COMMAND_ORDER[susceeding_index]); 185 // If we've found a match 186 if(matching_elements.getLength() > 0) { 187 187 // We add before the first element 188 188 Element matched_element = (Element) matching_elements.item(0); … … 190 190 Node sibling_element = matched_element.getPreviousSibling(); 191 191 if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) { 192 193 192 Element newline_element = document.createElement(NEWLINE_ELEMENT); 193 document_element.insertBefore(newline_element, sibling_element); 194 194 } 195 195 return sibling_element; // Note that this may be null 196 197 196 } 197 susceeding_index++; 198 198 } 199 199 // Well. Apparently there are no other commands in this collection configuration. So append away... 200 200 return null; 201 202 203 201 } 202 203 static public String toString(Element command_element, boolean show_extracted_namespace) { 204 204 String command_element_name = command_element.getNodeName(); 205 205 if(command_element_name.equals(CLASSIFY_ELEMENT)) { 206 206 return self.classifyToString(command_element, show_extracted_namespace); 207 207 } 208 208 else if(command_element_name.equals(FORMAT_ELEMENT)) { 209 209 return self.formatToString(command_element, show_extracted_namespace); 210 210 } 211 211 else if(command_element_name.equals(INDEXES_ELEMENT)) { 212 212 return self.indexesToString(command_element, show_extracted_namespace); 213 213 } 214 214 else if(command_element_name.equals(INDEX_DEFAULT_ELEMENT)) { 215 215 return self.indexDefaultToString(command_element, show_extracted_namespace); 216 216 } 217 217 else if(command_element_name.equals(LANGUAGES_ELEMENT)) { 218 218 return self.languagesToString(command_element); 219 219 } 220 220 else if(command_element_name.equals(LANGUAGE_DEFAULT_ELEMENT)) { 221 221 return self.languageDefaultToString(command_element); 222 222 } 223 223 else if(command_element_name.equals(LEVELS_ELEMENT)) { 224 224 return self.levelsToString(command_element); 225 225 } 226 226 else if(command_element_name.equals(COLLECTIONMETADATA_ELEMENT)) { 227 227 return self.metadataToString(command_element, show_extracted_namespace); 228 228 } 229 229 else if(command_element_name.equals(COLLECTIONMETADATA_CREATOR_ELEMENT)) { 230 230 return self.metadataToString(command_element, show_extracted_namespace); 231 231 } 232 232 else if(command_element_name.equals(COLLECTIONMETADATA_MAINTAINER_ELEMENT)) { 233 233 return self.metadataToString(command_element, show_extracted_namespace); 234 234 } 235 235 else if(command_element_name.equals(COLLECTIONMETADATA_PUBLIC_ELEMENT)) { 236 236 return self.metadataToString(command_element, show_extracted_namespace); 237 237 } 238 238 else if(command_element_name.equals(COLLECTIONMETADATA_BETA_ELEMENT)) { 239 239 return self.metadataToString(command_element, show_extracted_namespace); 240 240 } 241 241 else if(command_element_name.equals(PLUGIN_ELEMENT)) { 242 242 return self.pluginToString(command_element, show_extracted_namespace); 243 243 } 244 244 else if(command_element_name.equals(SEARCHTYPE_ELEMENT)) { 245 245 return self.searchtypeToString(command_element); 246 246 } 247 247 else if(command_element_name.equals(SUBCOLLECTION_ELEMENT)) { 248 248 return self.subcollectionToString(command_element, show_extracted_namespace); 249 249 } 250 250 else if(command_element_name.equals(SUBCOLLECTION_DEFAULT_INDEX_ELEMENT)) { 251 251 return self.subcollectionDefaultIndexToString(command_element); 252 252 } 253 253 else if(command_element_name.equals(SUBCOLLECTION_INDEXES_ELEMENT)) { 254 254 return self.subcollectionIndexesToString(command_element); 255 255 } 256 256 else if(command_element_name.equals(SUPERCOLLECTION_ELEMENT)) { 257 257 return self.supercollectionToString(command_element); 258 258 } 259 259 else if(command_element_name.equals(UNKNOWN_ELEMENT)) { 260 260 return self.unknownToString(command_element); 261 261 } 262 262 return ""; 263 264 265 266 267 268 269 263 } 264 265 /** Parses arguments from a tokenizer and returns a HashMap of mappings. The tricky bit here is that not all entries in the HashMap are name->value pairs, as some arguments are boolean and are turned on by their presence. Arguments are denoted by a '-' prefix. 266 * @param tokenizer a CommandTokenizer based on the unconsumed portion of a command string 267 * @return a HashMap containing the arguments parsed 268 */ 269 static public HashMap parseArguments(CommandTokenizer tokenizer) { 270 270 HashMap arguments = new HashMap(); 271 271 String name = null; 272 272 String value = null; 273 273 while(tokenizer.hasMoreTokens() || name != null) { 274 275 274 // First we retrieve a name if we need one. 275 if(name == null) { 276 276 name = tokenizer.nextToken(); 277 278 279 277 } 278 // Now we attempt to retrieve a value 279 if(tokenizer.hasMoreTokens()) { 280 280 value = tokenizer.nextToken(); 281 281 // Test if the value is actually a name, and if so add the name by itself, then put value into name so that it is parsed correctly during the next loop. 282 282 if(value.startsWith(StaticStrings.MINUS_CHARACTER)) { 283 284 283 arguments.put(name, null); 284 name = value; 285 285 } 286 286 // Otherwise we have a typical name->value pair ready to go 287 287 else { 288 289 290 } 291 292 293 288 arguments.put(name, value); 289 name = null; 290 } 291 } 292 // Otherwise its a binary flag 293 else { 294 294 arguments.put(name, null); 295 295 name = null; 296 296 } 297 297 } 298 298 return arguments; 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 299 } 300 301 static private ArrayList known_metadata; 302 303 static private CollectionConfiguration self; 304 305 static final private String EXTRACTED_PREFIX = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP; 306 /** Gives the preferred ordering of commands */ 307 static final private String[] COMMAND_ORDER = {StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, StaticStrings.COLLECTIONMETADATA_BETA_ELEMENT, StaticStrings.SEARCHTYPE_ELEMENT, StaticStrings.PLUGIN_ELEMENT, StaticStrings.INDEXES_ELEMENT, StaticStrings.LEVELS_ELEMENT, StaticStrings.INDEX_DEFAULT_ELEMENT, StaticStrings.LANGUAGES_ELEMENT, StaticStrings.LANGUAGE_DEFAULT_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}; 308 309 /** ************************** Public Data Members ***************************/ 310 311 /** ************************** Private Data Members ***************************/ 312 313 private File collect_config_file; 314 315 /** ************************** Public Methods ***************************/ 316 317 public CollectionConfiguration(File collect_config_file) { 318 318 this.self = this; 319 319 this.collect_config_file = collect_config_file; … … 321 321 String collect_config_name = collect_config_file.getName(); 322 322 if(collect_config_name.equals(COLLECTCONFIGURATION_XML)) { 323 324 323 // Parse with Utility but don't use class loader 324 document = Utility.parse(collect_config_file, false); 325 325 } 326 326 // Otherwise if this is a legacy collect.cfg file then read in the template and send to magic parser 327 327 else if(collect_config_name.equals(COLLECT_CFG)) { 328 329 330 } 331 332 333 334 328 document = Utility.parse(PSEUDO_COLLECTCONFIGURATION_XML, true); 329 parse(collect_config_file); 330 } 331 } 332 333 /** This debug facility shows the currently loaded collect.cfg or CollectConfig.xml file as a DOM tree. */ 334 public void display() { 335 335 JDialog dialog = new JDialog(Gatherer.g_man, "Collection Configuration", false); 336 336 dialog.setSize(400,400); … … 340 340 refresh_button.addActionListener(new ActionListener() { 341 341 public void actionPerformed(ActionEvent event) { 342 343 } 344 342 tree.setDocument(document); 343 } 344 }); 345 345 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 346 346 content_pane.setLayout(new BorderLayout()); … … 348 348 content_pane.add(refresh_button, BorderLayout.SOUTH); 349 349 dialog.show(); 350 351 352 350 } 351 352 public Element getBeta() { 353 353 Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_BETA_ELEMENT, null, null); 354 354 element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_BETA_STR); 355 355 element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR); 356 356 return element; 357 358 359 357 } 358 359 public Element getCreator() { 360 360 Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_CREATOR_ELEMENT, null, null); 361 361 element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_CREATOR_STR); 362 362 element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR); 363 363 return element; 364 365 366 364 } 365 366 public Element getDocumentElement() { 367 367 return document.getDocumentElement(); 368 369 370 368 } 369 370 public File getFile() { 371 371 return collect_config_file; 372 373 374 375 372 } 373 374 /** Retrieve or create the languages Element. */ 375 public Element getLanguages() { 376 376 return getOrCreateElementByTagName(LANGUAGES_ELEMENT, null, null); 377 378 379 377 } 378 379 public Element getLevels() { 380 380 return getOrCreateElementByTagName(LEVELS_ELEMENT, null, null); 381 382 383 381 } 382 383 public Element getMaintainer() { 384 384 Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_MAINTAINER_ELEMENT, null, null); 385 385 element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_MAINTAINER_STR); 386 386 element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR); 387 387 return element; 388 389 390 391 388 } 389 390 /** 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. */ 391 public Element getMGIndexes() { 392 392 return getOrCreateElementByTagName(INDEXES_ELEMENT, MGPP_ATTRIBUTE, FALSE_STR); 393 394 395 393 } 394 395 public Element getMGPPIndexes() { 396 396 return getOrCreateElementByTagName(INDEXES_ELEMENT, MGPP_ATTRIBUTE, TRUE_STR); 397 398 399 397 } 398 399 public Element getPublic() { 400 400 Element element = getOrCreateElementByTagName(COLLECTIONMETADATA_PUBLIC_ELEMENT, null, null); 401 401 element.setAttribute(NAME_ATTRIBUTE, COLLECTIONMETADATA_PUBLIC_STR); 402 402 element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR); 403 403 return element; 404 405 406 407 404 } 405 406 /** Retrieve or create the searchtype element. */ 407 public Element getSearchType() { 408 408 ///ystem.err.println("Get or create element by tag name: " + name); 409 409 Element document_element = document.getDocumentElement(); … … 411 411 int elements_length = elements.getLength(); 412 412 if(elements_length > 0) { 413 414 413 document_element = null; 414 return (Element) elements.item(0); 415 415 } 416 416 // Create the element … … 418 418 Node target_node = findInsertionPoint(element); 419 419 if(target_node != null) { 420 420 document_element.insertBefore(element, target_node); 421 421 } 422 422 else { 423 423 document_element.appendChild(element); 424 424 } 425 425 document_element = null; … … 429 429 element.appendChild(a_searchtype_element); 430 430 return element; 431 432 433 434 431 } 432 433 /** Retrieve or create the subindexes Element. */ 434 public Element getSubIndexes() { 435 435 return getOrCreateElementByTagName(SUBCOLLECTION_INDEXES_ELEMENT, null, null); 436 437 438 439 436 } 437 438 /** Retrieve or create the supercollections Element. */ 439 public Element getSuperCollection() { 440 440 return getOrCreateElementByTagName(SUPERCOLLECTION_ELEMENT, null, null); 441 442 443 441 } 442 443 public boolean ready() { 444 444 return document != null; 445 446 447 445 } 446 447 public void save() { 448 448 save(false); 449 450 451 449 } 450 451 public void save(boolean force_xml) { 452 452 if(collect_config_file.exists()) { 453 454 455 453 File original_file = new File(collect_config_file.getParentFile(), COLLECT_CFG); 454 File backup_file = new File(collect_config_file.getParentFile(), "collect.bak"); 455 if(backup_file.exists()) { 456 456 backup_file.delete(); 457 458 457 } 458 if(!original_file.renameTo(backup_file)) { 459 459 Gatherer.println("Can't rename collect.cfg"); 460 460 } 461 461 } 462 462 if(force_xml || collect_config_file.getName().equals(COLLECTCONFIGURATION_XML)) { 463 464 463 ///ystem.err.println("Writing XML"); 464 Utility.export(document, new File(collect_config_file.getParentFile(), COLLECTCONFIGURATION_XML)); 465 465 } 466 466 else { 467 468 467 ///ystem.err.println("Writing text"); 468 try { 469 469 FileWriter file_writer = new FileWriter(collect_config_file, false); 470 470 BufferedWriter buffered_writer = new BufferedWriter(file_writer); … … 476 476 boolean just_wrote_newline = false; // Prevent two or more newlines in a row 477 477 for(int i = 0; i < command_elements.getLength(); i++) { 478 479 478 Node command_node = command_elements.item(i); 479 if(command_node instanceof Element) { 480 480 Element command_element = (Element) command_node; 481 481 // The only thing left are NewLine elements 482 482 if(command_element.getNodeName().equals(NEWLINE_ELEMENT) && !just_wrote_newline) { 483 484 483 buffered_writer.newLine(); 484 just_wrote_newline = true; 485 485 } 486 486 // Anything else we write to file, but only if it has been assigned, the exception being the Indexes element which just get commented if unassigned (a side effect of MG && MGPP compatibility) 487 487 else if(!command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR) || command_element.getNodeName().equals(INDEXES_ELEMENT) || command_element.getNodeName().equals(INDEX_DEFAULT_ELEMENT) || command_element.getNodeName().equals(LEVELS_ELEMENT)){ 488 489 488 String command = toString(command_element, false); 489 if(command != null && command.length() > 0) { 490 490 write(buffered_writer, command); 491 491 buffered_writer.newLine(); 492 492 just_wrote_newline = false; 493 494 } 495 493 } 494 } 495 } 496 496 } 497 497 buffered_writer.close(); 498 498 known_metadata = null; 499 500 499 } 500 catch (Exception exception) { 501 501 Gatherer.println("Error in CollectionConfiguration.save(boolean): " + exception); 502 502 Gatherer.printStackTrace(exception); 503 504 } 505 506 507 508 509 503 } 504 } 505 } 506 507 /** ************************** Private Methods ***************************/ 508 509 private String classifyToString(Element command_element, boolean show_extracted_namespace) { 510 510 StringBuffer text = new StringBuffer(CLASSIFY_STR); 511 511 text.append(TAB_CHARACTER); … … 515 515 int option_elements_length = option_elements.getLength(); 516 516 for(int j = 0; j < option_elements_length; j++) { 517 518 517 Element option_element = (Element) option_elements.item(j); 518 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) { 519 519 text.append(StaticStrings.MINUS_CHARACTER); 520 520 text.append(option_element.getAttribute(NAME_ATTRIBUTE)); 521 521 String value_str = MSMUtils.getValue(option_element); 522 522 if(value_str.length() > 0) { 523 524 523 // If the value happens to be the identifier of an extracted metadata element, then remove the namespace. 524 if(!show_extracted_namespace && value_str.startsWith(EXTRACTED_PREFIX)) { 525 525 value_str = value_str.substring(EXTRACTED_PREFIX.length()); 526 527 528 526 } 527 text.append(SPACE_CHARACTER); 528 if(value_str.indexOf(SPACE_CHARACTER) == -1) { 529 529 text.append(value_str); 530 531 530 } 531 else { 532 532 text.append(SPEECH_CHARACTER); 533 533 text.append(value_str); 534 534 text.append(SPEECH_CHARACTER); 535 535 } 536 536 } 537 537 value_str = null; 538 538 if(j < option_elements_length - 1) { 539 540 } 541 542 539 text.append(SPACE_CHARACTER); 540 } 541 } 542 option_element = null; 543 543 } 544 544 option_elements = null; 545 545 return text.toString(); 546 547 548 546 } 547 548 private String formatToString(Element command_element, boolean show_extracted_namespace) { 549 549 StringBuffer text = new StringBuffer(FORMAT_STR); 550 550 text.append(SPACE_CHARACTER); … … 553 553 String value_str = command_element.getAttribute(VALUE_ATTRIBUTE); 554 554 if(value_str.length() != 0) { 555 555 text.append(value_str); 556 556 } 557 557 else { … … 560 560 // Remove any references to a namespace for extracted metadata 561 561 if(!show_extracted_namespace) { 562 562 value_str.replaceAll(EXTRACTED_PREFIX, ""); 563 563 } 564 564 text.append(SPEECH_CHARACTER); … … 568 568 value_str = null; 569 569 return text.toString(); 570 571 572 573 570 } 571 572 /** Retrieve or create the indexes Element. */ 573 private Element getOrCreateElementByTagName(String name, String conditional_attribute, String required_value) { 574 574 Element document_element = document.getDocumentElement(); 575 575 NodeList elements = document_element.getElementsByTagName(name); 576 576 int elements_length = elements.getLength(); 577 577 if(elements_length > 0) { 578 578 if(conditional_attribute == null) { 579 579 document_element = null; 580 580 return (Element) elements.item(0); 581 582 581 } 582 else { 583 583 for(int i = 0; i < elements_length; i++) { 584 585 584 Element element = (Element) elements.item(i); 585 if(element.getAttribute(conditional_attribute).equals(required_value)) { 586 586 document_element = null; 587 587 return element; 588 589 590 } 591 588 } 589 element = null; 590 } 591 } 592 592 } 593 593 // Create the element … … 595 595 // If there was a property set it 596 596 if(conditional_attribute != null) { 597 597 element.setAttribute(conditional_attribute, required_value); 598 598 } 599 599 Node target_node = findInsertionPoint(element); 600 600 if(target_node != null) { 601 601 document_element.insertBefore(element, target_node); 602 602 } 603 603 else { 604 604 document_element.appendChild(element); 605 605 } 606 606 document_element = null; 607 607 return element; 608 609 610 608 } 609 610 private String indexesToString(Element command_element, boolean show_extracted_namespace) { 611 611 boolean comment_only = false; 612 612 StringBuffer text = new StringBuffer(""); 613 613 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR)) { 614 615 614 text.append("#"); 615 comment_only = true; 616 616 } 617 617 text.append(INDEX_STR); 618 618 text.append(TAB_CHARACTER); 619 619 if(!comment_only) { 620 620 text.append(TAB_CHARACTER); 621 621 } 622 622 NodeList index_elements = command_element.getElementsByTagName(INDEX_ELEMENT); 623 623 if (index_elements.getLength() == 0) { // no indexes 624 624 return ""; 625 625 } 626 626 // For each index, write its level, a colon, then concatenate its child content elements into a single comma separated list 627 627 int index_elements_length = index_elements.getLength(); 628 628 for(int j = 0; j < index_elements_length; j++) { 629 630 631 629 Element index_element = (Element) index_elements.item(j); 630 String level_str = index_element.getAttribute(LEVEL_ATTRIBUTE); 631 if(level_str.length() > 0) { 632 632 text.append(level_str); 633 633 text.append(StaticStrings.COLON_CHARACTER); 634 635 636 637 638 634 } 635 NodeList content_elements = index_element.getElementsByTagName(CONTENT_ELEMENT); 636 int content_elements_length = content_elements.getLength(); 637 // Don't output anything if no indexes are set 638 if(content_elements_length == 0) { 639 639 return null; 640 641 640 } 641 for(int k = 0; k < content_elements_length; k++) { 642 642 Element content_element = (Element) content_elements.item(k); 643 643 String name_str = content_element.getAttribute(NAME_ATTRIBUTE); 644 644 if(!show_extracted_namespace && name_str.startsWith(EXTRACTED_PREFIX)) { 645 645 name_str = name_str.substring(EXTRACTED_PREFIX.length()); 646 646 } 647 647 text.append(name_str); 648 648 name_str = null; 649 649 if(k < content_elements_length - 1) { 650 650 text.append(StaticStrings.COMMA_CHARACTER); 651 651 } 652 652 content_element = null; 653 654 653 } 654 if(j < index_elements_length - 1) { 655 655 text.append(SPACE_CHARACTER); 656 657 658 656 } 657 content_elements = null; 658 index_element = null; 659 659 } 660 660 index_elements = null; 661 661 return text.toString(); 662 663 664 662 } 663 664 private String indexDefaultToString(Element command_element, boolean show_extracted_namespace) { 665 665 StringBuffer text = new StringBuffer(""); 666 666 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(FALSE_STR)) { 667 667 text.append("#"); 668 668 } 669 669 text.append(INDEX_DEFAULT_STR); … … 674 674 int content_elements_length = content_elements.getLength(); 675 675 for(int j = 0; j < content_elements_length; j++) { 676 677 678 676 Element content_element = (Element) content_elements.item(j); 677 String name_str = content_element.getAttribute(NAME_ATTRIBUTE); 678 if(!show_extracted_namespace && name_str.startsWith(EXTRACTED_PREFIX)) { 679 679 name_str = name_str.substring(EXTRACTED_PREFIX.length()); 680 681 682 683 680 } 681 text.append(name_str); 682 name_str = null; 683 if(j < content_elements_length - 1) { 684 684 text.append(StaticStrings.COMMA_CHARACTER); 685 686 685 } 686 content_element = null; 687 687 } 688 688 content_elements = null; 689 689 return text.toString(); 690 691 692 690 } 691 692 private String languagesToString(Element command_element) { 693 693 StringBuffer text = new StringBuffer(LANGUAGES_STR); 694 694 text.append(TAB_CHARACTER); … … 697 697 int language_elements_length = language_elements.getLength(); 698 698 if(language_elements_length == 0) { 699 699 return null; 700 700 } 701 701 for(int j = 0; j < language_elements_length; j++) { 702 703 704 702 Element language_element = (Element) language_elements.item(j); 703 text.append(language_element.getAttribute(NAME_ATTRIBUTE)); 704 if(j < language_elements_length - 1) { 705 705 text.append(SPACE_CHARACTER); 706 706 } 707 707 } 708 708 return text.toString(); 709 710 711 709 } 710 711 private String languageDefaultToString(Element command_element) { 712 712 StringBuffer text = new StringBuffer(LANGUAGE_DEFAULT_STR); 713 713 text.append(TAB_CHARACTER); 714 714 text.append(command_element.getAttribute(NAME_ATTRIBUTE)); 715 715 return text.toString(); 716 717 718 716 } 717 718 private String levelsToString(Element command_element) { 719 719 StringBuffer text = new StringBuffer(""); 720 720 if(!command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) { 721 721 text.append("#"); 722 722 } 723 723 text.append(LEVELS_STR); … … 728 728 // Don't output anything if no levels are set. 729 729 if(content_elements_length == 0) { 730 730 return null; 731 731 } 732 732 for(int i = 0; i < content_elements_length; i++) { 733 734 735 733 Element content_element = (Element) content_elements.item(i); 734 text.append(content_element.getAttribute(NAME_ATTRIBUTE)); 735 text.append(SPACE_CHARACTER); 736 736 } 737 737 return text.substring(0, text.length() - 1); 738 739 740 738 } 739 740 static public String metadataToString(Element command_element, boolean text_value) { 741 741 boolean special = false; 742 742 // If there is no value attribute, then we don't write anything … … 745 745 // If the name is one of the special four, we don't write the collectionmeta first. Note the maintainer collectionmeta is singled out for 'prittying' reasons. 746 746 if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) { 747 748 749 747 text.append(name_str); 748 text.append(TAB_CHARACTER); 749 special = true; 750 750 } 751 751 else if(name_str.equals(COLLECTIONMETADATA_BETA_STR) || name_str.equals(COLLECTIONMETADATA_CREATOR_STR) || name_str.equals(COLLECTIONMETADATA_PUBLIC_STR)) { 752 753 754 755 752 text.append(name_str); 753 text.append(TAB_CHARACTER); 754 text.append(TAB_CHARACTER); 755 special = true; 756 756 } 757 757 else { 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 758 text.append(COLLECTIONMETADATA_STR); 759 text.append(TAB_CHARACTER); 760 text.append(name_str); 761 text.append(SPACE_CHARACTER); 762 String language_str = command_element.getAttribute(LANGUAGE_ATTRIBUTE); 763 // If this is element is in english, and it is the first one found, we don't need to write the language argument. 764 //if(!language_str.equals(ENGLISH_LANGUAGE_STR) || known_metadata == null || known_metadata.contains(name_str)) { 765 // changed so that we always write the language string 766 text.append(LBRACKET_CHARACTER); 767 text.append(LANGUAGE_ARGUMENT); 768 text.append(language_str); 769 text.append(RBRACKET_CHARACTER); 770 text.append(SPACE_CHARACTER); 771 //} 772 if(known_metadata != null) { 773 773 known_metadata.add(name_str); 774 775 774 } 775 language_str = null; 776 776 } 777 777 name_str = null; 778 778 779 779 String value_str = MSMUtils.getValue(command_element); 780 780 // The value string we retrieved will be encoded for xml, so we now decode it - to text if text_value set. This parameter was originally show_extracted_namespace, but sincethis is only true for 'toString()' commands from within the CDM, its good enough to determine if this toString() will be used to display on screen, or write to collect.cfg 781 781 if(text_value == CollectionMeta.TEXT) { 782 782 value_str = Codec.transform(value_str, Codec.DOM_TO_TEXT); 783 783 } 784 784 else { 785 786 } 787 785 value_str = Codec.transform(value_str, Codec.DOM_TO_GREENSTONE); 786 } 787 788 788 // We don't wrap the email addresses in quotes, nor the other special metadata 789 789 if(special) { 790 790 text.append(value_str); 791 791 } 792 792 else { 793 794 795 793 text.append(SPEECH_CHARACTER); 794 text.append(value_str); 795 text.append(SPEECH_CHARACTER); 796 796 } 797 797 value_str = null; 798 798 return text.toString(); 799 } 800 801 /** Parse a collect.cfg into a DOM model representation. */ 802 private void parse(File collect_config_file) { 803 try { 804 Element collect_cfg_element = document.getDocumentElement(); 805 // Read in the file one command at a time. 806 FileReader in_reader = new FileReader(collect_config_file); 807 BufferedReader in = new BufferedReader(in_reader); 808 String command_str = null; 809 while((command_str = in.readLine()) != null) { 810 Element command_element = null; 811 // A command may be broken over several lines. 812 command_str = command_str.trim(); 813 boolean eof = false; 814 while(!eof && command_str.endsWith(NEWLINE_CHARACTER)) { 815 String next_line = in.readLine(); 816 if(next_line != null) { 817 next_line = next_line.trim(); 818 if(next_line.length() > 0) { 819 // Remove the new line character 820 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER)); 821 // And append the next line, which due to the test above must be non-zero length 822 command_str = command_str + next_line; 823 } 824 next_line = null; 825 } 826 // If we've reached the end of the file theres nothing more we can do 827 else { 828 eof = true; 829 } 830 } 831 // If there is still a new line character, then we remove it and hope for the best 832 if(command_str.endsWith(NEWLINE_CHARACTER)) { 833 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER)); 834 } 835 // Now we've either got a command to parse... 836 if(command_str.length() != 0) { 837 // Start trying to figure out what it is 838 StringTokenizer tokenizer = new StringTokenizer(command_str); 839 String command_type = tokenizer.nextToken().toLowerCase(); 840 tokenizer = null; 841 // Why can't you switch on strings eh? We pass it to the various subparsers who each have a bash at parsing the command. If none can parse the command, an unknown element is created 842 if(command_element == null && command_type.equals(CLASSIFY_STR)) { 843 command_element = parseClassify(command_str); 844 } 845 if(command_element == null && command_type.equals(FORMAT_STR)) { 846 command_element = parseFormat(command_str, in); 847 } 848 if(command_element == null && (command_type.equals(INDEX_STR) || command_type.equals(COMMENTED_INDEXES_STR))) { 849 command_element = parseIndex(command_str); 850 } 851 if(command_element == null && (command_type.equals(INDEX_DEFAULT_STR) || command_type.equals(COMMENTED_INDEX_DEFAULT_STR))) { 852 command_element = parseIndexDefault(command_str); 853 } 854 if(command_element == null && command_type.equals(LANGUAGES_STR)) { 855 command_element = parseLanguage(command_str); 856 } 857 if(command_element == null && command_type.equals(LANGUAGE_DEFAULT_STR)) { 858 command_element = parseLanguageDefault(command_str); 859 } 860 if(command_element == null && (command_type.equals(LEVELS_STR) || command_type.equals(COMMENTED_LEVELS_STR))) { 861 command_element = parseLevels(command_str); 862 } 863 if(command_element == null && command_type.equals(COLLECTIONMETADATA_STR)) { 864 // collectionmeta may go over more than one line, so 865 // pass in the reader 866 command_element = parseMetadata(command_str, in); 867 } 868 if(command_element == null && (command_type.equals(COLLECTIONMETADATA_BETA_STR) || command_type.equals(COLLECTIONMETADATA_PUBLIC_STR) || command_type.equals(COLLECTIONMETADATA_CREATOR_STR) || command_type.equals(COLLECTIONMETADATA_MAINTAINER_STR))) { 869 command_element = parseMetadataSpecial(command_str); 870 } 871 if(command_element == null && command_type.equals(PLUGIN_STR)) { 872 command_element = parsePlugIn(command_str); 873 } 874 if(command_element == null && command_type.equals(SEARCHTYPE_STR)) { 875 command_element = parseSearchType(command_str); 876 } 877 if(command_element == null && command_type.equals(SUBCOLLECTION_STR)) { 878 command_element = parseSubCollection(command_str); 879 } 880 if(command_element == null && command_type.equals(SUBCOLLECTION_DEFAULT_INDEX_STR)) { 881 command_element = parseSubCollectionDefaultIndex(command_str); 882 } 883 if(command_element == null && command_type.equals(SUBCOLLECTION_INDEX_STR)) { 884 command_element = parseSubCollectionIndex(command_str); 885 } 886 if(command_element == null && (command_type.equals(SUPERCOLLECTION_STR) || command_type.equals(CCS_STR))) { 887 command_element = parseSuperCollection(command_str); 888 } 889 // Doesn't match any known type 890 command_type = null; 891 if(command_element == null) { 799 } 800 801 /** Parse a collect.cfg into a DOM model representation. */ 802 private void parse(File collect_config_file) { 803 try { 804 Element collect_cfg_element = document.getDocumentElement(); 805 // Read in the file one command at a time. 806 FileReader in_reader = new FileReader(collect_config_file); 807 BufferedReader in = new BufferedReader(in_reader); 808 String command_str = null; 809 while((command_str = in.readLine()) != null) { 810 Element command_element = null; 811 // A command may be broken over several lines. 812 command_str = command_str.trim(); 813 boolean eof = false; 814 while(!eof && command_str.endsWith(NEWLINE_CHARACTER)) { 815 String next_line = in.readLine(); 816 if(next_line != null) { 817 next_line = next_line.trim(); 818 if(next_line.length() > 0) { 819 // Remove the new line character 820 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER)); 821 // And append the next line, which due to the test above must be non-zero length 822 command_str = command_str + next_line; 823 } 824 next_line = null; 825 } 826 // If we've reached the end of the file theres nothing more we can do 827 else { 828 eof = true; 829 } 830 } 831 // If there is still a new line character, then we remove it and hope for the best 832 if(command_str.endsWith(NEWLINE_CHARACTER)) { 833 command_str = command_str.substring(0, command_str.lastIndexOf(NEWLINE_CHARACTER)); 834 } 835 // Now we've either got a command to parse... 836 if(command_str.length() != 0) { 837 // Start trying to figure out what it is 838 //StringTokenizer tokenizer = new StringTokenizer(command_str); 839 // Instead of a standard string tokenizer I'm going to use the new version of CommandTokenizer, which is not only smart enough to correctly notice speech marks and correctly parse them out, but now also takes the input stream so it can rebuild tokens that stretch over several lines. 840 CommandTokenizer tokenizer = new CommandTokenizer(command_str, in); 841 String command_type = tokenizer.nextToken().toLowerCase(); 842 // Why can't you switch on strings eh? We pass it to the various subparsers who each have a bash at parsing the command. If none can parse the command, an unknown element is created 843 if(command_element == null && command_type.equals(CLASSIFY_STR)) { 844 command_element = parseClassify(command_str); 845 } 846 if(command_element == null && command_type.equals(FORMAT_STR)) { 847 command_element = parseFormat(tokenizer); // Revised to handle multiple lines 848 } 849 if(command_element == null && (command_type.equals(INDEX_STR) || command_type.equals(COMMENTED_INDEXES_STR))) { 850 command_element = parseIndex(command_str); 851 } 852 if(command_element == null && (command_type.equals(INDEX_DEFAULT_STR) || command_type.equals(COMMENTED_INDEX_DEFAULT_STR))) { 853 command_element = parseIndexDefault(command_str); 854 } 855 if(command_element == null && command_type.equals(LANGUAGES_STR)) { 856 command_element = parseLanguage(command_str); 857 } 858 if(command_element == null && command_type.equals(LANGUAGE_DEFAULT_STR)) { 859 command_element = parseLanguageDefault(command_str); 860 } 861 if(command_element == null && (command_type.equals(LEVELS_STR) || command_type.equals(COMMENTED_LEVELS_STR))) { 862 command_element = parseLevels(command_str); 863 } 864 if(command_element == null && command_type.equals(COLLECTIONMETADATA_STR)) { 865 command_element = parseMetadata(tokenizer); // Revised to handle multiple lines 866 } 867 if(command_element == null && (command_type.equals(COLLECTIONMETADATA_BETA_STR) || command_type.equals(COLLECTIONMETADATA_PUBLIC_STR) || command_type.equals(COLLECTIONMETADATA_CREATOR_STR) || command_type.equals(COLLECTIONMETADATA_MAINTAINER_STR))) { 868 command_element = parseMetadataSpecial(command_str); 869 } 870 if(command_element == null && command_type.equals(PLUGIN_STR)) { 871 command_element = parsePlugIn(command_str); 872 } 873 if(command_element == null && command_type.equals(SEARCHTYPE_STR)) { 874 command_element = parseSearchType(command_str); 875 } 876 if(command_element == null && command_type.equals(SUBCOLLECTION_STR)) { 877 command_element = parseSubCollection(command_str); 878 } 879 if(command_element == null && command_type.equals(SUBCOLLECTION_DEFAULT_INDEX_STR)) { 880 command_element = parseSubCollectionDefaultIndex(command_str); 881 } 882 if(command_element == null && command_type.equals(SUBCOLLECTION_INDEX_STR)) { 883 command_element = parseSubCollectionIndex(command_str); 884 } 885 if(command_element == null && (command_type.equals(SUPERCOLLECTION_STR) || command_type.equals(CCS_STR))) { 886 command_element = parseSuperCollection(command_str); 887 } 888 // Doesn't match any known type 889 command_type = null; 890 if(command_element == null) { 892 891 // No-one knows what to do with this command, so we create an Unknown command element 893 892 command_element = document.createElement(UNKNOWN_ELEMENT); … … 897 896 // Or an empty line to remember for later 898 897 else { 899 898 command_element = document.createElement(NEWLINE_ELEMENT); 900 899 } 901 900 // Now command element shouldn't be null so we append it to the collection config DOM 902 901 collect_cfg_element.appendChild(command_element); 903 902 } 904 903 } 905 904 catch(Exception exception) { 906 907 908 } 909 910 911 905 Gatherer.println("Error in CollectionConfiguration.parse(java.io.File): " + exception); 906 Gatherer.printStackTrace(exception); 907 } 908 } 909 910 private Element parseClassify(String command_str) { 912 911 Element command_element = null; 913 912 try { 914 915 916 913 CommandTokenizer tokenizer = new CommandTokenizer(command_str); 914 // Check the token count. The token count from a command tokenizer isn't guarenteed to be correct, but it does give the maximum number of available tokens according to the underlying StringTokenizer (some of which may actually be append together by the CommandTokenizer as being a single argument). 915 if(tokenizer.countTokens() >= 2) { // Must support "classify Phind" (no args) 917 916 command_element = document.createElement(CLASSIFY_ELEMENT); 918 917 // First token is classify … … 925 924 Iterator names = arguments.keySet().iterator(); 926 925 while(names.hasNext()) { 927 928 929 930 926 String name = (String) names.next(); 927 String value = (String) arguments.get(name); // Can be null 928 // The metadata argument gets added as the content attribute 929 if(name.equals(METADATA_ARGUMENT) && value != null) { 931 930 // The metadata argument must be the fully qualified name of a metadata element, so if it doesn't yet have a namespace, append the extracted metadata namespace. 932 931 if(value.indexOf(MSMUtils.NS_SEP) == -1) { 933 932 value = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + value; 934 933 } 935 934 //command_element.setAttribute(CONTENT_ATTRIBUTE, value); 936 937 938 939 940 935 } 936 // Everything else is an Option Element 937 Element option_element = document.createElement(OPTION_ELEMENT); 938 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1)); 939 if(value != null) { 941 940 // Remove any speech marks appended in strings containing whitespace 942 941 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) { 943 942 value = value.substring(1, value.length() - 1); 944 943 } 945 944 MSMUtils.setValue(option_element, value); 946 947 948 949 950 951 952 945 } 946 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR); 947 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR); 948 command_element.appendChild(option_element); 949 option_element = null; 950 name = null; 951 value = null; 953 952 } 954 953 names = null; 955 954 arguments = null; 956 957 955 } 956 tokenizer = null; 958 957 } 959 958 catch(Exception error) { 960 959 } 961 960 return command_element; 962 } 963 964 private Element parseFormat(String command_str, BufferedReader in) { 961 } 962 963 private Element parseFormat(CommandTokenizer tokenizer) { 964 Element command_element = null; 965 try { 966 command_element = document.createElement(FORMAT_ELEMENT); 967 String name_str = tokenizer.nextToken(); 968 String value_str = tokenizer.nextToken(); 969 if(name_str != null && value_str != null) { 970 command_element.setAttribute(NAME_ATTRIBUTE, name_str); 971 // If the value is true or false we add it as an attribute 972 if(value_str.equalsIgnoreCase(TRUE_STR) || value_str.equalsIgnoreCase(FALSE_STR)) { 973 command_element.setAttribute(VALUE_ATTRIBUTE, value_str.toLowerCase()); 974 } 975 // Otherwise it gets added as a text node 976 else { 977 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value 978 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM); 979 MSMUtils.setValue(command_element, value_str); 980 } 981 } 982 else { 983 command_element = null; 984 } 985 name_str = null; 986 value_str = null; 987 } 988 catch (Exception exception) { 989 Gatherer.printStackTrace(exception); 990 command_element = null; 991 } 992 return command_element; 993 } 994 995 private Element parseIndex(String command_str) { 965 996 Element command_element = null; 966 997 try { 967 CommandTokenizer tokenizer = new CommandTokenizer(command_str); 968 if(tokenizer.countTokens() >= 3) { 969 command_element = document.createElement(FORMAT_ELEMENT); 970 // First token is format 971 tokenizer.nextToken(); 972 command_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken()); 973 String value_str = tokenizer.nextToken(); 974 // If the value is true or false we add it as an attribute 975 if(value_str.equalsIgnoreCase(TRUE_STR) || value_str.equalsIgnoreCase(FALSE_STR)) { 976 command_element.setAttribute(VALUE_ATTRIBUTE, value_str.toLowerCase()); 977 } 978 // Otherwise it gets added as a text node 979 else { 980 981 // now we need to handle the case where the value is enclosed in quotes (single or double) and may extend across multiple lines 982 String start_string = value_str.substring(0,1); 983 if (start_string.equals("\"") || start_string.equals("\'")) { 984 if (value_str.endsWith(start_string) && value_str.length()!=1) { 985 // we remove the quotes from the ends 986 value_str = value_str.substring(1, value_str.length() - 1); 987 } else { 988 989 // remove the first quote 990 StringBuffer value_raw = new StringBuffer(value_str.substring(1)); 991 // add the new line back in 992 value_raw.append(StaticStrings.NEW_LINE_CHAR); 993 int pos = value_raw.indexOf(start_string); 994 int old_pos = 0; 995 while (pos != -1 && value_raw.charAt(pos-1)=='\\') { 996 old_pos = pos+1; 997 pos = value_raw.indexOf(start_string, old_pos); 998 } 999 while(pos == -1) { 1000 String next_line = in.readLine(); 1001 if(next_line != null) { 1002 value_raw.append(next_line); 1003 value_raw.append(StaticStrings.NEW_LINE_CHAR); 1004 } 1005 next_line = null; 1006 pos = value_raw.indexOf(start_string, old_pos); 1007 while (pos != -1 && value_raw.charAt(pos-1)=='\\') { 1008 old_pos = pos+1; 1009 pos = value_raw.indexOf(start_string, old_pos); 1010 } 1011 } 1012 1013 value_str = value_raw.substring(0, value_raw.lastIndexOf(start_string)); 1014 value_raw = null; 1015 1016 } // else 1017 } // if starts with a quote 1018 1019 if(value_str != null) { 1020 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value 1021 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM); 1022 MSMUtils.setValue(command_element, value_str); 1023 } 1024 else { 1025 command_element = null; 1026 } 1027 start_string = null; 1028 } 1029 value_str = null; 1030 1031 } 1032 tokenizer = null; 1033 } 1034 catch (Exception exception) { 1035 } 1036 return command_element; 1037 } 1038 1039 private Element parseIndex(String command_str) { 1040 Element command_element = null; 1041 try { 1042 StringTokenizer tokenizer = new StringTokenizer(command_str); 1043 String command = tokenizer.nextToken(); 1044 command_element = document.createElement(INDEXES_ELEMENT); 1045 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(INDEX_STR) ? TRUE_STR : FALSE_STR)); 1046 command = null; 1047 if(!tokenizer.hasMoreTokens()) { 1048 998 StringTokenizer tokenizer = new StringTokenizer(command_str); 999 String command = tokenizer.nextToken(); 1000 command_element = document.createElement(INDEXES_ELEMENT); 1001 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(INDEX_STR) ? TRUE_STR : FALSE_STR)); 1002 command = null; 1003 if(!tokenizer.hasMoreTokens()) { 1004 1049 1005 // there are no indexes 1050 1006 command_element.setAttribute(ASSIGNED_ATTRIBUTE, FALSE_STR); … … 1052 1008 tokenizer = null; 1053 1009 return command_element; 1054 1055 1056 1010 } 1011 1012 while(tokenizer.hasMoreTokens()) { 1057 1013 Element index_element = document.createElement(INDEX_ELEMENT); 1058 1014 String index_str = tokenizer.nextToken(); … … 1060 1016 boolean old_index; 1061 1017 if(index_str.indexOf(COLON_CHARACTER) != -1) { 1062 1063 1064 1065 1018 old_index = true; 1019 index_element.setAttribute(LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER))); 1020 index_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1); 1021 command_element.setAttribute(MGPP_ATTRIBUTE, FALSE_STR); 1066 1022 } 1067 1023 else { 1068 1069 1024 command_element.setAttribute(MGPP_ATTRIBUTE, TRUE_STR); 1025 old_index = false; 1070 1026 } 1071 1027 StringTokenizer content_tokenizer = new StringTokenizer(index_str, StaticStrings.COMMA_CHARACTER); 1072 1028 while(content_tokenizer.hasMoreTokens()) { 1073 1074 1075 1076 1029 Element content_element = document.createElement(CONTENT_ELEMENT); 1030 String content_str = content_tokenizer.nextToken(); 1031 // Since the contents of indexes have to be certain keywords, or metadata elements, if the content isn't a keyword and doesn't yet have a namespace, append the extracted metadata namespace. 1032 if(content_str.indexOf(MSMUtils.NS_SEP) == -1) { 1077 1033 if(content_str.equals(StaticStrings.TEXT_STR) || (!old_index && content_str.equals(StaticStrings.ALLFIELDS_STR))) { 1078 1034 // Our special strings are OK. 1079 1035 } 1080 1036 else { 1081 1082 } 1083 1084 1085 1086 1037 content_str = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + content_str; 1038 } 1039 } 1040 content_element.setAttribute(NAME_ATTRIBUTE, content_str); 1041 index_element.appendChild(content_element); 1042 content_element = null; 1087 1043 } 1088 1044 content_tokenizer = null; … … 1090 1046 command_element.appendChild(index_element); 1091 1047 index_element = null; 1092 1093 1048 } 1049 tokenizer = null; 1094 1050 } 1095 1051 catch (Exception exception) { 1096 1052 exception.printStackTrace(); 1097 1053 } 1098 1054 return command_element; 1099 1100 1101 1055 } 1056 1057 private Element parseIndexDefault(String command_str) { 1102 1058 Element command_element = null; 1103 1059 try { 1104 1105 1060 StringTokenizer tokenizer = new StringTokenizer(command_str); 1061 if(tokenizer.countTokens() >= 2) { 1106 1062 command_element = document.createElement(INDEX_DEFAULT_ELEMENT); 1107 1063 command_element.setAttribute(ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken()).equals(INDEX_DEFAULT_STR) ? TRUE_STR : FALSE_STR)); … … 1111 1067 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER); 1112 1068 while(content_tokenizer.hasMoreTokens()) { 1113 1114 1115 1116 1069 Element content_element = document.createElement(CONTENT_ELEMENT); 1070 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken()); 1071 command_element.appendChild(content_element); 1072 content_element = null; 1117 1073 } 1118 1074 content_tokenizer = null; … … 1120 1076 content_str = null; 1121 1077 index_str = null; 1122 1123 1078 } 1079 tokenizer = null; 1124 1080 } 1125 1081 catch (Exception exception) { 1126 1082 } 1127 1083 return command_element; 1128 1129 1130 1084 } 1085 1086 private Element parseLanguage(String command_str) { 1131 1087 Element command_element = null; 1132 1088 try { 1133 1134 1135 1089 StringTokenizer tokenizer = new StringTokenizer(command_str); 1090 tokenizer.nextToken(); 1091 if(tokenizer.hasMoreTokens()) { 1136 1092 command_element = document.createElement(LANGUAGES_ELEMENT); 1137 1093 while(tokenizer.hasMoreTokens()) { 1138 1139 1140 1141 1142 } 1143 1144 1094 Element language_element = document.createElement(LANGUAGE_ELEMENT); 1095 language_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken()); 1096 command_element.appendChild(language_element); 1097 language_element = null; 1098 } 1099 } 1100 tokenizer = null; 1145 1101 } 1146 1102 catch (Exception exception) { 1147 1103 } 1148 1104 return command_element; 1149 1150 1151 1105 } 1106 1107 private Element parseLanguageDefault(String command_str) { 1152 1108 Element command_element = null; 1153 1109 try { 1154 1155 1110 StringTokenizer tokenizer = new StringTokenizer(command_str); 1111 if(tokenizer.countTokens() >= 2) { 1156 1112 command_element = document.createElement(LANGUAGE_DEFAULT_ELEMENT); 1157 1113 tokenizer.nextToken(); … … 1160 1116 command_element.setAttribute(ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR); 1161 1117 default_language_str = null; 1162 1163 1118 } 1119 tokenizer = null; 1164 1120 } 1165 1121 catch (Exception exception) { 1166 1122 } 1167 1123 return command_element; 1168 1169 1170 1124 } 1125 1126 private Element parseLevels(String command_str) { 1171 1127 Element command_element = null; 1172 1128 try { 1173 1174 1175 1176 1129 StringTokenizer tokenizer = new StringTokenizer(command_str); 1130 // First token is command type (levels) 1131 String command = tokenizer.nextToken(); 1132 if(tokenizer.hasMoreTokens()) { 1177 1133 command_element = document.createElement(LEVELS_ELEMENT); 1178 1134 command_element.setAttribute(ASSIGNED_ATTRIBUTE, (command.equals(LEVELS_STR) ? TRUE_STR : FALSE_STR)); 1179 1135 while(tokenizer.hasMoreTokens()) { 1180 1181 1182 1183 1184 } 1185 1186 1136 Element level_element = document.createElement(CONTENT_ELEMENT); 1137 level_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken()); 1138 command_element.appendChild(level_element); 1139 level_element = null; 1140 } 1141 } 1142 command = null; 1187 1143 } 1188 1144 catch(Exception exception) { 1189 1145 } 1190 1146 return command_element; 1191 } 1192 1193 private Element parseMetadata(String command_str, BufferedReader in) { 1147 } 1148 1149 private Element parseMetadata(CommandTokenizer tokenizer) { 1150 Element command_element = null; 1151 try { 1152 command_element = document.createElement(COLLECTIONMETADATA_ELEMENT); 1153 String name_str = tokenizer.nextToken(); 1154 String value_str = tokenizer.nextToken(); 1155 if(name_str != null && value_str != null) { 1156 String language_str = "en"; // By default - why do we assume English??? 1157 // Check if the value string is actually a language string 1158 if(value_str.startsWith(LBRACKET_CHARACTER) && value_str.endsWith(RBRACKET_CHARACTER)) { 1159 language_str = value_str.substring(value_str.indexOf(LANGUAGE_ARGUMENT) + 2, value_str.length() - 1); 1160 value_str = tokenizer.nextToken(); 1161 } 1162 if(value_str != null) { 1163 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value 1164 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM); 1165 command_element.setAttribute(NAME_ATTRIBUTE, name_str); 1166 command_element.setAttribute(LANGUAGE_ATTRIBUTE, language_str); 1167 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR); 1168 MSMUtils.setValue(command_element, value_str); 1169 } 1170 else { 1171 command_element = null; 1172 } 1173 language_str = null; 1174 } 1175 else { 1176 command_element = null; 1177 } 1178 name_str = null; 1179 value_str = null; 1180 } 1181 catch (Exception exception) { 1182 Gatherer.printStackTrace(exception); 1183 command_element = null; 1184 } 1185 return command_element; 1186 } 1187 1188 private Element parseMetadataSpecial(String command_str) { 1194 1189 Element command_element = null; 1195 1190 try { 1196 CommandTokenizer tokenizer = new CommandTokenizer(command_str); 1197 if(tokenizer.countTokens() >= 3) { 1198 command_element = document.createElement(COLLECTIONMETADATA_ELEMENT); 1199 // First token is command type 1200 tokenizer.nextToken(); 1201 String name_str = tokenizer.nextToken(); 1202 String value_str = tokenizer.nextToken(); 1203 String language_str = "en"; // By default - why do we assume English??? 1204 // Check if the value string is actually a language string 1205 if(value_str.startsWith(LBRACKET_CHARACTER) && value_str.endsWith(RBRACKET_CHARACTER)) { 1206 language_str = value_str.substring(value_str.indexOf(LANGUAGE_ARGUMENT) + 2, value_str.length() - 1); 1207 value_str = tokenizer.nextToken(); 1208 } 1209 1210 // now we need to handle the case where the value is enclosed in quotes (single or double) and may extend across multiple lines 1211 String start_string = value_str.substring(0,1); 1212 if (start_string.equals("\"") || start_string.equals("\'")) { 1213 1214 if (value_str.endsWith(start_string) && value_str.length()!=1) { 1215 // we remove the quotes from the ends 1216 value_str = value_str.substring(1, value_str.length() - 1); 1217 } else { 1218 1219 // remove the first quote 1220 StringBuffer value_raw = new StringBuffer(value_str.substring(1)); 1221 // add the new line back in 1222 value_raw.append(StaticStrings.NEW_LINE_CHAR); 1223 1224 int pos = value_raw.indexOf(start_string); 1225 int old_pos = 0; 1226 while (pos != -1 && value_raw.charAt(pos-1)=='\\') { 1227 old_pos = pos+1; 1228 pos = value_raw.indexOf(start_string, old_pos); 1229 } 1230 while(pos == -1) { 1231 String next_line = in.readLine(); 1232 if(next_line != null) { 1233 value_raw.append(next_line); 1234 value_raw.append(StaticStrings.NEW_LINE_CHAR); 1235 } 1236 next_line = null; 1237 pos = value_raw.indexOf(start_string, old_pos); 1238 while (pos != -1 && value_raw.charAt(pos-1)=='\\') { 1239 old_pos = pos+1; 1240 pos = value_raw.indexOf(start_string, old_pos); 1241 } 1242 } 1243 1244 value_str = value_raw.substring(0, value_raw.lastIndexOf(start_string)); 1245 value_raw = null; 1246 1247 } // else 1248 } // if starts with a quote 1249 1250 if(value_str != null) { 1251 // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value 1252 value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM); 1253 command_element.setAttribute(NAME_ATTRIBUTE, name_str); 1254 command_element.setAttribute(LANGUAGE_ATTRIBUTE, language_str); 1255 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR); 1256 MSMUtils.setValue(command_element, value_str); 1257 } 1258 else { 1259 command_element = null; 1260 } 1261 language_str = null; 1262 value_str = null; 1263 name_str = null; 1264 } 1265 tokenizer = null; 1266 } 1267 catch (Exception exception) { 1268 } 1269 return command_element; 1270 } 1271 1272 private Element parseMetadataSpecial(String command_str) { 1273 Element command_element = null; 1274 try { 1275 StringTokenizer tokenizer = new StringTokenizer(command_str); 1276 if(tokenizer.countTokens() >= 2) { 1191 StringTokenizer tokenizer = new StringTokenizer(command_str); 1192 if(tokenizer.countTokens() >= 2) { 1277 1193 String name_str = tokenizer.nextToken(); 1278 1194 String value_str = tokenizer.nextToken(); 1279 1195 if(name_str.equals(COLLECTIONMETADATA_BETA_STR)) { 1280 1196 command_element = document.createElement(COLLECTIONMETADATA_BETA_ELEMENT); 1281 1197 } 1282 1198 else if(name_str.equals(COLLECTIONMETADATA_CREATOR_STR)) { 1283 1199 command_element = document.createElement(COLLECTIONMETADATA_CREATOR_ELEMENT); 1284 1200 } 1285 1201 else if(name_str.equals(COLLECTIONMETADATA_MAINTAINER_STR)) { 1286 1202 command_element = document.createElement(COLLECTIONMETADATA_MAINTAINER_ELEMENT); 1287 1203 } 1288 1204 else if(name_str.equals(COLLECTIONMETADATA_PUBLIC_STR)) { 1289 1205 command_element = document.createElement(COLLECTIONMETADATA_PUBLIC_ELEMENT); 1290 1206 } 1291 1207 if(command_element != null) { 1292 1293 1294 1295 1296 1208 command_element.setAttribute(NAME_ATTRIBUTE, name_str); 1209 command_element.setAttribute(LANGUAGE_ATTRIBUTE, ENGLISH_LANGUAGE_STR); 1210 command_element.setAttribute(SPECIAL_ATTRIBUTE, TRUE_STR); 1211 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR); 1212 if(value_str.startsWith(SPEECH_CHARACTER) && value_str.endsWith(SPEECH_CHARACTER)) { 1297 1213 value_str = value_str.substring(1, value_str.length() - 1); 1298 1299 1214 } 1215 MSMUtils.setValue(command_element, value_str); 1300 1216 } 1301 1217 value_str = null; 1302 1218 name_str = null; 1303 1304 1219 } 1220 tokenizer = null; 1305 1221 } 1306 1222 catch (Exception exception) { 1307 1223 } 1308 1224 return command_element; 1309 1310 1311 1225 } 1226 1227 private Element parsePlugIn(String command_str) { 1312 1228 Element command_element = null; 1313 1229 boolean use_metadata_files = false; 1314 1230 boolean show_progress = false; 1315 1231 try { 1316 1317 1318 1232 CommandTokenizer tokenizer = new CommandTokenizer(command_str); 1233 // Check the token count. The token count from a command tokenizer isn't guarenteed to be correct, but it does give the maximum number of available tokens according to the underlying StringTokenizer (some of which may actually be append together by the CommandTokenizer as being a single argument). 1234 if(tokenizer.countTokens() >= 2) { 1319 1235 command_element = document.createElement(PLUGIN_ELEMENT); 1320 1236 // First token is plugin … … 1328 1244 Iterator names = arguments.keySet().iterator(); 1329 1245 while(names.hasNext()) { 1330 1331 1332 1333 1246 String name = (String) names.next(); 1247 String value = (String) arguments.get(name); // Can be null 1248 Element option_element = document.createElement(OPTION_ELEMENT); 1249 if(name.substring(1).equals(USE_METADATA_FILES_ARGUMENT)) { 1334 1250 use_metadata_files = true; 1335 1336 1337 1338 1339 1340 1341 1342 1251 } 1252 else if(name.substring(1).equals(SHOW_PROGRESS_ARGUMENT)) { 1253 show_progress = true; 1254 } 1255 option_element.setAttribute(NAME_ATTRIBUTE, name.substring(1)); 1256 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR); 1257 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR); // All arguments are considered to be custom until matched against base plugins arguments 1258 if(value != null) { 1343 1259 // Remove any speech marks appended in strings containing whitespace 1344 1260 if(value.startsWith(SPEECH_CHARACTER) && value.endsWith(SPEECH_CHARACTER)) { 1345 1261 value = value.substring(1, value.length() - 1); 1346 1262 } 1347 1263 if(name.equals(METADATA_ARGUMENT)) { 1348 1349 1264 // The metadata argument must be the fully qualified name of a metadata element, so if it doesn't yet have a namespace, append the extracted metadata namespace. 1265 if(value.indexOf(MSMUtils.NS_SEP) == -1) { 1350 1266 value = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + value; 1351 1267 } 1352 1268 } 1353 1269 MSMUtils.setValue(option_element, value); 1354 1355 1356 1357 1358 1270 } 1271 command_element.appendChild(option_element); 1272 option_element = null; 1273 name = null; 1274 value = null; 1359 1275 } 1360 1276 1361 1277 // We must have some RecPlug options: use_metadata_files, and show_progress 1362 1278 if (type.equals(RECPLUG_STR)) { 1363 1279 if (!use_metadata_files) { 1364 1280 Element option_element = document.createElement(OPTION_ELEMENT); 1365 1281 option_element.setAttribute(NAME_ATTRIBUTE, USE_METADATA_FILES_ARGUMENT); … … 1368 1284 command_element.appendChild(option_element); 1369 1285 option_element = null; 1370 1371 1372 1373 1374 1375 1376 1377 1378 1286 } 1287 if(!show_progress) { 1288 Element option_element = document.createElement(OPTION_ELEMENT); 1289 option_element.setAttribute(NAME_ATTRIBUTE, SHOW_PROGRESS_ARGUMENT); 1290 option_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR); 1291 option_element.setAttribute(CUSTOM_ATTRIBUTE, TRUE_STR); 1292 command_element.appendChild(option_element); 1293 option_element = null; 1294 } 1379 1295 } 1380 1296 type = null; 1381 1297 names = null; 1382 1298 arguments = null; 1383 1384 1299 } 1300 tokenizer = null; 1385 1301 } 1386 1302 catch(Exception exception) { 1387 1303 } 1388 1304 return command_element; 1389 1390 1391 1305 } 1306 1307 private Element parseSearchType(String command_str) { 1392 1308 Element command_element = null; 1393 1309 try { 1394 1395 1396 1397 1310 StringTokenizer tokenizer = new StringTokenizer(command_str); 1311 // First token is command type (levels) 1312 tokenizer.nextToken(); 1313 if(tokenizer.hasMoreTokens()) { 1398 1314 command_element = document.createElement(SEARCHTYPE_ELEMENT); 1399 1315 command_element.setAttribute(ASSIGNED_ATTRIBUTE, TRUE_STR); 1400 1316 while(tokenizer.hasMoreTokens()) { 1401 1402 1403 1404 1405 } 1406 1317 Element search_element = document.createElement(CONTENT_ELEMENT); 1318 search_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken()); 1319 command_element.appendChild(search_element); 1320 search_element = null; 1321 } 1322 } 1407 1323 } 1408 1324 catch(Exception exception) { 1409 1325 } 1410 1326 return command_element; 1411 1412 1413 1327 } 1328 1329 private Element parseSubCollection(String command_str) { 1414 1330 Element command_element = null; 1415 1331 try { 1416 1417 1332 CommandTokenizer tokenizer = new CommandTokenizer(command_str); 1333 if(tokenizer.countTokens() >= 3) { 1418 1334 command_element = document.createElement(SUBCOLLECTION_ELEMENT); 1419 1335 // First token is command type … … 1427 1343 // Set inclusion/exclusion flag, remove any exclaimation mark and the speech marks 1428 1344 if(exclusion) { 1429 1430 1345 full_pattern_str = full_pattern_str.substring(2, full_pattern_str.length() - 1); 1346 command_element.setAttribute(TYPE_ATTRIBUTE, EXCLUDE_STR); 1431 1347 } 1432 1348 else { 1433 1434 1349 full_pattern_str = full_pattern_str.substring(1, full_pattern_str.length() - 1); 1350 command_element.setAttribute(TYPE_ATTRIBUTE, INCLUDE_STR); 1435 1351 } 1436 1352 StringTokenizer pattern_tokenizer = new StringTokenizer(full_pattern_str, SEPARATOR_CHARACTER); 1437 1353 if(pattern_tokenizer.countTokens() >= 2) { 1438 1439 1440 1354 String content_str = pattern_tokenizer.nextToken(); 1355 // Since the contents of indexes have to be certain keywords, or metadata elements, if the content isn't a keyword and doesn't yet have a namespace, append the extracted metadata namespace. 1356 if(!content_str.equals(StaticStrings.FILENAME_STR) && content_str.indexOf(MSMUtils.NS_SEP) == -1) { 1441 1357 content_str = Utility.EXTRACTED_METADATA_NAMESPACE + MSMUtils.NS_SEP + content_str; 1442 1443 1444 1445 1358 } 1359 command_element.setAttribute(CONTENT_ATTRIBUTE, content_str); 1360 MSMUtils.setValue(command_element, pattern_tokenizer.nextToken()); 1361 if(pattern_tokenizer.hasMoreTokens()) { 1446 1362 command_element.setAttribute(OPTIONS_ATTRIBUTE, pattern_tokenizer.nextToken()); 1447 1363 } 1448 1364 } 1449 1365 pattern_tokenizer = null; 1450 1366 } 1451 1367 } 1452 1368 catch(Exception exception) { 1453 1369 exception.printStackTrace(); 1454 1370 } 1455 1371 return command_element; 1456 1457 1458 1372 } 1373 1374 private Element parseSubCollectionDefaultIndex(String command_str) { 1459 1375 Element command_element = null; 1460 1376 try { 1461 1462 1377 StringTokenizer tokenizer = new StringTokenizer(command_str); 1378 if(tokenizer.countTokens() == 2) { 1463 1379 command_element = document.createElement(SUBCOLLECTION_DEFAULT_INDEX_ELEMENT); 1464 1380 tokenizer.nextToken(); … … 1467 1383 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER); 1468 1384 while(content_tokenizer.hasMoreTokens()) { 1469 1470 1471 1472 1385 Element content_element = document.createElement(CONTENT_ELEMENT); 1386 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken()); 1387 command_element.appendChild(content_element); 1388 content_element = null; 1473 1389 } 1474 1390 content_tokenizer = null; 1475 1391 content_str = null; 1476 1477 1392 } 1393 tokenizer = null; 1478 1394 } 1479 1395 catch(Exception exception) { 1480 1396 } 1481 1397 return command_element; 1482 1483 1484 1398 } 1399 1400 private Element parseSubCollectionIndex(String command_str) { 1485 1401 Element command_element = null; 1486 1402 try { 1487 1488 1489 1403 StringTokenizer tokenizer = new StringTokenizer(command_str); 1404 tokenizer.nextToken(); 1405 if(tokenizer.hasMoreTokens()) { 1490 1406 command_element = document.createElement(SUBCOLLECTION_INDEXES_ELEMENT); 1491 1492 1407 } 1408 while(tokenizer.hasMoreTokens()) { 1493 1409 Element subcollectionindex_element = document.createElement(INDEX_ELEMENT); 1494 1410 //command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken()); … … 1496 1412 StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER); 1497 1413 while(content_tokenizer.hasMoreTokens()) { 1498 1499 1500 1501 1414 Element content_element = document.createElement(CONTENT_ELEMENT); 1415 content_element.setAttribute(NAME_ATTRIBUTE, content_tokenizer.nextToken()); 1416 subcollectionindex_element.appendChild(content_element); 1417 content_element = null; 1502 1418 } 1503 1419 content_tokenizer = null; … … 1505 1421 command_element.appendChild(subcollectionindex_element); 1506 1422 subcollectionindex_element = null; 1507 1508 1423 } 1424 tokenizer = null; 1509 1425 } 1510 1426 catch (Exception exception) { 1511 1427 } 1512 1428 return command_element; 1513 1514 1515 1429 } 1430 1431 private Element parseSuperCollection(String command_str) { 1516 1432 Element command_element = null; 1517 1433 try { 1518 1519 1434 StringTokenizer tokenizer = new StringTokenizer(command_str); 1435 if(tokenizer.countTokens() >= 3) { 1520 1436 command_element = document.createElement(SUPERCOLLECTION_ELEMENT); 1521 1437 tokenizer.nextToken(); 1522 1438 while(tokenizer.hasMoreTokens()) { 1523 1524 1525 1526 1527 } 1528 1529 1439 Element collection_element = document.createElement(COLLECTION_ELEMENT); 1440 collection_element.setAttribute(NAME_ATTRIBUTE, tokenizer.nextToken()); 1441 command_element.appendChild(collection_element); 1442 collection_element = null; 1443 } 1444 } 1445 tokenizer = null; 1530 1446 } 1531 1447 catch(Exception exception) { 1532 1448 } 1533 1449 return command_element; 1534 1535 1536 1450 } 1451 1452 private String pluginToString(Element command_element, boolean show_extracted_namespace) { 1537 1453 StringBuffer text = new StringBuffer(); 1538 1454 if(!command_element.getAttribute(SEPARATOR_ATTRIBUTE).equals(TRUE_STR)) { 1539 1540 1541 1542 1543 1544 1545 1546 1455 text.append(PLUGIN_STR); 1456 text.append(TAB_CHARACTER); 1457 text.append(TAB_CHARACTER); 1458 text.append(command_element.getAttribute(TYPE_ATTRIBUTE)); 1459 // Retrieve, and output, the arguments 1460 NodeList option_elements = command_element.getElementsByTagName(OPTION_ELEMENT); 1461 int option_elements_length = option_elements.getLength(); 1462 if(option_elements_length > 0) { 1547 1463 text.append(SPACE_CHARACTER); 1548 1464 for(int j = 0; j < option_elements_length; j++) { 1549 1550 1465 Element option_element = (Element) option_elements.item(j); 1466 if(option_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) { 1551 1467 text.append(StaticStrings.MINUS_CHARACTER); 1552 1468 text.append(option_element.getAttribute(NAME_ATTRIBUTE)); 1553 1469 String value_str = MSMUtils.getValue(option_element); 1554 1470 if(!show_extracted_namespace && value_str.startsWith(EXTRACTED_PREFIX)) { 1555 1471 value_str = value_str.substring(EXTRACTED_PREFIX.length()); 1556 1472 } 1557 1473 if(value_str.length() > 0) { 1558 1559 1474 text.append(SPACE_CHARACTER); 1475 if(value_str.indexOf(SPACE_CHARACTER) == -1) { 1560 1476 text.append(value_str); 1561 1562 1477 } 1478 else { 1563 1479 text.append(SPEECH_CHARACTER); 1564 1480 text.append(value_str); 1565 1481 text.append(SPEECH_CHARACTER); 1566 1482 } 1567 1483 } 1568 1484 value_str = null; 1569 1485 if(j < option_elements_length - 1) { 1570 1571 } 1572 1573 1574 } 1575 1576 1486 text.append(SPACE_CHARACTER); 1487 } 1488 } 1489 option_element = null; 1490 } 1491 } 1492 option_elements = null; 1577 1493 } 1578 1494 return text.toString(); 1579 1580 1581 1495 } 1496 1497 private String searchtypeToString(Element command_element) { 1582 1498 if(command_element.getAttribute(ASSIGNED_ATTRIBUTE).equals(TRUE_STR)) { 1583 1584 1585 1586 1587 1499 StringBuffer text = new StringBuffer(SEARCHTYPE_STR); 1500 text.append(TAB_CHARACTER); 1501 NodeList search_elements = command_element.getElementsByTagName(CONTENT_ELEMENT); 1502 int search_elements_length = search_elements.getLength(); 1503 for(int i = 0; i < search_elements_length; i++) { 1588 1504 Element search_element = (Element) search_elements.item(i); 1589 1505 text.append(search_element.getAttribute(NAME_ATTRIBUTE)); 1590 1506 text.append(SPACE_CHARACTER); 1591 1592 1507 } 1508 return text.substring(0, text.length() - 1); 1593 1509 } 1594 1510 else { 1595 1596 } 1597 1598 1599 1511 return null; 1512 } 1513 } 1514 1515 private String subcollectionToString(Element command_element, boolean show_extracted_namespace) { 1600 1516 StringBuffer text = new StringBuffer(SUBCOLLECTION_STR); 1601 1517 text.append(SPACE_CHARACTER); … … 1605 1521 text.append(SPEECH_CHARACTER); 1606 1522 if(command_element.getAttribute(TYPE_ATTRIBUTE).equals(EXCLUDE_STR)) { 1607 1523 text.append(EXCLAIMATION_CHARACTER); 1608 1524 } 1609 1525 String content_str = command_element.getAttribute(CONTENT_ATTRIBUTE); 1610 1526 if(!show_extracted_namespace && content_str.startsWith(EXTRACTED_PREFIX)) { 1611 1527 content_str = content_str.substring(EXTRACTED_PREFIX.length()); 1612 1528 } 1613 1529 text.append(content_str); … … 1618 1534 String options_str = command_element.getAttribute(OPTIONS_ATTRIBUTE); 1619 1535 if(options_str.length() > 0) { 1620 1536 text.append(options_str); 1621 1537 } 1622 1538 options_str = null; 1623 1539 text.append(SPEECH_CHARACTER); 1624 1540 return text.toString(); 1625 1626 1627 1541 } 1542 1543 private String subcollectionDefaultIndexToString(Element command_element) { 1628 1544 StringBuffer text = new StringBuffer(SUBCOLLECTION_DEFAULT_INDEX_STR); 1629 1545 text.append(TAB_CHARACTER); … … 1631 1547 int content_elements_length = content_elements.getLength(); 1632 1548 for(int j = 0; j < content_elements_length; j++) { 1633 1634 1635 1549 Element content_element = (Element) content_elements.item(j); 1550 text.append(content_element.getAttribute(NAME_ATTRIBUTE)); 1551 if(j < content_elements_length - 1) { 1636 1552 text.append(StaticStrings.COMMA_CHARACTER); 1637 1553 } 1638 1554 } 1639 1555 return text.toString(); 1640 1641 1642 1556 } 1557 1558 private String subcollectionIndexesToString(Element command_element) { 1643 1559 StringBuffer text = new StringBuffer(SUBCOLLECTION_INDEX_STR); 1644 1560 text.append(TAB_CHARACTER); … … 1647 1563 int subcollectionindex_elements_length = subcollectionindex_elements.getLength(); 1648 1564 if(subcollectionindex_elements_length == 0) { 1649 1565 return null; 1650 1566 } 1651 1567 for(int j = 0; j < subcollectionindex_elements_length; j++) { 1652 1653 1654 1655 1568 Element subcollectionindex_element = (Element) subcollectionindex_elements.item(j); 1569 NodeList content_elements = subcollectionindex_element.getElementsByTagName(CONTENT_ELEMENT); 1570 int content_elements_length = content_elements.getLength(); 1571 for(int k = 0; k < content_elements_length; k++) { 1656 1572 Element content_element = (Element) content_elements.item(k); 1657 1573 text.append(content_element.getAttribute(NAME_ATTRIBUTE)); 1658 1574 if(k < content_elements_length - 1) { 1659 1660 } 1661 1662 1575 text.append(StaticStrings.COMMA_CHARACTER); 1576 } 1577 } 1578 if(j < subcollectionindex_elements_length - 1) { 1663 1579 text.append(SPACE_CHARACTER); 1664 1580 } 1665 1581 } 1666 1582 return text.toString(); 1667 1668 1669 1583 } 1584 1585 private String supercollectionToString(Element command_element) { 1670 1586 NodeList content_elements = command_element.getElementsByTagName(COLLECTION_ELEMENT); 1671 1587 int content_elements_length = content_elements.getLength(); 1672 1588 if(content_elements_length > 1) { 1673 1674 1675 1589 StringBuffer text = new StringBuffer(SUPERCOLLECTION_STR); 1590 text.append(TAB_CHARACTER); 1591 for(int j = 0; j < content_elements_length; j++) { 1676 1592 Element content_element = (Element) content_elements.item(j); 1677 1593 text.append(content_element.getAttribute(NAME_ATTRIBUTE)); 1678 1594 if(j < content_elements_length - 1) { 1679 1680 } 1681 1682 1595 text.append(SPACE_CHARACTER); 1596 } 1597 } 1598 return text.toString(); 1683 1599 } 1684 1600 return null; 1685 1686 1687 1601 } 1602 1603 private String unknownToString(Element command_element) { 1688 1604 return MSMUtils.getValue(command_element); 1689 1690 1691 1692 1693 1694 1695 1605 } 1606 1607 /** 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. 1608 * @param writer the BufferedWriter to which the str will be written 1609 * @param str the String to be written 1610 */ 1611 private void write(BufferedWriter writer, String str) 1696 1612 throws IOException { 1697 1613 writer.write(str, 0, str.length()); 1698 1614 } 1699 1615 } -
trunk/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java
r5995 r6051 96 96 classifier_manager = new ClassifierManager(); 97 97 general_manager = new GeneralManager(); 98 98 99 99 searchtype_manager = new SearchTypeManager(collect_config.getSearchType()); 100 100 if(searchtype_manager.isMGPPEnabled()) { … … 104 104 index_manager = new IndexManager(collect_config.getMGIndexes()); 105 105 } 106 106 107 107 metadataset_view = new MetadataSetView(); 108 108 plugin_manager = new PlugInManager(); … … 156 156 general_manager.gainFocus(); 157 157 } 158 158 159 159 /** Retrieve the name of the collection configuration file which is being used as the source of the information in this object. 160 160 * @return The files absolute path as a <strong>String</strong>. … … 192 192 collection_released = true; 193 193 } 194 194 195 195 general_manager.loseFocus(); 196 196 collect_config.save(); 197 197 198 198 // Readd collection 199 199 ///ystem.err.println("Would have added collection if it had been released."); … … 206 206 } 207 207 } 208 208 209 /** Ensures that the collection is now public. Useful for collections that are based on another, or that are about to be exported */ 210 public void setCollectionAsPublic() { 211 CollectionMeta public_collectionmeta = new CollectionMeta(CollectionDesignManager.collect_config.getPublic()); 212 if(public_collectionmeta != null) { 213 public_collectionmeta.setValue(CollectionConfiguration.TRUE_STR); 214 public_collectionmeta = null; 215 } 216 } 217 209 218 /** Method used during a global search and replace to highlight the appropriate record within the Collection Design Managers version of the Metadata Set Manager (view only). 210 219 * @param element The name of the desired element as a <strong>String</strong>. … … 221 230 private class CDMChangeListener 222 231 implements ActionListener, DocumentListener { 223 232 224 233 public void actionPerformed(ActionEvent event) { 225 234 Gatherer.c_man.getCollection().setSaved(false); … … 230 239 Gatherer.c_man.getCollection().setSaved(false); 231 240 } 232 241 233 242 /** Gives notification that there was an insert into the document. */ 234 243 public void insertUpdate(DocumentEvent e) { 235 244 Gatherer.c_man.getCollection().setSaved(false); 236 245 } 237 246 238 247 /** Gives notification that a portion of the document has been removed. */ 239 248 public void removeUpdate(DocumentEvent e) { -
trunk/gli/src/org/greenstone/gatherer/cdm/CommandTokenizer.java
r6033 r6051 38 38 39 39 /************************************************************************************** 40 * Title: 40 * Title: Gatherer 41 41 * Description: The Gatherer: a tool for gathering and enriching a digital collection. 42 * Company: 43 * Written: 44 * Revised: 42 * Company: The University of Waikato 43 * Written: 07/05/02 44 * Revised: 03/10/02 - Commented 45 45 **************************************************************************************/ 46 import java.io.BufferedReader; 46 47 import java.util.StringTokenizer; 48 import org.greenstone.gatherer.Gatherer; 49 import org.greenstone.gatherer.util.StaticStrings; 47 50 48 51 /** This class provides an extension to the standard StringTokenizer in that it recognizes quotes (or some form of bracketting) enclose a single token so in something like: <br>format Search '<table><img src=... </table>'<br> the formatting string is parsed as a single token. Unfortunately this makes countTokens() unreliable for exact measurement of tokens remaining, and only useful for determining if there are tokens left to be processed (includes any that have already been read into command buffer). … … 50 53 * @version 2.3 51 54 */ 52 public class CommandTokenizer 53 extends StringTokenizer { 54 55 private int last_type = -1; 56 57 static final public int BRACKET_ENCLOSED = 0; 58 static final public int DOUBLE_QUOTE_ENCLOSED = 1; 59 static final public int NORMAL = 2; 60 static final public int QUOTE_ENCLOSED = 3; 61 62 /** Constructor. 63 * @param command The command <strong>String</strong> you wish to tokenize. 64 */ 65 public CommandTokenizer(String command) { 66 super(command); 67 } 68 69 /* private int getLastType() { 70 return last_type; 71 } */ 72 73 /* private boolean isComment() { 74 return (last_type == DOUBLE_QUOTE_ENCLOSED || last_type == QUOTE_ENCLOSED); 75 } */ 76 77 /** Method to retrieve the next token from the command, taking care to group tokens enclosed in speech marks. 78 * @return A <strong>String</strong> containing the next token from the command. 79 */ 80 public String nextToken() { 81 String result = null; 82 if(hasMoreTokens()) { 83 StringBuffer buffer = new StringBuffer(super.nextToken()); 84 switch(buffer.charAt(0)) { 85 case '\"': 86 while((buffer.length() == 1 || buffer.charAt(buffer.length() - 1) != '\"') && hasMoreTokens()) { 87 buffer.append(" "); 88 buffer.append(super.nextToken()); 89 ///ystem.err.println("Current Buffer = '" + buffer.toString() + "'"); 90 } 91 ///ystem.err.println("Final Buffer = '" + buffer.toString() + "'"); 92 last_type = DOUBLE_QUOTE_ENCLOSED; 93 break; 94 case '\'': 95 while((buffer.length() == 1 || buffer.charAt(buffer.length() - 1) != '\'') && hasMoreTokens()) { 96 buffer.append(" "); 97 buffer.append(super.nextToken()); 98 } 99 last_type = QUOTE_ENCLOSED; 100 break; 101 case '[': 102 while((buffer.length() == 1 || buffer.charAt(buffer.length() - 1) != ']') && hasMoreTokens()) { 103 buffer.append(" "); 104 buffer.append(super.nextToken()); 105 } 106 last_type = BRACKET_ENCLOSED; 107 break; 108 default: 109 last_type = NORMAL; 110 } 111 result = buffer.toString(); 112 } 113 return result; 114 } 115 116 /** Unfortunately the StringBuffer doesn't have a built in endsWith method, so I'll just have to implement my own. 117 * @param str The <strong>StringBuffer</strong> we are checking the end of. 118 * @param target The <strong>String</strong> fragment we are searching for. 119 * @return <i>true</i> if str ends with target, <i>false</i> otherwise. 120 */ 121 private boolean endsWith(StringBuffer str, String target) { 122 String temp = str.toString(); 123 if(temp.endsWith(target) != (str.lastIndexOf(target) == str.length() - target.length())) { 124 ///ystem.err.println("Holy error that'll crash the HFile creator if it happens twice, Batman!"); 125 ///ystem.err.println("String = '" + temp + "'"); 126 ///ystem.err.println("Target = '" + target + "'"); 127 } 128 return str.lastIndexOf(target) == str.length() - target.length(); 129 } 55 public class CommandTokenizer { 56 57 static final public int BRACKET_ENCLOSED = 0; 58 static final public int DOUBLE_QUOTE_ENCLOSED = 1; 59 static final public int NORMAL = 2; 60 static final public int QUOTE_ENCLOSED = 3; 61 62 private BufferedReader in_stream; 63 private int count = -1; 64 private StringTokenizer internal_tokenizer; 65 66 /** Basic Constructor. Used to parse tokens from a string keeping tokens surrounded by speechmarks or square brackets intact. Thus something like:<br> 67 * collectionmeta collectionextra [l = en] "Hello World"<br> 68 * is tokenized thus<br> 69 * {'collectionmeta', 'collectionextra', 'l = en', 'Hello World'} 70 * @param command the command String you wish to tokenize 71 */ 72 public CommandTokenizer(String command) { 73 this.internal_tokenizer = new StringTokenizer(command); 74 this.in_stream = null; 75 } 76 77 /** Advanced Constructor. As above but with one major difference. Since it is provided an input stream (presumably where the command string originated from), it is able to parse a quote enclosed command token that stretches over several lines. Each newline is preserved in the resulting token. There is an extra bitchslap here as comething like a collection extra might have html code in them that contain escaped speechmarks, so extra care must be taken not to break at them. Thus something like:<br> 78 * collectionmeta collectionextra [l = en] "<br> 79 * an example of the crazy as description we sometimes get which includes of all things something like <a href=\"this.html\"<br> 80 * >this</a> which you could easily see might be a problem if I parse this niavely."<br> 81 * is tokenized thus<br> 82 * {'collectionmeta', 'collectionextra', 'l = en', '\nan example of the crazy as description we sometimes get which includes of all things something like <a href=\"this.html\"\n>this</a> which you could easily see might be a problem if I parse this niavely.'} 83 * @param command the command String you wish to tokenize 84 * @param in_stream a BufferedReader from which the tokenizer can draw further lines as necessary 85 */ 86 public CommandTokenizer(String command, BufferedReader in_stream) { 87 ///atherer.println("***** CommandTokenizer *****\nparse:\t" + command + "\n****************************"); 88 this.internal_tokenizer = new StringTokenizer(command); 89 this.in_stream = in_stream; 90 } 91 92 /** Returns the minumum number of remaining tokens before the tokenizer runs out of string. There may be more tokens than this count, but never less. The discrepancy is due to internal functionality and the fact we can't read ahead in the string or associated stream without risking the need for unpredictable push-back 93 * @return the minumum number of tokens available as an int 94 */ 95 public int countTokens() { 96 if(count == 0 && internal_tokenizer.countTokens() > 1) { 97 return 1; 98 } 99 if(count == -1) { 100 count = internal_tokenizer.countTokens(); 101 } 102 return count; 103 } 104 105 /** Determine if there are still tokens available. 106 * @return true if there are more tokens, false otherwise 107 */ 108 public boolean hasMoreTokens() { 109 return internal_tokenizer.hasMoreTokens(); 110 } 111 112 /** Method to retrieve the next token from the command, taking care to group tokens enclosed in speech marks. 113 * @return a String containing the next token from the command 114 */ 115 public String nextToken() { 116 String result = null; 117 if(internal_tokenizer.hasMoreTokens()) { 118 StringBuffer buffer = new StringBuffer(internal_tokenizer.nextToken()); 119 switch(buffer.charAt(0)) { 120 case StaticStrings.DOUBLEQUOTE_CHAR: 121 result = buildToken(buffer, StaticStrings.DOUBLEQUOTE_CHAR, true); 122 break; 123 case StaticStrings.SINGLEQUOTE_CHAR: 124 result = buildToken(buffer, StaticStrings.SINGLEQUOTE_CHAR, true); 125 break; 126 case StaticStrings.OPENBRACKET_CHAR: 127 result = buildToken(buffer, StaticStrings.CLOSEBRACKET_CHAR, false); 128 break; 129 default: 130 result = buffer.toString(); 131 } 132 buffer = null; 133 } 134 // Because of our tricky counting system we never want to have negative tokens remaining. In fact, unless the internal string buffer is empty, we will return a count of 1 anyway 135 if(count > 0) { 136 count = count - 1; 137 } 138 ///atherer.println("----- CommandTokenizer -----\ntoken:\t" + result + "\n----------------------------"); 139 return result; 140 } 141 142 /** Parse in the next token. paying heed to enclosing characters demands, escaped characters, newlines and empty buffers and consequential unexpected end of tokens 143 * @param buffer the StringBuffer in which the partial token is stored (at the first bit that caused this method to be called) 144 * @param end_char the sentinel char we are watching for as it encloses a token 145 * @param strip_characters a boolean denoting whether the enclosing characters should be stripped off 146 * @return the token, either in its entirity less the enclosing characters if required or, if an unexpected end occured, whatever we parsed without its starting enclosing character, again only if required. In fact if we weren't asked to strip characters then we add the enclosing character back in 147 */ 148 private String buildToken(StringBuffer buffer, char end_char, boolean strip_characters) { 149 while(buffer.charAt(buffer.length() - 1) != end_char || (buffer.length() > 3 && buffer.charAt(buffer.length() - 2) == StaticStrings.BACKSLASH_CHAR)) { 150 try { 151 // The first version is for the basic tokenizer which has no idea of an input stream, so runs out tokens at the same time as the internal tokenizer does 152 if(internal_tokenizer.hasMoreTokens()) { 153 buffer.append(StaticStrings.SPACE_CHAR); 154 buffer.append(internal_tokenizer.nextToken()); 155 } 156 // While the second version can draw more lines from the stream until eof occurs 157 else if(in_stream != null) { 158 String line_str = null; 159 while(!internal_tokenizer.hasMoreTokens() && (line_str = in_stream.readLine()) != null) { 160 ///atherer.println("+++++ CommandTokenizer +++++\nappend:\t" + line_str + "\n+++++++++++++++++++++++++++++"); 161 // Its at this stage the our token count becomes completely patu 162 internal_tokenizer = new StringTokenizer(line_str); 163 buffer.append(StaticStrings.NEW_LINE_CHAR); // A new line in the final token 164 } 165 line_str = null; 166 if(internal_tokenizer.hasMoreTokens()) { 167 // Don't add a space if we just added a newline 168 if(buffer.charAt(buffer.length() - 1) != StaticStrings.NEW_LINE_CHAR) { 169 buffer.append(StaticStrings.SPACE_CHAR); 170 } 171 buffer.append(internal_tokenizer.nextToken()); 172 } 173 // We've prematurely run out of content, so throw the dummy, or at least return whatever we managed to parse sans its opening character 174 else { 175 if(strip_characters) { 176 return buffer.substring(1); 177 } 178 else { 179 buffer.append(end_char); 180 return buffer.toString(); 181 } 182 } 183 } 184 // We've prematurely run out of content, so throw the dummy, or at least return whatever we managed to parse sans its opening character 185 else { 186 if(strip_characters) { 187 return buffer.substring(1); 188 } 189 else { 190 buffer.append(end_char); 191 return buffer.toString(); 192 } 193 } 194 } 195 // Exception throw when we attempted reading from the input stream, so throw the dummy, or at least return whatever we managed to parse sans its opening character 196 catch(Exception exception) { 197 Gatherer.printStackTrace(exception); 198 if(strip_characters) { 199 return buffer.substring(1); 200 } 201 else { 202 buffer.append(end_char); 203 return buffer.toString(); 204 } 205 } 206 } 207 // Return the string sans enclosing characters 208 if(buffer.length() > 0 && strip_characters) { 209 return buffer.substring(1, buffer.length() - 1); 210 } 211 else { 212 return buffer.toString(); 213 } 214 } 130 215 } -
trunk/gli/src/org/greenstone/gatherer/cdm/GeneralManager.java
r6003 r6051 133 133 /** This class represents the visual component of the general options stored in the CollectionDesignManager. */ 134 134 private class GeneralControl 135 extends JPanel 135 extends JPanel 136 136 implements Control { 137 137 private boolean ready = false; … … 262 262 instruction_panel.add(title_label, BorderLayout.NORTH); 263 263 instruction_panel.add(new JScrollPane(instructions_textarea), BorderLayout.CENTER); 264 264 265 265 creator_panel.setLayout(new BorderLayout()); 266 266 creator_panel.add(creator_label, BorderLayout.WEST); … … 334 334 small_icon_textfield.setText(icon_collection_small_collectionmeta.getValue(CollectionMeta.TEXT)); 335 335 small_icon_textfield.setCaretPosition(0); 336 // I forgot to keep the checkboxes up to date. Why hasn't this caused problems before today? 337 public_checkbox.setSelected(public_collectionmeta.getValue(CollectionMeta.TEXT).equals(CollectionConfiguration.TRUE_STR)); 338 beta_checkbox.setSelected(beta_collectionmeta.getValue(CollectionMeta.TEXT).equals(CollectionConfiguration.TRUE_STR)); 336 339 ready = true; 337 340 } … … 343 346 beta_collectionmeta.setValue((beta_checkbox.isSelected() ? CollectionConfiguration.TRUE_STR : CollectionConfiguration.FALSE_STR)); 344 347 public_collectionmeta.setValue((public_checkbox.isSelected() ? CollectionConfiguration.TRUE_STR : CollectionConfiguration.FALSE_STR)); 345 creator_collectionmeta.setValue(creator_emailfield.getText()); 348 String creator_email_str = creator_emailfield.getText(); 349 creator_collectionmeta.setValue(creator_email_str); 350 Gatherer.config.setEmail(creator_email_str); // Store the email address in the configuration 346 351 collection_extra_collectionmeta.setValue(description_textarea.getText()); 347 352 icon_collection_collectionmeta.setValue(icon_textfield.getText()); … … 356 361 private class BrowseListener 357 362 implements ActionListener { 358 363 359 364 public void actionPerformed(ActionEvent event) { 360 365 // Open an almost standard file browser to the images folder of the current collection … … 405 410 } 406 411 } 407 412 408 413 /** ImageFilter.java is a 1.4 example used by FileChooserDemo2.java. */ 409 private class ImageFilter 414 private class ImageFilter 410 415 extends javax.swing.filechooser.FileFilter { 411 416 412 417 private Pattern pattern = null; 413 418 414 419 public ImageFilter() { 415 420 pattern = Pattern.compile(".*\\.(gif|png|jpe?g)"); 416 421 } 417 422 418 423 // Accept all directories and all .col files 419 424 public boolean accept(File f) { … … 422 427 return f.isDirectory() || matcher.matches(); 423 428 } 424 429 425 430 // The description of this filter 426 431 public String getDescription() { -
trunk/gli/src/org/greenstone/gatherer/cdm/IndexManager.java
r5931 r6051 331 331 Gatherer.c_man.configurationChanged(); 332 332 } 333 333 334 334 /** This method is reponsible for changing the underlying Index commands from MG to MGPP and back again. This turns out to be easyish for MG->MGPP and very hard for the reverse. For the former we remove the level fragment and make sure the same levels are set, then we produce a list of the sources involved, breaking down comma seperated lists and making sure each item it unique. Changing back the other way turns out to be impossible, so we don't (beyond generating document:text, section:text and paragraph:text if text is an index and the respective levels are present). In either case we start by creating a comment containing the old index information. 335 335 * @param state true to enable MGPP indexes, false to use standard MG style ones … … 378 378 index = null; 379 379 } 380 // Replace mg element with mgpp element 380 // Replace mg element with mgpp element 381 381 setRoot(mgpp_element); 382 382 … … 426 426 } 427 427 else { 428 // Replace mg element with mgpp element 428 // Replace mg element with mgpp element 429 429 setRoot(mgpp_element); 430 430 } … … 444 444 default_index.setAssigned(true); 445 445 } 446 // If mg element has no indexes, and the current mgpp index include a text one, then generate text indexes for each of the registered levels. 446 // If mg element has no indexes, and the current mgpp index include a text one, then generate text indexes for each of the registered levels. 447 447 NodeList indexes = mgpp_element.getElementsByTagName(CollectionConfiguration.INDEX_ELEMENT); 448 448 if(indexes.getLength() == 0) { … … 489 489 /** This class creates a set of controls for editing the indexes. */ 490 490 private class IndexControl 491 extends JPanel 491 extends JPanel 492 492 implements Control { 493 493 … … 728 728 else if(source_list.isSelectionEmpty()) { 729 729 add_enabled = false; 730 } 730 } 731 731 // If we get this far, create a dummy index and see if its already assigned in the collection 732 732 else { … … 806 806 return component; 807 807 } 808 808 809 809 } 810 810 811 811 private class MoveListener 812 812 implements ActionListener { 813 813 814 814 private boolean move_up; 815 815 … … 849 849 private class SetDefaultListener 850 850 implements ActionListener { 851 851 852 852 public void actionPerformed(ActionEvent event) { 853 853 Index index = (Index) index_list.getSelectedValue(); … … 879 879 validateAddButton(); 880 880 } 881 881 882 882 /** Gives notification that there was an insert into the document. */ 883 883 public void insertUpdate(DocumentEvent e) { 884 884 validateAddButton(); 885 885 } 886 886 887 887 /** Gives notification that a portion of the document has been removed. */ 888 888 public void removeUpdate(DocumentEvent e) { … … 928 928 // Create Indexes 929 929 JPanel indexes_panel = new JPanel(); 930 930 931 931 JPanel current_indexes_panel = new JPanel(); 932 932 … … 1053 1053 index_spacer_panel.add(index_body_panel, BorderLayout.NORTH); 1054 1054 index_spacer_panel.add(index_empty_panel, BorderLayout.CENTER); 1055 1055 1056 1056 indexes_panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 1057 1057 indexes_panel.setLayout(new BorderLayout()); … … 1061 1061 // Create Levels 1062 1062 JPanel levels_panel = new JPanel(); 1063 1063 1064 1064 JPanel current_levels_panel = new JPanel(); 1065 1065 … … 1119 1119 add_level_button.setMnemonic(KeyEvent.VK_A); 1120 1120 Dictionary.registerBoth(add_level_button, "CDM.IndexManager.MGPP.Add_Level", "CDM.IndexManager.MGPP.Add_Level_Tooltip"); 1121 1121 1122 1122 remove_level_button = new JButton("CDM.IndexManager.MGPP.Remove_Level"); 1123 1123 remove_level_button.setEnabled(false); … … 1173 1173 level_spacer_panel.add(level_body_panel, BorderLayout.NORTH); 1174 1174 level_spacer_panel.add(level_empty_panel, BorderLayout.CENTER); 1175 1175 1176 1176 levels_panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 1177 1177 levels_panel.setLayout(new BorderLayout()); … … 1181 1181 // Create General 1182 1182 JPanel header_panel = new JPanel(); 1183 1183 1184 1184 title_label = new JLabel(); 1185 1185 title_label.setHorizontalAlignment(JLabel.CENTER); … … 1376 1376 validateAddButton(); 1377 1377 } 1378 1378 1379 1379 /** Gives notification that a portion of the document has been removed. 1380 1380 * @param event a DocumentEvent containing information about the text removed … … 1383 1383 validateAddButton(); 1384 1384 } 1385 1385 1386 1386 /** Change the enable state of the add button depending on the current value in the search type combobox. */ 1387 1387 public void validateAddButton() { … … 1438 1438 validateAddButton(); 1439 1439 } 1440 1440 1441 1441 /** Gives notification that a portion of the document has been removed. 1442 1442 * @param event a DocumentEvent containing information about the text removed … … 1445 1445 validateAddButton(); 1446 1446 } 1447 1447 1448 1448 /** Change the enable state of the add button depending on the current value in the search type combobox. */ 1449 1449 public void validateAddButton() { … … 1500 1500 1501 1501 /** Replace really only replaces the string. */ 1502 private class ReplaceIndexActionListener 1502 private class ReplaceIndexActionListener 1503 1503 implements ActionListener { 1504 1504 … … 1526 1526 } 1527 1527 } 1528 1528 1529 1529 private class RemoveIndexActionListener 1530 1530 implements ActionListener { -
trunk/gli/src/org/greenstone/gatherer/cdm/MetadataSetView.java
r5593 r6051 158 158 /** This class creates and lays-out the various controls for reviewing the metadata sets, and their commands as they would appear in the collection configuration file. */ 159 159 private class MetadataSetControl 160 extends JPanel 160 extends JPanel 161 161 implements Control { 162 162 /** The label denoting the element list. */ … … 324 324 String namespace = set.getNamespace(); 325 325 // Watch out for the greenstone set, with its namespace of "" 326 if(namespace == null || namespace.length() == 0) { 327 namespace = "greenstone"; 328 } 329 return "metadataset " + namespace + " \"" + set.getFile().getName() + "\""; 326 return "metadataset " + namespace + " \"" + set.getName() + "\""; 330 327 } 331 328 } -
trunk/gli/src/org/greenstone/gatherer/cdm/PlugInManager.java
r5926 r6051 967 967 */ 968 968 private class RemoveListener 969 implements ActionListener { 970 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls. 971 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action. 972 */ 973 public void actionPerformed(ActionEvent event) { 974 if(!plugin_list.isSelectionEmpty()) { 975 Object [] objects = plugin_list.getSelectedValues(); 976 for(int i = 0; i < objects.length; i++) { 977 if(objects[i] instanceof PlugIn) { 978 removePlugIn((PlugIn)objects[i]); 969 implements ActionListener { 970 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls. 971 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action. 972 */ 973 public void actionPerformed(ActionEvent event) { 974 int selected_index = plugin_list.getSelectedIndex(); 975 if(selected_index != -1) { 976 PlugIn selected_plugin = (PlugIn) plugin_list.getSelectedValue(); 977 removePlugIn(selected_plugin); 978 selected_plugin = null; 979 // Select the next plugin if available 980 if(selected_index < plugin_list.getModel().getSize()) { 981 // If the new selection is above the separator we can remove it 982 if(selected_index < findSeparatorIndex()) { 983 plugin_list.setSelectedIndex(selected_index); 984 remove.setEnabled(true); 985 } 986 // Otherwise select the first non-removable plugin 987 else { 988 plugin_list.setSelectedIndex(selected_index + 1); 989 remove.setEnabled(false); 990 } 991 } 992 else { 993 remove.setEnabled(false); 994 } 995 // Refresh the available plugins 996 plugin.setModel(new DefaultComboBoxModel(getAvailable())); 979 997 } 980 } 981 // Refresh the available plugins 982 plugin.setModel(new DefaultComboBoxModel(getAvailable())); 983 } 984 remove.setEnabled(false); 985 } 998 else { 999 remove.setEnabled(false); 1000 } 1001 /* 1002 if(!plugin_list.isSelectionEmpty()) { 1003 Object [] objects = plugin_list.getSelectedValues(); 1004 for(int i = 0; i < objects.length; i++) { 1005 if(objects[i] instanceof PlugIn) { 1006 removePlugIn((PlugIn)objects[i]); 1007 } 1008 } 1009 // Refresh the available plugins 1010 plugin.setModel(new DefaultComboBoxModel(getAvailable())); 1011 } 1012 */ 1013 } 986 1014 } 987 1015 } -
trunk/gli/src/org/greenstone/gatherer/cdm/SearchTypeManager.java
r5928 r6051 29 29 /************************************************************************************** 30 30 * Written: 16/07/03 31 * Revised: 31 * Revised: 32 32 **************************************************************************************/ 33 33 import java.awt.*; … … 82 82 return controls; 83 83 } 84 85 public String getSearchTypes() { 86 StringBuffer search_types = new StringBuffer(); 87 ArrayList types = children(); 88 for (int i=0; i<types.size(); i++) { 89 if (i>0) { 90 search_types.append(","); 91 } 92 search_types.append(((SearchType)types.get(i)).getName()); 93 } 94 return search_types.toString(); 95 } 96 /** Be examining the SearchType 'root' we were created with, determine if mgpp is enabled. 97 * @return true if MGPP is enabled, false otherwise 98 */ 99 public boolean isMGPPEnabled() { 100 return root.getAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE).equals(CollectionConfiguration.TRUE_STR); 101 } 84 85 /** Return a list of the currently assigned search types as a comma separated string. 86 * @return a String 87 */ 88 public String getSearchTypes() { 89 StringBuffer search_types = new StringBuffer(); 90 ArrayList types = children(); 91 for (int i = 0; i < types.size(); i++) { 92 if (i>0) { 93 search_types.append(","); 94 } 95 search_types.append(((SearchType)types.get(i)).getName()); 96 } 97 return search_types.toString(); 98 } 99 100 /** Be examining the SearchType 'root' we were created with, determine if mgpp is enabled. 101 * @return true if MGPP is enabled, false otherwise 102 */ 103 public boolean isMGPPEnabled() { 104 return root.getAttribute(CollectionConfiguration.ASSIGNED_ATTRIBUTE).equals(CollectionConfiguration.TRUE_STR); 105 } 102 106 103 107 public void moveSearchType(SearchType search_type, boolean direction) { … … 127 131 remove(search_type); 128 132 add(index, search_type); 129 Gatherer.c_man.configurationChanged(); 133 Gatherer.c_man.configurationChanged(); 130 134 } 131 135 … … 147 151 private JButton move_up_button; 148 152 private JButton remove_button; 149 153 150 154 private JCheckBox enable_advanced_searches_checkbox; 151 155 … … 267 271 inner_panel.add(current_search_types_panel, BorderLayout.CENTER); 268 272 inner_panel.add(search_type_panel, BorderLayout.SOUTH); 269 273 270 274 spacer_panel.setLayout(new BorderLayout()); 271 275 spacer_panel.add(inner_panel, BorderLayout.NORTH); … … 280 284 public void destroy() { 281 285 } 282 286 283 287 public void gainFocus() { 284 288 instructions_textarea.setCaretPosition(0); … … 413 417 414 418 /** Listens for changes in the search types combobox, and enabled add button appropriately. */ 415 private class SearchTypesActionDocumentListener 419 private class SearchTypesActionDocumentListener 416 420 implements ActionListener, DocumentListener { 417 421 /** Called whenever a selection action occurs on the combobox. … … 434 438 validateAddButton(); 435 439 } 436 440 437 441 /** Gives notification that a portion of the document has been removed. 438 442 * @param event a DocumentEvent containing information about the text removed … … 441 445 validateAddButton(); 442 446 } 443 447 444 448 /** Change the enable state of the add button depending on the current value in the search type combobox. */ 445 449 private void validateAddButton() { -
trunk/gli/src/org/greenstone/gatherer/cdm/SuperCollectionManager.java
r5590 r6051 37 37 import org.greenstone.gatherer.checklist.CheckList; 38 38 import org.greenstone.gatherer.checklist.Entry; 39 import org.greenstone.gatherer.collection. CollectionConfiguration;39 import org.greenstone.gatherer.collection.BasicCollectionConfiguration; 40 40 import org.greenstone.gatherer.util.StaticStrings; 41 41 import org.greenstone.gatherer.util.Utility; … … 43 43 44 44 /** This class contains the information about what supercollection has been specified (if any) and methods for changing this information. Note that there is a major difference between this manager and the others in that its DOM model is never used directly in any list component. It is only used to decide whether a certain entry in the actual checklist is checked. */ 45 public class SuperCollectionManager 45 public class SuperCollectionManager 46 46 extends DOMProxyListModel { 47 47 … … 107 107 /** Provides controls for altering the SuperCollection settings. */ 108 108 private class SuperCollectionControl 109 extends JPanel 109 extends JPanel 110 110 implements Control { 111 111 … … 119 119 // Creation 120 120 JPanel header_panel = new JPanel(); 121 121 122 122 JLabel title_label = new JLabel(); 123 123 title_label.setHorizontalAlignment(JLabel.CENTER); … … 141 141 header_panel.add(title_label, BorderLayout.NORTH); 142 142 header_panel.add(new JScrollPane(instructions), BorderLayout.CENTER); 143 143 144 144 setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 145 145 setLayout(new BorderLayout()); … … 198 198 File collect_cfg_file = new File(possible_collections[i], Utility.CONFIG_DIR); 199 199 if(collect_cfg_file.exists()) { 200 CollectionConfiguration collect_cfg = newCollectionConfiguration(collect_cfg_file);200 BasicCollectionConfiguration collect_cfg = new BasicCollectionConfiguration(collect_cfg_file); 201 201 String collection_title = collect_cfg.getName(); 202 202 String collection_name = possible_collections[i].getName(); … … 210 210 collection_checklist_model.add(entry); 211 211 entry = null; 212 212 213 213 } 214 214 collection_name = null; -
trunk/gli/src/org/greenstone/gatherer/collection/Collection.java
r5815 r6051 43 43 import org.greenstone.gatherer.Gatherer; 44 44 import org.greenstone.gatherer.cdm.CollectionDesignManager; 45 import org.greenstone.gatherer.cdm.CollectionMeta; 46 import org.greenstone.gatherer.cdm.CollectionMetaManager; 45 47 import org.greenstone.gatherer.collection.BuildOptions; 48 import org.greenstone.gatherer.collection.BasicCollectionConfiguration; 46 49 import org.greenstone.gatherer.collection.CollectionManager; 47 50 import org.greenstone.gatherer.file.FileNode; … … 59 62 */ 60 63 public class Collection { 61 /** A reference to the BuildOptions. */ 62 public BuildOptions build_options; 63 /** A reference to the Collection Design Manager. */ 64 public CollectionDesignManager cdm; 65 /** A reference to the Greenstone Directory Metadata Manager. */ 66 public GDMManager gdm; 67 /** A reference to the Metadata Set Manager. */ 68 public MetadataSetManager msm; 69 /** <i>true</i> if the currently loaded collection has been saved since the last significant change, <i>false</i> otherwise. */ 70 private boolean saved = false; 71 /** The collectio configuration file for this collection. */ 72 private CollectionConfiguration collect_cfg; 73 /** The document around which this collection class is based. */ 74 private Document document; 75 /** The file the collection is in (the file may not actually exist, such in the case of a legacy collection)! */ 76 private File file; 64 /** A reference to the BuildOptions. */ 65 public BuildOptions build_options; 66 /** A reference to the Collection Design Manager. */ 67 public CollectionDesignManager cdm; 68 /** A reference to the Greenstone Directory Metadata Manager. */ 69 public GDMManager gdm; 70 /** A reference to the Metadata Set Manager. */ 71 public MetadataSetManager msm; 72 /** <i>true</i> if the currently loaded collection has been saved since the last significant change, <i>false</i> otherwise. */ 73 private boolean saved = false; 74 /** The document around which this collection class is based. */ 75 private Document document; 76 /** The file the collection is in (the file may not actually exist, such in the case of a legacy collection)! */ 77 private File file; 77 78 /** The name of the argument element. */ 78 79 static final private String ARGUMENT = "Argument"; 79 80 static final private String BASE_COLLECTION = "base_collection"; 80 /** The name of the build element. */ 81 static final private String BUILD = "Build"; 82 /** The name of the build config element. */ 83 static final private String BUILD_CONFIG = "BuildConfig"; 84 /** The name of the collection xml template. */ 85 static final private String COLLECTION_XML_TEMPLATE = "xml/template.col"; 86 /** The name of the directory mappings element. */ 87 static final private String DIRECTORY_MAPPINGS = "DirectoryMappings"; 88 /** The name of the file attribute. */ 89 static final private String FILE = "file"; 90 /** The name of the import element. */ 91 static final private String IMPORT = "Import"; 92 /** The name of the imported attribute. */ 93 static final private String IMPORTED = "imported"; 94 /** The name of the mapping element. */ 95 static final private String MAPPING = "Mapping"; 96 /** The name of the name attribute. */ 97 static final private String NAME = "name"; 98 /** The name of the true value. */ 99 static final private String TRUE = "true"; 100 /** Constructor. */ 101 public Collection(File collection_xml) { 102 this.file = collection_xml; 103 // Try to load this collections details. 104 document = Utility.parse(collection_xml, false); 105 // If that fails load the default settings for a collection. 106 if(document == null) { 107 document = Utility.parse(COLLECTION_XML_TEMPLATE, true); 108 } 109 // Point the Configuration class at our gatherer config arguments. 110 Gatherer.config.setCollectionConfiguration(document); 111 // We also attempt to parse the collection configuration file. 112 collect_cfg = new CollectionConfiguration(new File(collection_xml.getParentFile(), Utility.CONFIG_DIR)); 113 // Finally create all of the child managers that are directly dependant on a collection 114 build_options = new BuildOptions(getBuildValues(), getImportValues()); 115 } 116 /** Add a special directory mapping. */ 117 public boolean addDirectoryMapping(String name, File file) { 81 /** The name of the build element. */ 82 static final private String BUILD = "Build"; 83 /** The name of the build config element. */ 84 static final private String BUILD_CONFIG = "BuildConfig"; 85 /** The name of the collection xml template. */ 86 static final private String COLLECTION_XML_TEMPLATE = "xml/template.col"; 87 /** The name of the directory mappings element. */ 88 static final private String DIRECTORY_MAPPINGS = "DirectoryMappings"; 89 /** The name of the file attribute. */ 90 static final private String FILE = "file"; 91 /** The name of the import element. */ 92 static final private String IMPORT = "Import"; 93 /** The name of the imported attribute. */ 94 static final private String IMPORTED = "imported"; 95 /** The name of the mapping element. */ 96 static final private String MAPPING = "Mapping"; 97 /** The name of the name attribute. */ 98 static final private String NAME = "name"; 99 /** The name of the true value. */ 100 static final private String TRUE = "true"; 101 /** Constructor. */ 102 public Collection(File collection_xml) { 103 this.file = collection_xml; 104 // Try to load this collections details. 105 document = Utility.parse(collection_xml, false); 106 // If that fails load the default settings for a collection. 107 if(document == null) { 108 document = Utility.parse(COLLECTION_XML_TEMPLATE, true); 109 } 110 // Point the Configuration class at our gatherer config arguments. 111 Gatherer.config.setCollectionConfiguration(document); 112 // Finally create all of the child managers that are directly dependant on a collection 113 build_options = new BuildOptions(getBuildValues(), getImportValues()); 114 } 115 116 /** Add a special directory mapping. */ 117 public boolean addDirectoryMapping(String name, File file) { 118 118 boolean result = false; 119 119 try { 120 121 120 Element document_element = document.getDocumentElement(); 121 Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS); 122 122 // Ensure the name isn't already in use. 123 124 125 123 boolean found = false; 124 NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING); 125 for(int i = 0; !found && i < mappings.getLength(); i++) { 126 126 Element mapping_element = (Element) mappings.item(i); 127 127 if(mapping_element.getAttribute(NAME).equalsIgnoreCase(name)) { 128 128 found = true; 129 129 } 130 130 mapping_element = null; 131 132 133 131 } 132 // Otherwise add the mapping. 133 if(!found) { 134 134 Element mapping_element = document.createElement(MAPPING); 135 135 mapping_element.setAttribute(NAME, name); … … 138 138 result = true; 139 139 mapping_element = null; 140 141 142 143 144 140 } 141 mappings = null; 142 directory_mappings_element = null; 143 document_element = null; 144 saved = false; 145 145 } 146 146 catch (Exception error) { 147 147 Gatherer.printStackTrace(error); 148 148 } 149 149 return result; 150 151 152 /** Destructor. 153 154 150 } 151 152 /** Destructor. 153 * @see org.greenstone.gatherer.collection.CollectionModel */ 154 public void destroy() { 155 155 cdm.destroy(); 156 156 gdm.destroy(); … … 161 161 gdm = null; 162 162 msm = null; 163 163 } 164 164 165 165 /** Determine the path to the base collection. 166 167 166 * @return the path as a String 167 */ 168 168 public String getBaseCollection() { 169 169 return getString(BASE_COLLECTION); 170 170 } 171 172 173 171 172 /** Determine the number of documents and folders in this collection. */ 173 public int getCount() { 174 174 return getCount((TreeNode)Gatherer.c_man.getRecordSet().getRoot(), true, true); 175 176 177 178 175 } 176 177 /** Calculates the number of documents in this collection. */ 178 public int getDocumentCount() { 179 179 return getCount((TreeNode)Gatherer.c_man.getRecordSet().getRoot(), false, true); 180 } 181 /** Retrieve the description of this collection. 182 * @return The description as a <strong>String</strong>. 183 */ 184 public String getDescription() { 185 return collect_cfg.getDescription(); 186 } 187 188 public String getCollectionType() { 189 return collect_cfg.getBuildType(); 190 } 191 192 public String getSearchTypes() { 193 return collect_cfg.getSearchTypes(); 194 } 195 /** Retrieve a specific directory mapping associated with this collection. 196 * @param name The name of the mapping to retrieve as a <strong>String</strong>. 197 * @return The <strong>File</strong> this name maps to, or <i>null</i> if no such mapping. 198 */ 199 /* private File getDirectoryMapping(String name) { 200 File result = null; 201 try { 202 Element document_element = document.getDocumentElement(); 203 Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS); 204 // Ensure the name isn't already in use. 205 boolean found = false; 206 NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING); 207 for(int i = 0; !found && i < mappings.getLength(); i++) { 208 Element mapping_element = (Element) mappings.item(i); 209 if(mapping_element.getAttribute(NAME).equalsIgnoreCase(name)) { 210 result = new File(MSMUtils.getValue(mapping_element)); 211 found = true; 212 } 213 mapping_element = null; 214 } 215 mappings = null; 216 directory_mappings_element = null; 217 document_element = null; 218 } 219 catch(Exception error) { 220 Gatherer.printStackTrace(error); 221 } 222 return result; 223 } */ 224 /** Retrieve the special directory mappings associated with this collection. 225 * @return A <strong>HashMap</strong> containing mappings from names to directories. 226 */ 227 public HashMap getDirectoryMappings() { 228 HashMap special_directories = new HashMap(); 229 try { 230 Element document_element = document.getDocumentElement(); 231 Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS); 232 // Ensure the name isn't already in use. 233 boolean found = false; 234 NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING); 235 for(int i = 0; !found && i < mappings.getLength(); i++) { 236 Element mapping_element = (Element) mappings.item(i); 237 String name = mapping_element.getAttribute(NAME); 238 File file = new File(mapping_element.getAttribute(FILE)); 239 special_directories.put(name, file); 240 file = null; 241 name = null; 242 mapping_element = null; 243 } 244 mappings = null; 245 directory_mappings_element = null; 246 document_element = null; 247 } 248 catch(Exception error) { 249 Gatherer.printStackTrace(error); 250 } 251 return special_directories; 252 } 253 /** Retrieve the authors email for this collection. 254 * @return The email as a <strong>String</strong>. 255 */ 256 public String getEmail() { 257 return collect_cfg.getCreator(); 258 } 259 /** Counts the number of folders used in the current record set. */ 260 /* private int getFolderCount() { 261 return getCount((TreeNode)Gatherer.c_man.getRecordSet().getRoot(), true, false); 262 } */ 263 /** Determine if this collection has had an import action run upon it since the last major change. 264 * @return <i>true</i> if an import has occured, <i>false</i> otherwise. 265 */ 266 /* private boolean getImported() { 267 return get(IMPORTED); 268 } */ 269 /** Retrieve the short name for this collection. 270 * @return The name as a <strong>String</strong>. 271 */ 272 public String getName() { 273 return file.getParentFile().getName(); 274 } 275 /** Determine if this collection has been saved since the last major change. 276 * @return <i>true</i> if it has been saved recently, <i>false</i> otherwise. 277 */ 278 public boolean getSaved() { 279 return saved; 280 } 281 /** Retrieve the title of this collection. 282 * @return The title as a <strong>String</strong>. 283 */ 284 public String getTitle() { 285 return collect_cfg.getName(); 286 } 287 /** Remove a previously defined special directory mapping. 288 * @param name The name of the mapping to remove as a <strong>String</strong>. 289 * @return The <strong>File</strong> of the mapping removed. 290 */ 291 public File removeDirectoryMapping(String name) { 292 File file = null; 293 try { 294 Element document_element = document.getDocumentElement(); 295 Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS); 296 // Ensure the name isn't already in use. 297 boolean found = false; 298 NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING); 299 for(int i = 0; !found && i < mappings.getLength(); i++) { 300 Element mapping_element = (Element) mappings.item(i); 301 if(mapping_element.getAttribute(NAME).equalsIgnoreCase(name)) { 302 file = new File(MSMUtils.getValue(mapping_element)); 303 directory_mappings_element.removeChild(mapping_element); 304 found = true; 305 } 306 mapping_element = null; 307 } 308 mappings = null; 309 directory_mappings_element = null; 310 document_element = null; 311 saved = false; 312 } 313 catch(Exception error) { 314 Gatherer.printStackTrace(error); 315 } 316 return file; 317 } 318 /** Save this xml document to the given file. */ 319 public void save() { 180 } 181 182 /** Retrieve the description of this collection. 183 * @return a String 184 */ 185 public String getDescription() { 186 if(cdm == null) { 187 return StaticStrings.EMPTY_STR; 188 } 189 CollectionMeta collection_extra_collectionmeta = cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR); 190 return collection_extra_collectionmeta.getValue(CollectionMeta.TEXT); 191 } 192 193 /** Retrieve the special directory mappings associated with this collection. 194 * @return A <strong>HashMap</strong> containing mappings from names to directories. 195 */ 196 public HashMap getDirectoryMappings() { 197 HashMap special_directories = new HashMap(); 198 try { 199 Element document_element = document.getDocumentElement(); 200 Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS); 201 // Ensure the name isn't already in use. 202 boolean found = false; 203 NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING); 204 for(int i = 0; !found && i < mappings.getLength(); i++) { 205 Element mapping_element = (Element) mappings.item(i); 206 String name = mapping_element.getAttribute(NAME); 207 File file = new File(mapping_element.getAttribute(FILE)); 208 special_directories.put(name, file); 209 file = null; 210 name = null; 211 mapping_element = null; 212 } 213 mappings = null; 214 directory_mappings_element = null; 215 document_element = null; 216 } 217 catch(Exception error) { 218 Gatherer.printStackTrace(error); 219 } 220 return special_directories; 221 } 222 /** Retrieve the authors email for this collection. 223 * @return The email as a <strong>String</strong>. 224 */ 225 public String getEmail() { 226 if(cdm == null) { 227 return StaticStrings.EMPTY_STR; 228 } 229 CollectionMeta creator_collectionmeta = new CollectionMeta(CollectionDesignManager.collect_config.getCreator()); 230 return creator_collectionmeta.getValue(CollectionMeta.TEXT); 231 } 232 233 /** Retrieve the short name for this collection. 234 * @return The name as a <strong>String</strong>. 235 */ 236 public String getName() { 237 return file.getParentFile().getName(); 238 } 239 240 /** Determine if this collection has been saved since the last major change. 241 * @return <i>true</i> if it has been saved recently, <i>false</i> otherwise. 242 */ 243 public boolean getSaved() { 244 return saved; 245 } 246 247 /** Retrieve the title of this collection. 248 * @return The title as a <strong>String</strong>. 249 */ 250 public String getTitle() { 251 if(cdm == null) { 252 return StaticStrings.EMPTY_STR; 253 } 254 CollectionMeta collection_name_collectionmeta = cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR); 255 return collection_name_collectionmeta.getValue(CollectionMeta.TEXT); 256 } 257 /** Remove a previously defined special directory mapping. 258 * @param name The name of the mapping to remove as a <strong>String</strong>. 259 * @return The <strong>File</strong> of the mapping removed. 260 */ 261 public File removeDirectoryMapping(String name) { 262 File file = null; 263 try { 264 Element document_element = document.getDocumentElement(); 265 Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS); 266 // Ensure the name isn't already in use. 267 boolean found = false; 268 NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING); 269 for(int i = 0; !found && i < mappings.getLength(); i++) { 270 Element mapping_element = (Element) mappings.item(i); 271 if(mapping_element.getAttribute(NAME).equalsIgnoreCase(name)) { 272 file = new File(MSMUtils.getValue(mapping_element)); 273 directory_mappings_element.removeChild(mapping_element); 274 found = true; 275 } 276 mapping_element = null; 277 } 278 mappings = null; 279 directory_mappings_element = null; 280 document_element = null; 281 saved = false; 282 } 283 catch(Exception error) { 284 Gatherer.printStackTrace(error); 285 } 286 return file; 287 } 288 /** Save this xml document to the given file. */ 289 public void save() { 320 290 Utility.export(document, file); 321 291 } 322 292 323 293 public void setBaseCollection(String base_collection) { 324 294 set(BASE_COLLECTION, base_collection); 325 295 } 326 327 328 329 330 296 297 /** Set the value of imported to the given value. 298 * @param value The new value for imported, <i>true</i> if the collection has been imported successfully, <i>false</i> otherwise. 299 */ 300 public void setImported(boolean value) { 331 301 set(IMPORTED, value); 332 302 saved = false; 333 334 335 336 337 303 } 304 /** Set the value of saved to the given value. 305 * @param value The new value for saved, <i>true</i> if the collection has been saved recently, <i>false</i> otherwise. 306 */ 307 public void setSaved(boolean value) { 338 308 saved = value; 339 } 340 /** Set the value of title to the given value. 341 * @param title The new <strong>String</strong> title. 342 */ 343 public void setTitle(String title) { 344 collect_cfg.setName(title); 345 } 346 /** Method called to return a textual representation of a class, which in this case is the collections title. 347 * @return A <strong>String</strong> containing the collections title. 348 */ 349 public String toString() { 350 return collect_cfg.getName(); 351 } 352 /** Get the value of a collection argument. */ 353 private boolean get(String name) { 309 } 310 /** Set the value of title to the given value. 311 * @param title The new <strong>String</strong> title. 312 */ 313 public void setTitle(String title) { 314 if(cdm != null) { 315 CollectionMeta collection_name_collectionmeta = cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR); 316 collection_name_collectionmeta.setValue(title); 317 } 318 } 319 /** Method called to return a textual representation of a class, which in this case is the collections title. 320 * @return A <strong>String</strong> containing the collections title. 321 */ 322 public String toString() { 323 return getTitle(); 324 } 325 /** Get the value of a collection argument. */ 326 private boolean get(String name) { 354 327 boolean result = false; 355 328 try { 356 357 358 359 329 Element document_element = document.getDocumentElement(); 330 NodeList arguments = document_element.getElementsByTagName(ARGUMENT); 331 boolean found = false; 332 for(int i = 0; !found && i < arguments.getLength(); i++) { 360 333 Element argument_element = (Element) arguments.item(i); 361 334 if(argument_element.getParentNode() == document_element) { 362 335 if(argument_element.getAttribute(NAME).equalsIgnoreCase(name)) { 363 336 String value = MSMUtils.getValue(argument_element); 364 337 if(value.equalsIgnoreCase(TRUE)) { 365 338 result = true; 366 339 } 367 340 found = true; 368 341 value = null; 369 342 } 370 343 } 371 344 argument_element = null; 372 373 374 345 } 346 arguments = null; 347 document_element = null; 375 348 } 376 349 catch (Exception error) { 377 350 Gatherer.printStackTrace(error); 378 351 } 379 352 return result; 380 381 382 383 353 } 354 355 /** Get the value of a collection argument. */ 356 private String getString(String name) { 384 357 String result = ""; 385 358 try { 386 387 388 389 359 Element document_element = document.getDocumentElement(); 360 NodeList arguments = document_element.getElementsByTagName(ARGUMENT); 361 boolean found = false; 362 for(int i = 0; !found && i < arguments.getLength(); i++) { 390 363 Element argument_element = (Element) arguments.item(i); 391 364 if(argument_element.getParentNode() == document_element) { 392 365 if(argument_element.getAttribute(NAME).equalsIgnoreCase(name)) { 393 366 result = MSMUtils.getValue(argument_element); 394 367 found = true; 395 368 } 396 369 } 397 370 argument_element = null; 398 399 400 371 } 372 arguments = null; 373 document_element = null; 401 374 } 402 375 catch (Exception error) { 403 376 Gatherer.printStackTrace(error); 404 377 } 405 378 return result; 406 } 407 408 409 379 } 380 381 /** Method to retrieve the current build options associated with this Collection. */ 382 private Element getBuildValues() { 410 383 Element build_values_element = null; 411 384 try { 412 413 414 415 416 385 Element document_element = document.getDocumentElement(); 386 Element build_config_element = (Element) MSMUtils.getNodeFromNamed(document_element, BUILD_CONFIG); 387 build_values_element = (Element) MSMUtils.getNodeFromNamed(build_config_element, BUILD); 388 build_config_element = null; 389 document_element = null; 417 390 } 418 391 catch (Exception error) { 419 392 Gatherer.printStackTrace(error); 420 393 } 421 394 return build_values_element; 422 423 424 425 395 } 396 397 /** Count either documents or folders, depending on the state of the given boolean. */ 398 private int getCount(TreeNode node, boolean count_folders, boolean count_files) { 426 399 int count = 0; 427 400 File file = ((FileNode)node).getFile(); 428 401 if(file.isFile() && count_files) { 429 402 count++; 430 403 } 431 404 else if(file.isDirectory() && count_folders) { 432 405 count++; 433 406 } 434 407 for(int i = 0; i < node.getChildCount(); i++) { 435 408 count = count + getCount(node.getChildAt(i), count_folders, count_files); 436 409 } 437 410 return count; 438 439 440 441 411 } 412 413 /** Method to retrieve the current import options associated with this Collection. */ 414 public Element getImportValues() { 442 415 Element import_values_element = null; 443 416 try { 444 445 446 447 448 417 Element document_element = document.getDocumentElement(); 418 Element build_config_element = (Element) MSMUtils.getNodeFromNamed(document_element, BUILD_CONFIG); 419 import_values_element = (Element) MSMUtils.getNodeFromNamed(build_config_element, IMPORT); 420 build_config_element = null; 421 document_element = null; 449 422 } 450 423 catch (Exception error) { 451 424 Gatherer.printStackTrace(error); 452 425 } 453 426 return import_values_element; 454 427 } 455 428 456 429 /** Set the value of a collection argument. */ 457 430 private void set(String name, boolean value) { 458 431 set(name, (value ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR)); 459 432 } 460 433 461 434 private void set(String name, String value) { 462 435 try { 463 436 Element document_element = document.getDocumentElement(); 464 437 NodeList arguments = document_element.getElementsByTagName(ARGUMENT); 465 438 boolean found = false; 466 439 for(int i = 0; !found && i < arguments.getLength(); i++) { 467 468 469 440 Element argument_element = (Element) arguments.item(i); 441 if(argument_element.getParentNode() == document_element) { 442 if(argument_element.getAttribute(NAME).equalsIgnoreCase(name)) { 470 443 // Strip any current value nodes. 471 444 while(argument_element.hasChildNodes()) { 472 445 argument_element.removeChild(argument_element.getFirstChild()); 473 446 } 474 447 // Append new value 475 448 argument_element.appendChild(document.createTextNode(value)); 476 449 found = true; 477 478 479 450 } 451 } 452 argument_element = null; 480 453 } 481 454 // Append it 482 455 if(!found) { 483 484 485 486 487 456 Element argument_element = document.createElement(ARGUMENT); 457 argument_element.setAttribute(NAME, name); 458 argument_element.appendChild(document.createTextNode(value)); 459 document_element.appendChild(argument_element); 460 argument_element = null; 488 461 } 489 462 arguments = null; 490 463 document_element = null; 491 492 464 } 465 catch (Exception error) { 493 466 Gatherer.printStackTrace(error); 494 467 } 495 468 } 496 469 } -
trunk/gli/src/org/greenstone/gatherer/collection/CollectionManager.java
r6026 r6051 47 47 import org.greenstone.gatherer.Gatherer; 48 48 import org.greenstone.gatherer.cdm.CollectionDesignManager; 49 import org.greenstone.gatherer.cdm.CollectionMeta; 50 import org.greenstone.gatherer.cdm.CollectionMetaManager; 49 51 import org.greenstone.gatherer.collection.Collection; 50 52 import org.greenstone.gatherer.collection.SaveCollectionTask; … … 380 382 updateCollectionCFG(new File(base_collection_directory, Utility.CONFIG_DIR), new File(a_dir, Utility.CONFIG_DIR), description, email, title); 381 383 } 382 384 383 385 // Always import the extracted metadata set if we didn't already 384 386 if(collection.msm.getSet(Utility.EXTRACTED_METADATA_NAMESPACE) == null) { 385 387 collection.msm.importMDS(new File(Utility.METADATA_DIR + Utility.EXTRACTED_METADATA_NAMESPACE + StaticStrings.METADATA_SET_EXTENSION), false); 386 388 } 387 389 388 390 collection.cdm = new CollectionDesignManager(new File(getCollectionConfig())); 391 392 // Now that we have a CDM, update several settings, such as if we created this collection by basing it on another, set it as public automatically 393 if(base_collection_directory != null) { 394 // Update the creator and maintainer 395 CollectionMeta creator_collectionmeta = new CollectionMeta(collection.cdm.collect_config.getCreator()); 396 creator_collectionmeta.setValue(email); 397 creator_collectionmeta = null; 398 CollectionMeta maintainer_collectionmeta = new CollectionMeta(collection.cdm.collect_config.getMaintainer()); 399 maintainer_collectionmeta.setValue(email); 400 maintainer_collectionmeta = null; 401 // Update the collection title 402 CollectionMeta collection_name_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR); 403 collection_name_collectionmeta.setValue(title); 404 collection_name_collectionmeta = null; 405 // And now the description 406 CollectionMeta collection_extra_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR); 407 collection_extra_collectionmeta.setValue(description); 408 collection_extra_collectionmeta = null; 409 // All collections based on others are automatically public 410 CollectionMeta public_collectionmeta = new CollectionMeta(collection.cdm.collect_config.getPublic()); 411 public_collectionmeta.setValue(StaticStrings.TRUE_STR); 412 public_collectionmeta = null; 413 // Finally reset the icons 414 CollectionMeta icon_collection_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR); 415 icon_collection_collectionmeta.setValue(StaticStrings.EMPTY_STR); 416 icon_collection_collectionmeta = null; 417 CollectionMeta icon_collection_small_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR); 418 icon_collection_small_collectionmeta.setValue(StaticStrings.EMPTY_STR); 419 icon_collection_small_collectionmeta = null; 420 } 421 389 422 collection.gdm = new GDMManager(); 390 423 … … 740 773 } 741 774 742 // Special case of a user trying to open an old greenstone collection. 775 // Special case of a user trying to open an old greenstone collection. 743 776 File metadata_directory = new File(collection_directory, Utility.META_DIR); 744 777 if(!metadata_directory.exists()) { 745 778 746 779 Gatherer.println("CollectionManager.loadCollection: trying to load up a non-gatherer collection"); 747 780 non_gatherer_collection = true; … … 758 791 dialog = null; 759 792 } 760 793 761 794 if(choice != LockFileDialog.YES_OPTION) { 762 795 // user has cancelled … … 766 799 } 767 800 768 801 769 802 try { 770 803 if(lock_file.exists()) { … … 787 820 msm = collection.msm; // Legacy 788 821 collection.msm.load(); 789 822 790 823 // if non-gatherer collection, need to add some metadata sets 791 824 if (non_gatherer_collection) { … … 798 831 } 799 832 } 800 833 801 834 collection.cdm = new CollectionDesignManager(new File(collection_file.getParent(), Utility.CONFIG_DIR)); 802 835 if (non_gatherer_collection) { … … 806 839 lci = null; 807 840 } 808 841 809 842 // Whether the collection is legacy or not, we should now be able to prepared the GDMManager 810 843 collection.gdm = new GDMManager(); 811 844 812 845 // Tell everyone that it worked. 813 846 String[] args = new String[1]; … … 836 869 } 837 870 } 838 871 839 872 lock_file = null; 840 873 collection_directory = null; 841 874 842 875 args2 = null; 843 876 return result; 844 877 } 845 878 846 879 /** I started giving the user the choice of using an existing meta set or creating a new one. The second option being so that they didn't have to add/merge/ignore each element, they could all be added automatically. However, I am not sure where the merge prompt gets called from, and it is not essential, so I am leaving it for now - it shoudl be added back in and finished. [kjdon] */ 847 880 private boolean addSomeMetadataSets(File collection_dir) { 848 849 881 882 850 883 ExternalCollectionPrompt external_prompt = new ExternalCollectionPrompt(); 851 884 int meta_choice = external_prompt.getMetadataChoice(); … … 853 886 if (cancelled) { 854 887 return false; 855 } 856 888 } 889 857 890 /*if (meta_choice == ExternalCollectionPrompt.NEW_META_SET) { 858 NewMetaSetPrompt nmsp = new NewMetaSetPrompt(); 891 NewMetaSetPrompt nmsp = new NewMetaSetPrompt(); 859 892 if (nmsp.isCancelled()) { 860 893 return false; … … 883 916 884 917 return true; 885 } 918 } 886 919 887 920 private boolean searchForMetadata(TreeModel collection_tree, FileNode current_node) { … … 1042 1075 else if(event.getStatus() == GShell.ERROR) { 1043 1076 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Preview_Ready_Failed"), Dictionary.get("CollectionManager.Preview_Ready_Title"), JOptionPane.ERROR_MESSAGE); 1044 Gatherer.g_man.collectionChanged(ready()); 1077 Gatherer.g_man.collectionChanged(ready()); 1045 1078 } 1046 1079 } … … 1084 1117 public void registerBuildMonitor(GShellProgressMonitor monitor) { 1085 1118 build_monitor = monitor; 1086 } 1119 } 1087 1120 /** This method associates the collection copy monitor with the copy monitor created in CreatePane. 1088 1121 * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the copy monitor. … … 1207 1240 Gatherer.println("Index = " + index_dir.getAbsolutePath()); 1208 1241 } 1209 1242 1210 1243 File build_dir = new File(getCollectionBuild(), "temp.txt"); 1211 1244 build_dir = build_dir.getParentFile(); … … 1287 1320 } 1288 1321 1289 private void updateCollectionCFG(File base_cfg, File new_cfg, String description, String email, String title) { 1290 boolean first_name = true; 1291 boolean first_extra = true; 1292 String collection_path = (base_cfg.getParentFile().getParentFile()).getAbsolutePath(); 1293 1294 HashMap mappings = collection.msm.profiler.getActions(collection_path); 1295 if(mappings == null) { 1296 Gatherer.println("Mappings is null, which is odd. Leaving all configuration commands which use metadata as they are."); 1297 } 1298 1299 // Now read in base_cfg line by line, parsing important onces and/or replacing them with information pertinent to our collection. Each line is then written back out to the new collect.cfg file. 1300 try { 1301 BufferedReader in = new BufferedReader(new FileReader(base_cfg)); 1302 BufferedWriter out = new BufferedWriter(new FileWriter(new_cfg, false)); // Overwrite whats there. 1303 String command = null; 1304 while((command = in.readLine()) != null) { 1305 // We have to test the end of command for the special character '\'. If found, remove it and append the next line, then repeat. 1306 while(command.trim().endsWith("\\")) { 1307 command = command.substring(0, command.lastIndexOf("\\")); 1308 String next_line = in.readLine(); 1309 if(next_line != null) { 1310 command = command + next_line; 1311 } 1322 private void updateCollectionCFG(File base_cfg, File new_cfg, String description, String email, String title) { 1323 boolean first_name = true; 1324 boolean first_extra = true; 1325 String collection_path = (base_cfg.getParentFile().getParentFile()).getAbsolutePath(); 1326 1327 HashMap mappings = collection.msm.profiler.getActions(collection_path); 1328 if(mappings == null) { 1329 Gatherer.println("Mappings is null, which is odd. Leaving all configuration commands which use metadata as they are."); 1312 1330 } 1313 ///ystem.err.println("Read: " + command); 1314 // Now we've finished parsing a line, determine what to do with it. 1315 String command_lc = command.toLowerCase(); 1316 // We replace the creator string with our own. 1317 if(command_lc.startsWith(Utility.CFG_CREATOR)) { 1318 ///ystem.err.println("Found creator - replace with current"); 1319 write(out, Utility.CFG_CREATOR + " " + email); 1320 } 1321 else if(command_lc.startsWith(Utility.CFG_MAINTAINER)) { 1322 ///ystem.err.println("Found maintainer - replace with current"); 1323 write(out, Utility.CFG_MAINTAINER + " " + email); 1324 } 1325 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONNAME)) { 1326 if(first_name) { 1327 write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONNAME + " \"" + title + "\""); 1328 first_name = false; 1329 } 1330 } 1331 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA)) { 1332 if(first_extra) { 1333 write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA + " \"" + description + "\""); 1334 first_extra = false; 1335 } 1336 } 1337 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_ICONCOLLECTION)) { 1338 write(out, Utility.CFG_COLLECTIONMETA_ICONCOLLECTION + " \"\""); 1339 } 1340 1331 1332 // Now read in base_cfg line by line, parsing important onces and/or replacing them with information pertinent to our collection. Each line is then written back out to the new collect.cfg file. 1333 try { 1334 BufferedReader in = new BufferedReader(new FileReader(base_cfg)); 1335 BufferedWriter out = new BufferedWriter(new FileWriter(new_cfg, false)); // Overwrite whats there. 1336 String command = null; 1337 while((command = in.readLine()) != null) { 1338 // We have to test the end of command for the special character '\'. If found, remove it and append the next line, then repeat. 1339 while(command.trim().endsWith("\\")) { 1340 command = command.substring(0, command.lastIndexOf("\\")); 1341 String next_line = in.readLine(); 1342 if(next_line != null) { 1343 command = command + next_line; 1344 } 1345 } 1346 ///ystem.err.println("Read: " + command); 1347 // Now we've finished parsing a line, determine what to do with it. 1348 String command_lc = command.toLowerCase(); 1349 // We replace the creator string with our own. 1350 /* 1351 if(command_lc.startsWith(Utility.CFG_CREATOR)) { 1352 ///ystem.err.println("Found creator - replace with current"); 1353 write(out, Utility.CFG_CREATOR + " " + email); 1354 } 1355 else if(command_lc.startsWith(Utility.CFG_MAINTAINER)) { 1356 ///ystem.err.println("Found maintainer - replace with current"); 1357 write(out, Utility.CFG_MAINTAINER + " " + email); 1358 } 1359 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONNAME)) { 1360 if(first_name) { 1361 write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONNAME + " \"" + title + "\""); 1362 first_name = false; 1363 } 1364 } 1365 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA)) { 1366 if(first_extra) { 1367 write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA + " \"" + description + "\""); 1368 first_extra = false; 1369 } 1370 } 1371 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_ICONCOLLECTION)) { 1372 write(out, Utility.CFG_COLLECTIONMETA_ICONCOLLECTION + " \"\""); 1373 } 1374 */ 1341 1375 // Just before we try more general parsing there are the special cases to check. These are explicit changes required by some collections to produce sensible results. 1342 elseif(special_case == SPECIAL_DLS && command_lc.equals("classify hierarchy -hfile azlist.txt -metadata azlist -sort title -buttonname title -hlist_at_top")) {1343 1344 }1345 else if(command_lc.startsWith(Utility.CFG_CLASSIFY)) {1376 if(special_case == SPECIAL_DLS && command_lc.equals("classify hierarchy -hfile azlist.txt -metadata azlist -sort title -buttonname title -hlist_at_top")) { 1377 write(out, "classify AZList -metadata dls.Title -buttonname Title"); 1378 } 1379 else if(command_lc.startsWith(Utility.CFG_CLASSIFY)) { 1346 1380 StringTokenizer tokenizer = new StringTokenizer(command); 1347 1381 StringBuffer text = new StringBuffer(tokenizer.nextToken()); -
trunk/gli/src/org/greenstone/gatherer/gui/CollectionPane.java
r5854 r6051 65 65 */ 66 66 public class CollectionPane 67 68 69 70 private DragGroup group= null;71 72 private DragTree collection_tree= null;73 74 private WorkspaceTree workspace_tree= null;75 76 private FileQueue file_queue= null;77 78 79 80 81 82 private TreeModel collection= null;83 84 private TreeModel workspace= null;85 86 private JButton stop_action= null;87 88 private JButton new_folder= null;89 90 private JLabel collection_label= null;91 92 private JLabel filename_label= null;93 94 private JLabel status_label= null;95 96 private JLabel workspace_label= null;97 98 private JPanel collection_pane= null;99 100 private JPanel control_pane= null;101 102 private JPanel workspace_pane= null;103 104 105 106 107 108 private JSplitPane tree_pane= null;109 110 private String args[]= null;111 112 113 114 115 116 private UndoManager bin_button= null;117 118 119 120 121 122 static private Dimension MIN_SIZE= new Dimension( 90, 90);123 124 125 126 127 128 129 130 131 132 133 67 extends JPanel 68 implements ActionListener, FocusListener { 69 /** The group encompassing all of the components available as drop targets for drag and drop actions. Required so that only one component renders the ghost and higlights itself as a target, which the other members are restored to their original, pristine, condition. */ 70 private DragGroup group = null; 71 /** The tree showing the files within the collection. */ 72 private DragTree collection_tree = null; 73 /** The tree showing the available source workspace. */ 74 private WorkspaceTree workspace_tree = null; 75 /** The threaded queue that handles the actually movement of files, so that the gui remains responsive. */ 76 private FileQueue file_queue = null; 77 /** The filter currently applied to the collection tree. */ 78 private Filter collection_filter = null; 79 /** The filter currently applied to the workspace tree. */ 80 private Filter workspace_filter = null; 81 /** The collection model which is used to build, and hold the data of, the collection tree. */ 82 private TreeModel collection = null; 83 /** The GTree model used as the data source for the workspace tree. */ 84 private TreeModel workspace = null; 85 /** The button used to cancel all pending file queue jobs. */ 86 private JButton stop_action = null; 87 /** The button used to create a new folder in the collection tree. */ 88 private JButton new_folder = null; 89 /** The label shown at the top of the collection tree. */ 90 private JLabel collection_label = null; 91 /** The label shown in the status area explaining the file apon which action is taking place. */ 92 private JLabel filename_label = null; 93 /** The label shown explaining the current state of the file queue thread. */ 94 private JLabel status_label = null; 95 /** The label at the top of the workspace tree. */ 96 private JLabel workspace_label = null; 97 /** The panel that contains the collection tree. */ 98 private JPanel collection_pane = null; 99 /** The panel that contains the various controls including the status area. */ 100 private JPanel control_pane = null; 101 /** The panel that contains the workspace tree. */ 102 private JPanel workspace_pane = null; 103 /** The scrollable area into which the collection tree is placed. */ 104 private JScrollPane collection_scroll = null; 105 /** The scrollable area into which the workspace tree is placed. */ 106 private JScrollPane workspace_scroll = null; 107 /** A split pane seperating the two trees, allowing for the screen real-estate for each to be changed. */ 108 private JSplitPane tree_pane = null; 109 /** Text fragment arguments used to fill in phrases returned from the dictionary. */ 110 private String args[] = null; 111 /** Ensures that expansion and selection events between collection trees based on the same model are synchronized. */ 112 private TreeSynchronizer collection_tree_sync = null; 113 /** Ensures that expansion and selection events between workspace trees based on the same model are synchronized. */ 114 private TreeSynchronizer workspace_tree_sync = null; 115 /** The button used to delete files, which also doubles as a drop target for files from the Trees. */ 116 private UndoManager bin_button = null; 117 /** The default size of a label in the interface. */ 118 static final private Dimension LABEL_SIZE = new Dimension(100,30); 119 /** The default size of a special mapping dialog. */ 120 static final Dimension DIALOG_SIZE = new Dimension(400, 120); 121 /** The minimum size a gui component can become. */ 122 static private Dimension MIN_SIZE = new Dimension( 90, 90); 123 /** The default size of the status area. */ 124 static private Dimension STATUS_SIZE = new Dimension(450, 120); 125 /** The initial size of the trees. */ 126 static private Dimension TREE_SIZE = new Dimension(400, 430); 127 128 /* Constructor. 129 * @param tree_sync Ensures that expansion events between like trees are synchronized. 130 * @see org.greenstone.gatherer.file.FileManager 131 * @see org.greenstone.gatherer.file.FileQueue 132 */ 133 public CollectionPane(TreeSynchronizer workspace_tree_sync, TreeSynchronizer collection_tree_sync) { 134 134 this.group = new DragGroup(); 135 135 this.file_queue = Gatherer.f_man.getQueue(); … … 149 149 new_folder.setPreferredSize(MIN_SIZE); 150 150 Dictionary.registerTooltip(new_folder, "Collection.New_Folder_Tooltip"); 151 152 153 154 151 } 152 153 /** Any implementation of ActionListener requires this method so that when an action is performed the appropriate effect can occur. In this case there are three valid possibilities. If the action occured on the recycle bin, then delete the current selection from the collection tree. If the action instead occured on the new folder button, then create a new folder under the current (single) selection in the collection tree. And finally if the cancel button was pressed, cancel the current, and remaining, jobs on the file queue. */ 154 public void actionPerformed(ActionEvent event) { 155 155 // If a user has clicked on the bin button directly remove whatever 156 156 // files are selected in the active tree. 157 157 if(event.getSource() == bin_button) { 158 158 if(!bin_button.ignore()) { 159 159 // Find the active tree (you've made selections in). 160 160 DragTree tree = (DragTree) group.getActive(); … … 164 164 TreePath paths[] = tree.getSelectionPaths(); 165 165 if(paths != null) { 166 167 166 FileNode[] source_nodes = new FileNode[paths.length]; 167 for(int i = 0; i < paths.length; i++) { 168 168 source_nodes[i] = (FileNode)(paths[i].getLastPathComponent()); 169 170 171 } 172 169 } 170 Gatherer.f_man.action(tree, source_nodes, bin_button, null); 171 } 172 } 173 173 } 174 174 // If a user has clicked on new_folder create a new folder under 175 175 // whatever node is selected. 176 176 else if(event.getSource() == new_folder && collection_tree != null) { 177 178 179 177 int count = collection_tree.getSelectionCount(); 178 boolean error = false; 179 if(count == 1) { 180 180 TreePath path = collection_tree.getSelectionPath(); 181 181 FileNode node = (FileNode) path.getLastPathComponent(); 182 182 if(node.getAllowsChildren()) { 183 183 Gatherer.f_man.newFolder(collection_tree, node); 184 184 } 185 185 else { 186 187 188 186 // try the parent 187 FileNode parent = (FileNode)node.getParent(); 188 if (parent!=null && parent.getAllowsChildren()) { 189 189 Gatherer.f_man.newFolder(collection_tree, parent); 190 190 } else { 191 191 error = true; 192 193 } 194 195 192 } 193 } 194 } 195 else { 196 196 error = true; 197 198 197 } 198 if(error) { 199 199 // instead of an error, we now create a new folder at the root 200 200 FileNode node = (FileNode) collection_tree.getModel().getRoot(); 201 201 Gatherer.f_man.newFolder(collection_tree, node); 202 202 //JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("FileActions.No_Parent_For_New_Folder"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); 203 203 } 204 204 } 205 205 else if(event.getSource() == stop_action) { 206 207 } 208 209 210 211 212 213 214 215 216 217 218 206 file_queue.cancelAction(); 207 } 208 } 209 /** Called whenever a significant change occurs in the current collections state, such as a new collection being loaded or the current one being closed. Several actions must occur in the GUI to indicate this change to the user, such as en/disabling the collection tree. 210 * @param ready <i>true</i> if a collection is loaded and ready to be modified, <i>false</i> otherwise. 211 * @see org.greenstone.gatherer.Configuration 212 * @see org.greenstone.gatherer.Gatherer 213 * @see org.greenstone.gatherer.collection.CollectionManager 214 * @see org.greenstone.gatherer.gui.Coloring 215 * @see org.greenstone.gatherer.gui.Filter 216 * @see org.greenstone.gatherer.util.TreeSynchronizer 217 */ 218 public void collectionChanged(boolean ready) { 219 219 // Try to retrieve the collections record set. 220 220 collection = Gatherer.c_man.getRecordSet(); 221 221 if(collection != null) { 222 223 224 Dictionary.registerText(collection_label, "Collection.Collection", args);225 226 227 222 //args = new String[1]; 223 //args[0] = Gatherer.c_man.getCollection().getName(); 224 Dictionary.registerText(collection_label, "Collection.Collection"); 225 collection_tree.setModel(collection); 226 collection_tree.repaint(); 227 collection_filter.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false)); 228 228 } 229 229 else { 230 231 232 233 234 235 230 String args[] = new String[1]; 231 args[0] = Dictionary.get("Collection.No_Collection"); 232 Dictionary.registerText(collection_label, "Collection.Collection", args); 233 args = null; 234 collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode("Error"))); 235 collection_filter.setBackground(Color.lightGray); 236 236 } 237 237 collection_tree.setEnabled(ready); … … 251 251 stop_action.setEnabled(ready); 252 252 new_folder.setEnabled(ready); 253 254 255 256 253 } 254 255 /** Generates the pane on controls used to 'collect' files into the collection. Resposible for creating, connecting and laying out these controls. */ 256 public void display() { 257 257 // Create Components. 258 258 KeyListenerImpl key_listener = new KeyListenerImpl(); … … 306 306 collection_pane.setSize(TREE_SIZE); 307 307 308 args = new String[1];309 args[0] = Dictionary.get("Collection.No_Collection");308 //args = new String[1]; 309 //args[0] = Dictionary.get("Collection.No_Collection"); 310 310 collection_label = new JLabel(); 311 311 collection_label.setOpaque(true); 312 Dictionary.registerText(collection_label, "Collection. Collection", args);312 Dictionary.registerText(collection_label, "Collection.No_Collection"); 313 313 314 314 collection = Gatherer.c_man.getRecordSet(); 315 315 if(collection != null) { 316 317 316 collection_tree = new DragTree(Utility.COLLECTION_TREE, collection, null, true); 317 collection_tree.setEnabled(true); 318 318 } 319 319 else { 320 321 320 collection_tree = new DragTree(Utility.COLLECTION_TREE, null, true); 321 collection_tree.setEnabled(false); 322 322 } 323 323 group.add(collection_tree); … … 340 340 collection_filter = Gatherer.g_man.getFilter(collection_tree); 341 341 if(collection != null) { 342 342 collection_filter.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false)); 343 343 } 344 344 else { 345 345 collection_filter.setBackground(Color.lightGray); 346 346 } 347 347 // Change the default colours of this filters combobox. … … 427 427 this.add(tree_pane, BorderLayout.CENTER); 428 428 this.add(control_pane, BorderLayout.SOUTH); 429 430 431 429 } 430 /** This method ensures that a certain tree path is visible and selected within the collection tree, expanding nodes if necessary. If the method is successful the bounds of the new selection are returned. */ 431 public Rectangle expandPath(TreePath path) { 432 432 collection_tree.setImmediate(true); 433 433 collection_tree.scrollPathToVisible(path); … … 435 435 collection_tree.setImmediate(false); 436 436 return collection_tree.getRowBounds(collection_tree.getRowForPath(path)); 437 438 439 440 441 437 } 438 /** Called whenever this pane gains focus, this method ensures that the various tree renderers are correctly colouring the tree (as these settings sometimes get lost). 439 * @param event A <strong>FocusEvent</strong> containing details about the focus action performed. 440 */ 441 public void focusGained(FocusEvent event) { 442 442 DefaultTreeCellRenderer def = new DefaultTreeCellRenderer(); 443 443 DefaultTreeCellRenderer w = (DefaultTreeCellRenderer)workspace_tree.getCellRenderer(); 444 444 DefaultTreeCellRenderer c = (DefaultTreeCellRenderer)collection_tree.getCellRenderer(); 445 445 if(event.getSource() == workspace_tree) { 446 447 446 w.setBackgroundSelectionColor(def.getBackgroundSelectionColor()); 447 c.setBackgroundSelectionColor(Color.lightGray); 448 448 } 449 449 else if(event.getSource() == collection_tree) { 450 451 450 c.setBackgroundSelectionColor(def.getBackgroundSelectionColor()); 451 w.setBackgroundSelectionColor(Color.lightGray); 452 452 } 453 453 repaint(); 454 455 456 457 458 459 460 461 462 463 464 454 } 455 /** Implementation side-effect, not used in any way. 456 * @param event A <strong>FocusEvent</strong> containing details about the focus action performed. 457 */ 458 public void focusLost(FocusEvent event) { 459 } 460 461 /** Called to inform this control panel that it has just gained focus as an effect of the user clicking on its tab. 462 * @see org.greenstone.gatherer.tree.GTree 463 */ 464 public void gainFocus() { 465 465 // Update the menubar's idea of whats been selected 466 466 if (collection_tree != null) { 467 467 if (collection_tree.isSelectionEmpty()) { 468 468 Gatherer.g_man.menu_bar.setMetaAuditSuffix(null); 469 470 469 } 470 else { 471 471 Gatherer.g_man.menu_bar.setMetaAuditSuffix(collection_tree.getSelectionDetails()); 472 472 } 473 473 } 474 474 // Update the meta-audit view to show the current selection, if any. 475 475 Gatherer.g_man.meta_audit.setRecords(getSelected()); 476 477 478 479 476 } 477 478 /** Retrieve a list of the currently selected file records in the active tree. */ 479 public FileNode[] getSelected() { 480 480 TreePath paths[] = collection_tree.getSelectionPaths(); 481 481 FileNode records[] = null; 482 482 if(paths != null) { 483 484 483 records = new FileNode[paths.length]; 484 for(int i = 0; i < records.length; i++) { 485 485 records[i] = (FileNode) paths[i].getLastPathComponent(); 486 486 } 487 487 } 488 488 return records; 489 490 491 489 } 490 491 public String getSelectionDetails() { 492 492 return collection_tree.getSelectionDetails(); 493 494 495 496 497 493 } 494 495 496 public void refreshCollectionTree(int refresh_reason) 497 { 498 498 collection_tree.refresh(null); 499 500 501 502 503 499 } 500 501 502 public void refreshWorkspaceTree(int refresh_reason) 503 { 504 504 workspace_tree.refresh(refresh_reason); 505 506 507 508 509 510 511 512 513 514 505 } 506 507 508 /** Used to set the enabled state, and hence the colouring, of the two tree labels. 509 * @param label The <strong>JLabel</strong> to be affected. 510 * @param state <i>true</i> for enabled, i.e. when a collection is ready, <i>false</i> otherwise. 511 * @param foreground The <strong>Color</strong> to make the foreground text of the label when enabled. 512 * @param background The <strong>Color</strong> to make the background of the label when enabled. 513 */ 514 private void setEnabled(JLabel label, boolean state, Color foreground, Color background) { 515 515 ///ystem.err.println("Setting the label color to state " + state); 516 516 if(state) { 517 518 517 label.setBackground(background); 518 label.setForeground(foreground); 519 519 } 520 520 else { 521 522 521 label.setBackground(Color.lightGray); 522 label.setForeground(Color.black); 523 523 } 524 524 label.repaint(); 525 525 ///ystem.err.println("Color is now " + label.getBackground()); 526 } 527 528 /** When a user right-clicks within the trees on the collection pane view they are presented with a small popup menu of context based options. This class provides such functionality. 529 */ 530 private class GPopupMenu 531 extends JPopupMenu 532 implements ActionListener { 533 /** The tree over which the right click action occured. */ 534 private DragTree tree = null; 535 /** The file record over which the right click action occured, if any. */ 536 private FileNode node = null; 537 /** A menu item enabled if a delete action is appropriate in the menus current context. */ 538 private JMenuItem delete = null; 539 /** A menu item enabled if a special directory mapping is appropriate in the menus current context. */ 540 private JMenuItem map = null; 541 /** A menu item enabled if a new folder action is appropriate in the menus current context. */ 542 private JMenuItem new_folder = null; 543 /** A menu item enabled if a show meta-audit dialog action is appropriate in the menus current context. */ 544 private JMenuItem show_metaaudit = null; 545 /** A menu item allowing a user to unmap a special directory, if and only if a special directory is selected. */ 546 private JMenuItem unmap = null; 547 /** Constructor. */ 548 public GPopupMenu(DragTree tree, MouseEvent event) { 549 super(); 550 this.tree = tree; 551 TreePath path = tree.getClosestPathForLocation(event.getX(), event.getY()); 552 if(path != null) { 553 node = (FileNode)path.getLastPathComponent(); 554 // Set Options based on selection and tree 555 if(tree.getSelectionCount() != 0 && tree == collection_tree) { 556 String[] args = new String[1]; 557 args[0] = collection_tree.getSelectionDetails(); 558 show_metaaudit = new JMenuItem(Dictionary.get("Menu.Metadata_View", args), KeyEvent.VK_V); 559 show_metaaudit.addActionListener(this); 560 add(show_metaaudit); 561 } 562 if(tree == collection_tree && node != null && node.getFile() != null && node.getFile().isDirectory() && !node.isReadOnly()) { 563 new_folder = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Folder"), KeyEvent.VK_N); 564 new_folder.addActionListener(this); 565 add(new_folder); 566 add(new JSeparator()); 567 } 568 if(tree == collection_tree && tree.getSelectionCount() != 0 && node != null && !node.isReadOnly()) { 569 delete = new JMenuItem(Dictionary.get("CollectionPopupMenu.Delete"), KeyEvent.VK_D); 570 delete.addActionListener(this); 571 add(delete); 572 } 573 if(tree == workspace_tree && node != null && !node.isLeaf()) { 574 String node_name = node.toString(); 575 FileNode root = (FileNode) tree.getModel().getRoot(); 576 if(!node_name.equals(Dictionary.get("Tree.World")) && !node_name.equals(Dictionary.get("Tree.Root")) && !node_name.equals(Dictionary.get("Tree.Public")) && !node_name.equals(Dictionary.get("Tree.Private"))) { 577 // You can unmap 1st level nodes. 578 if(root.getIndex(node) != -1) { 579 unmap = new JMenuItem(Dictionary.get("MappingPrompt.Unmap"), KeyEvent.VK_U); 580 unmap.addActionListener(this); 581 add(unmap); 526 } 527 528 /** When a user right-clicks within the trees on the collection pane view they are presented with a small popup menu of context based options. This class provides such functionality. 529 */ 530 private class GPopupMenu 531 extends JPopupMenu 532 implements ActionListener { 533 534 /** The tree over which the right click action occured. */ 535 private DragTree tree = null; 536 /** The file record over which the right click action occured, if any. */ 537 private FileNode node = null; 538 private JMenuItem collapse_expand_folder_menuitem; 539 /** A menu item enabled if a delete action is appropriate in the menus current context. */ 540 private JMenuItem delete = null; 541 /** A menu item enabled if a special directory mapping is appropriate in the menus current context. */ 542 private JMenuItem map = null; 543 /** A menu item enabled if a new folder action is appropriate in the menus current context. */ 544 private JMenuItem new_folder = null; 545 /** A menu item enabled if a show meta-audit dialog action is appropriate in the menus current context. */ 546 private JMenuItem show_metaaudit = null; 547 /** A menu item allowing a user to unmap a special directory, if and only if a special directory is selected. */ 548 private JMenuItem unmap = null; 549 private TreePath path = null; 550 /** Constructor. */ 551 public GPopupMenu(DragTree tree, MouseEvent event) { 552 super(); 553 this.tree = tree; 554 this.path = tree.getClosestPathForLocation(event.getX(), event.getY()); 555 if(path != null) { 556 node = (FileNode)path.getLastPathComponent(); 557 // Any folder node gets a menu item allowing you to collapse or expand it depending on its current status 558 if(!node.isLeaf()) { 559 // Collapse 560 if(tree.isExpanded(path)) { 561 collapse_expand_folder_menuitem = new JMenuItem(Dictionary.get("Menu.Collapse"), KeyEvent.VK_C); 562 } 563 // Expand 564 else { 565 collapse_expand_folder_menuitem = new JMenuItem(Dictionary.get("Menu.Expand"), KeyEvent.VK_O); 566 } 567 collapse_expand_folder_menuitem.addActionListener(this); 568 add(collapse_expand_folder_menuitem); 569 } 570 // Set Options based on selection and tree 571 if(tree.getSelectionCount() != 0 && tree == collection_tree) { 572 String[] args = new String[1]; 573 args[0] = collection_tree.getSelectionDetails(); 574 show_metaaudit = new JMenuItem(Dictionary.get("Menu.Metadata_View", args), KeyEvent.VK_V); 575 show_metaaudit.addActionListener(this); 576 add(show_metaaudit); 577 } 578 if(tree == collection_tree && node != null && node.getFile() != null && node.getFile().isDirectory() && !node.isReadOnly()) { 579 new_folder = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Folder"), KeyEvent.VK_N); 580 new_folder.addActionListener(this); 581 add(new_folder); 582 add(new JSeparator()); 583 } 584 if(tree == collection_tree && tree.getSelectionCount() != 0 && node != null && !node.isReadOnly()) { 585 delete = new JMenuItem(Dictionary.get("CollectionPopupMenu.Delete"), KeyEvent.VK_D); 586 delete.addActionListener(this); 587 add(delete); 588 } 589 if(tree == workspace_tree && node != null && !node.isLeaf()) { 590 String node_name = node.toString(); 591 FileNode root = (FileNode) tree.getModel().getRoot(); 592 if(!node_name.equals(Dictionary.get("Tree.World")) && !node_name.equals(Dictionary.get("Tree.Root")) && !node_name.equals(Dictionary.get("Tree.Public")) && !node_name.equals(Dictionary.get("Tree.Private"))) { 593 // You can unmap 1st level nodes. 594 if(root.getIndex(node) != -1) { 595 unmap = new JMenuItem(Dictionary.get("MappingPrompt.Unmap"), KeyEvent.VK_U); 596 unmap.addActionListener(this); 597 add(unmap); 598 } 599 // Or map any other level directories. 600 else { 601 map = new JMenuItem(Dictionary.get("MappingPrompt.Map"), KeyEvent.VK_M); 602 map.addActionListener(this); 603 add(map); 604 } 605 } 606 } 607 show(tree, event.getX(), event.getY()); 608 } 582 609 } 583 // Or map any other level directories. 584 else { 585 map = new JMenuItem(Dictionary.get("MappingPrompt.Map"), KeyEvent.VK_M); 586 map.addActionListener(this); 587 add(map); 610 611 /** Called whenever one of the menu items is actioned apon, this method then causes the appropriate effect. */ 612 public void actionPerformed(ActionEvent event) { 613 Object source = event.getSource(); 614 if(source == delete) { 615 // Retrieve the selection. Of course this gets a bit tricky as the user may have right clicked over a node not in the current selection, in which case we remove only that node. 616 TreePath[] selection_paths = tree.getSelectionPaths(); 617 if(selection_paths != null) { 618 FileNode[] source_nodes = new FileNode[selection_paths.length]; 619 boolean found = false; 620 for(int i = 0; i < selection_paths.length; i++) { 621 source_nodes[i] = (FileNode) selection_paths[i].getLastPathComponent(); 622 if(node != null) { 623 found = found || source_nodes[i].equals(node); 624 } 625 } 626 if(node != null && !found) { 627 source_nodes = null; 628 source_nodes = new FileNode[1]; 629 source_nodes[0] = node; 630 } 631 // Fire a delete action 632 Gatherer.f_man.action(tree, source_nodes, bin_button, null); 633 source_nodes = null; 634 } 635 selection_paths = null; 636 } 637 else if(source == map && node != null) { 638 MappingPrompt mp = new MappingPrompt(node.getFile()); 639 mp.destroy(); 640 mp = null; 641 } 642 else if(source == new_folder && node != null) { 643 Gatherer.f_man.newFolder(tree, node); 644 } 645 else if(source == show_metaaudit) { 646 Gatherer.g_man.showMetaAuditBox(); 647 } 648 else if(source == unmap && node != null) { 649 Gatherer.c_man.removeDirectoryMapping(node); 650 } 651 else if(source == collapse_expand_folder_menuitem && path != null && node != null && !node.isLeaf()) { 652 // Collapse 653 if(tree.isExpanded(path)) { 654 tree.collapsePath(path); 655 } 656 // Expand 657 else { 658 tree.expandPath(path); 659 } 660 } 588 661 } 589 } 590 } 591 show(tree, event.getX(), event.getY()); 592 } 593 } 594 /** Called whenever one of the menu items is actioned apon, this method then causes the appropriate effect. */ 595 public void actionPerformed(ActionEvent event) { 596 if(event.getSource() == delete) { 597 // Retrieve the selection. Of course this gets a bit tricky as the user may have right clicked over a node not in the current selection, in which case we remove only that node. 598 TreePath[] selection_paths = tree.getSelectionPaths(); 599 if(selection_paths != null) { 600 FileNode[] source_nodes = new FileNode[selection_paths.length]; 601 boolean found = false; 602 for(int i = 0; i < selection_paths.length; i++) { 603 source_nodes[i] = (FileNode) selection_paths[i].getLastPathComponent(); 604 if(node != null) { 605 found = found || source_nodes[i].equals(node); 606 } 607 } 608 if(node != null && !found) { 609 source_nodes = null; 610 source_nodes = new FileNode[1]; 611 source_nodes[0] = node; 612 } 613 // Fire a delete action 614 Gatherer.f_man.action(tree, source_nodes, bin_button, null); 615 source_nodes = null; 616 } 617 selection_paths = null; 618 } 619 else if(event.getSource() == map && node != null) { 620 MappingPrompt mp = new MappingPrompt(node.getFile()); 621 mp.destroy(); 622 mp = null; 623 } 624 else if(event.getSource() == new_folder && node != null) { 625 Gatherer.f_man.newFolder(tree, node); 626 } 627 else if(event.getSource() == show_metaaudit) { 628 Gatherer.g_man.showMetaAuditBox(); 629 } 630 else if(event.getSource() == unmap && node != null) { 631 Gatherer.c_man.removeDirectoryMapping(node); 632 } 633 } 634 } 635 636 /** This class listens for certain key presses, such as [Enter] or [Delete], and responds appropriately. */ 637 private class KeyListenerImpl 662 } 663 664 /** This class listens for certain key presses, such as [Enter] or [Delete], and responds appropriately. */ 665 private class KeyListenerImpl 638 666 extends KeyAdapter { 639 667 /** Called whenever a key that was pressed is released, it is this action that will cause the desired effects (this allows for the key event itself to be processed prior to this listener dealing with it). */ 640 668 public void keyReleased(KeyEvent event) { 641 669 ///ystem.err.println("Key Release detected. " + event.getKeyCode()); 642 670 if(event.getKeyCode() == KeyEvent.VK_DELETE) { 643 671 // Get the selected files from the tree and removal them using the default dnd removal method. 644 672 // Find the active tree (you've made selections in). … … 649 677 TreePath paths[] = tree.getSelectionPaths(); 650 678 if(paths != null) { 651 652 679 FileNode[] source_nodes = new FileNode[paths.length]; 680 for(int i = 0; i < source_nodes.length; i++) { 653 681 source_nodes[i] = (FileNode) paths[i].getLastPathComponent(); 654 655 656 657 } 658 659 682 } 683 Gatherer.f_man.action(tree, source_nodes, bin_button, null); 684 source_nodes = null; 685 } 686 } 687 else if(event.getKeyCode() == KeyEvent.VK_ENTER) { 660 688 // Get the first selected file. 661 689 DragTree tree = (DragTree)event.getSource(); 662 690 TreePath path = tree.getSelectionPath(); 663 691 if(path != null) { 664 665 692 File file = ((FileNode)path.getLastPathComponent()).getFile(); 693 if(file != null && file.isFile()) { 666 694 Gatherer.self.spawnApplication(file); 667 }668 else {669 if(!tree.isExpanded(path)) {670 tree.expandPath(path);671 695 } 672 696 else { 673 tree.collapsePath(path); 697 if(!tree.isExpanded(path)) { 698 tree.expandPath(path); 674 699 } 675 } 676 } 677 } 678 } 679 } 680 681 /** This provides a small prompt for gathering addition details about a special directory mapping such as its symbolic name. */ 682 private class MappingPrompt 700 else { 701 tree.collapsePath(path); 702 } 703 } 704 } 705 } 706 } 707 } 708 709 /** This provides a small prompt for gathering addition details about a special directory mapping such as its symbolic name. */ 710 private class MappingPrompt 683 711 extends JDialog 684 712 implements ActionListener, KeyListener { … … 688 716 private JTextField name_field = null; 689 717 public MappingPrompt(File file) { 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 718 super(Gatherer.g_man); 719 setModal(true); 720 setSize(DIALOG_SIZE); 721 Dictionary.setText(this, "MappingPrompt.Title"); 722 723 // Creation 724 JPanel content_pane = (JPanel) getContentPane(); 725 JPanel center_pane = new JPanel(); 726 JPanel file_pane = new JPanel(); 727 JLabel file_label = new JLabel(); 728 file_label.setPreferredSize(LABEL_SIZE); 729 Dictionary.setText(file_label, "MappingPrompt.File"); 730 JLabel file_field = new JLabel(file.getAbsolutePath()); 731 JPanel name_pane = new JPanel(); 732 JLabel name_label = new JLabel(); 733 name_label.setPreferredSize(LABEL_SIZE); 734 Dictionary.setText(name_label, "MappingPrompt.Name"); 735 name_field = new JTextField(file.getName()); 736 JPanel button_pane = new JPanel(); 737 ok_button = new JButton(); 738 ok_button.setEnabled(name_field.getText().length() > 0); 739 Dictionary.setBoth(ok_button, "General.OK", "General.OK_Tooltip"); 740 cancel_button = new JButton(); 741 Dictionary.setBoth(cancel_button, "General.Cancel", "General.Cancel_Tooltip"); 742 743 // Connection 744 cancel_button.addActionListener(this); 745 ok_button.addActionListener(this); 746 name_field.addKeyListener(this); 747 // Layout 748 file_pane.setLayout(new BorderLayout()); 749 file_pane.add(file_label, BorderLayout.WEST); 750 file_pane.add(file_field, BorderLayout.CENTER); 751 752 name_pane.setLayout(new BorderLayout()); 753 name_pane.add(name_label, BorderLayout.WEST); 754 name_pane.add(name_field, BorderLayout.CENTER); 755 756 center_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); 757 center_pane.setLayout(new GridLayout(2,1,5,5)); 758 center_pane.add(file_pane); 759 center_pane.add(name_pane); 760 761 button_pane.setLayout(new GridLayout(1,2,5,5)); 762 button_pane.add(ok_button); 763 button_pane.add(cancel_button); 764 765 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 766 content_pane.setLayout(new BorderLayout()); 767 content_pane.add(center_pane, BorderLayout.CENTER); 768 content_pane.add(button_pane, BorderLayout.SOUTH); 769 // Display 770 Dimension screen_size = Gatherer.config.screen_size; 771 setLocation((screen_size.width - DIALOG_SIZE.width) / 2, (screen_size.height - DIALOG_SIZE.height) / 2); 772 show(); 773 // If not cancelled create mapping. 774 if(!cancelled) { 747 775 Gatherer.c_man.addDirectoryMapping(name_field.getText(), file); 748 776 } 749 777 } 750 778 public void actionPerformed(ActionEvent event) { 751 779 if(event.getSource() == cancel_button) { 752 780 cancelled = true; 753 754 781 } 782 dispose(); 755 783 } 756 784 public void destroy() { 757 758 759 785 cancel_button = null; 786 ok_button = null; 787 name_field = null; 760 788 } 761 789 public void keyPressed(KeyEvent event) { 762 790 } 763 791 public void keyReleased(KeyEvent event) { 764 792 ok_button.setEnabled(name_field.getText().length() > 0); 765 793 766 794 } 767 795 public void keyTyped(KeyEvent event) { 768 796 } 769 770 771 797 } 798 /** This class listens for mouse clicks and responds right mouse button clicks (popup menu). */ 799 private class MouseListenerImpl 772 800 extends MouseAdapter { 773 801 /** Any subclass of MouseAdapter can override this method to respond to mouse click events. In this case we want to open a pop-up menu if we detect a right mouse click over one of our registered components, and start an external application if someone double clicks on a certain file record. */ 774 802 public void mouseClicked(MouseEvent event) { 775 803 if(SwingUtilities.isRightMouseButton(event)) { 776 804 new GPopupMenu((DragTree)event.getSource(), event); 777 778 } 779 805 } 806 } 807 } 780 808 } -
trunk/gli/src/org/greenstone/gatherer/gui/Filter.java
r5772 r6051 74 74 static final private Dimension SIZE = new Dimension(100,25); 75 75 /** Preprogrammed default filters. */ 76 static final private String DEFAULTS[] = {"^.*\\.html?$", "^.*\\.xml$", "^.*\\.txt$", "(^.*\\.jpe?g$)|(^.*\\.png$)|(^. \\.gif$)|(^.\\.bmp$)|(^.\\.tif$)"};76 static final private String DEFAULTS[] = {"^.*\\.html?$", "^.*\\.xml$", "^.*\\.txt$", "(^.*\\.jpe?g$)|(^.*\\.png$)|(^.*\\.gif$)|(^.*\\.bmp$)|(^.*\\.tif$)"}; 77 77 78 78 /** Constructor. … … 129 129 } 130 130 131 /** Used to restore the filter state to enabled, the normal state during collection editing. 131 /** Used to restore the filter state to enabled, the normal state during collection editing. 132 132 * @param state The new state for the filter. <i>true</i> for enabled, <i>false</i> otherwise. 133 133 */ … … 282 282 } 283 283 /** An object that holds a filter entry. This is string used for the filter pattern and, if not custom built, its name. */ 284 private class Entry 284 private class Entry 285 285 implements Comparable { 286 286 /** The compiled pattern created from a regular expression. */ -
trunk/gli/src/org/greenstone/gatherer/gui/GUIManager.java
r6040 r6051 202 202 } 203 203 else if(esrc == menu_bar.file_options) { 204 // Just incase the user has edited the GeneralSettings of a collection without losing focus afterwards. Well I'm forever losing foc... ooh shiney. 205 config_pane.loseFocus(); 206 // And spawn a new preferences. 204 207 new Preferences(); 205 208 } … … 459 462 460 463 preview_pane = new PreviewPane(); 461 preview_pane.display(); 462 if(Gatherer.config.get("workflow.preview", true)) { 464 preview_pane.display(); 465 if(Gatherer.config.get("workflow.preview", true)) { 463 466 tab_pane.addTab("GUI.Preview", Utility.getImage("final.gif"), preview_pane); 464 467 tab_pane.setEnabledAt(tab_pane.indexOfComponent(preview_pane), false); -
trunk/gli/src/org/greenstone/gatherer/gui/MetaEditPane.java
r6027 r6051 234 234 this.element = element; 235 235 // Transform the raw text to be GREENSTONE and DOM compatible - as that will be its next destination immediately after being added to the value model 236 this.value = Codec.transform(value, Codec.ENCODE_PATH); 236 this.value = Codec.transform(value, Codec.ENCODE_PATH); 237 237 this.value = Codec.transform(this.value, Codec.REMOVE_SQUARE_BRACKET); 238 238 this.value = Codec.transform(this.value, Codec.TEXT_TO_DOM); … … 335 335 if(ready) { 336 336 TreeModel collection_model = Gatherer.c_man.getRecordSet(); 337 String[] args = new String[1];338 args[0] = Gatherer.c_man.getCollection().getName();339 Dictionary.registerText(collection_label, "Collection.Collection" , args);337 //String[] args = new String[1]; 338 //args[0] = Gatherer.c_man.getCollection().getName(); 339 Dictionary.registerText(collection_label, "Collection.Collection"); 340 340 // Update label coloring. 341 341 collection_label.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false)); … … 389 389 ///atherer.println("\tCreating collection_label"); 390 390 collection_label = new JLabel(); 391 Dictionary.registerText(collection_label, "Collection. Collection");391 Dictionary.registerText(collection_label, "Collection.No_Collection"); 392 392 collection_label.setOpaque(true); 393 393 … … 972 972 973 973 974 /** Provides a popup menu to display when a right mouse button click is detected over the collection tree. */ 975 private class RightButtonMenu 976 extends JPopupMenu 977 implements ActionListener { 978 /** Constructor. 979 * @param event The <strong>MouseEvent</strong> that triggered the creation of this menu. Used to determine where the menu will be located. 980 */ 981 private RightButtonMenu(MouseEvent event) { 982 super(); 983 // Creation 984 String[] args = new String[1]; 985 args[0] = collection_tree.getSelectionDetails(); 986 JMenuItem show_metaaudit = new JMenuItem(Dictionary.get("Menu.Metadata_View", args), KeyEvent.VK_V); 987 show_metaaudit.addActionListener(this); 988 add(show_metaaudit); 989 // Display 990 show(collection_tree, event.getX(), event.getY()); 991 show_metaaudit = null; 992 } 993 994 /** Called whenever a user clicks on the single menu item, view all assigned metadata. 995 * @param event An <strong>ActionEvent</strong> containing further information about the action. 996 * @see org.greenstone.gatherer.Gatherer 997 * @see org.greenstone.gatherer.gui.GUIManager 998 */ 999 public void actionPerformed(ActionEvent event) { 1000 Gatherer.g_man.showMetaAuditBox(); 1001 } 1002 } 974 /** Provides a popup menu to display when a right mouse button click is detected over the collection tree. */ 975 private class RightButtonMenu 976 extends JPopupMenu 977 implements ActionListener { 978 979 private FileNode node; 980 private JMenuItem collapse_expand_folder_menuitem; 981 private JMenuItem show_metaaudit; 982 private TreePath path; 983 984 /** Constructor. 985 * @param event The <strong>MouseEvent</strong> that triggered the creation of this menu. Used to determine where the menu will be located. 986 */ 987 private RightButtonMenu(MouseEvent event) { 988 super(); 989 this.path = collection_tree.getClosestPathForLocation(event.getX(), event.getY()); 990 this.node = (FileNode)path.getLastPathComponent(); 991 // Creation 992 // Any folder node gets a menu item allowing you to collapse or expand it depending on its current status 993 if(!node.isLeaf()) { 994 // Collapse 995 if(collection_tree.isExpanded(path)) { 996 collapse_expand_folder_menuitem = new JMenuItem(Dictionary.get("Menu.Collapse"), KeyEvent.VK_C); 997 } 998 // Expand 999 else { 1000 collapse_expand_folder_menuitem = new JMenuItem(Dictionary.get("Menu.Expand"), KeyEvent.VK_O); 1001 } 1002 collapse_expand_folder_menuitem.addActionListener(this); 1003 add(collapse_expand_folder_menuitem); 1004 } 1005 String[] args = new String[1]; 1006 args[0] = collection_tree.getSelectionDetails(); 1007 show_metaaudit = new JMenuItem(Dictionary.get("Menu.Metadata_View", args), KeyEvent.VK_V); 1008 show_metaaudit.addActionListener(this); 1009 add(show_metaaudit); 1010 // Display 1011 show(collection_tree, event.getX(), event.getY()); 1012 show_metaaudit = null; 1013 } 1014 1015 /** Called whenever a user clicks on the single menu item, view all assigned metadata. 1016 * @param event An <strong>ActionEvent</strong> containing further information about the action. 1017 * @see org.greenstone.gatherer.Gatherer 1018 * @see org.greenstone.gatherer.gui.GUIManager 1019 */ 1020 public void actionPerformed(ActionEvent event) { 1021 Object source = event.getSource(); 1022 if(source == show_metaaudit) { 1023 Gatherer.g_man.showMetaAuditBox(); 1024 } 1025 else if(source == collapse_expand_folder_menuitem && path != null && node != null && !node.isLeaf()) { 1026 // Collapse 1027 if(collection_tree.isExpanded(path)) { 1028 collection_tree.collapsePath(path); 1029 } 1030 // Expand 1031 else { 1032 collection_tree.expandPath(path); 1033 } 1034 } 1035 } 1036 } 1003 1037 1004 1038 -
trunk/gli/src/org/greenstone/gatherer/gui/NewCollectionDetailsPrompt.java
r6041 r6051 1 /** 2 *######################################################################### 3 * 4 * A component of the Gatherer application, part of the Greenstone digital 5 * library suite from the New Zealand Digital Library Project at the 6 * University of Waikato, New Zealand. 7 * 8 * Author: John Thompson, Greenstone Digital Library, University of Waikato 9 * 10 * Copyright (C) 1999 New Zealand Digital Library Project 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 *######################################################################## 26 */ 1 27 package org.greenstone.gatherer.gui; 2 28 … … 10 36 import org.greenstone.gatherer.Dictionary; 11 37 import org.greenstone.gatherer.Gatherer; 12 import org.greenstone.gatherer.collection. CollectionConfiguration;38 import org.greenstone.gatherer.collection.BasicCollectionConfiguration; 13 39 import org.greenstone.gatherer.util.Utility; 14 40 import org.greenstone.gatherer.gui.SimpleMenuBar; … … 60 86 File metadata_directory = new File(possible_collections[i], Utility.META_DIR); 61 87 if(collect_cfg_file.exists()) { 62 CollectionConfiguration collect_cfg = newCollectionConfiguration(collect_cfg_file);88 BasicCollectionConfiguration collect_cfg = new BasicCollectionConfiguration(collect_cfg_file); 63 89 String collection_name = collect_cfg.getName(); 64 90 // Even if there is no metadata directory we add it if its one of the 'big five + 1' that we know how to handle. … … 74 100 // Else not a collection at all. Someones pulling a fast one. 75 101 } 76 102 77 103 // Sort the result. 78 104 Collections.sort(base_collection_model); … … 135 161 cancel_button.setMnemonic(KeyEvent.VK_C); 136 162 Dictionary.setBoth(cancel_button, "General.Cancel", "General.Cancel_Tooltip"); 137 163 138 164 //ColorListener email_color_listener = new ColorListener(address, host); No more email 139 165 … … 203 229 center_pane.setLayout(new BorderLayout()); 204 230 center_pane.add(description_pane, BorderLayout.CENTER); 205 231 206 232 bottom_pane.setLayout(new BorderLayout()); 207 233 bottom_pane.add(base_collection_pane, BorderLayout.CENTER); … … 245 271 * @return the filename as a String 246 272 */ 247 public String getName() { 248 // Retrieve the first 8 non-whitespace characters of title_final. 249 StringBuffer name_buffer = new StringBuffer(""); 250 int i = 0; 251 while(i < title_final.length() && name_buffer.length() < 8) { 252 char c = title_final.charAt(i); 253 if(!Character.isWhitespace(c)) { 254 name_buffer.append(Character.toLowerCase(c)); 255 } 256 i++; 257 } 258 // We need to ensure the filename is unique 259 int counter = 0; 260 while(filenameClashes(name_buffer.toString())) { 261 counter++; 262 String suffix = String.valueOf(counter); 263 name_buffer.replace(name_buffer.length() - suffix.length(), name_buffer.length(), suffix); 264 } 265 // All done 266 return name_buffer.toString(); 267 } 273 public String getName() { 274 // Retrieve the first 8 non-whitespace characters of title_final. 275 StringBuffer name_buffer = new StringBuffer(""); 276 int i = 0; 277 while(i < title_final.length() && name_buffer.length() < 8) { 278 char c = title_final.charAt(i); 279 if(!Character.isWhitespace(c)) { 280 name_buffer.append(Character.toLowerCase(c)); 281 } 282 i++; 283 } 284 // We need to ensure the filename is unique 285 int counter = 0; 286 StringBuffer new_name_buffer = new StringBuffer(name_buffer.toString()); 287 while(filenameClashes(new_name_buffer.toString())) { 288 new_name_buffer = new StringBuffer(name_buffer.toString()); 289 counter++; 290 String suffix = String.valueOf(counter); 291 // If we have to truncate the namestring so as to fit the suffix 292 if(suffix.length() + new_name_buffer.length() > 8) { 293 new_name_buffer.replace(new_name_buffer.length() - suffix.length(), new_name_buffer.length(), suffix); 294 } 295 // Or just append it if that isn't necessary 296 else { 297 new_name_buffer.append(suffix); 298 } 299 300 } 301 // All done 302 return new_name_buffer.toString(); 303 } 268 304 269 305 private boolean filenameClashes(String filename) { … … 283 319 284 320 285 private class BrowseListener 321 private class BrowseListener 286 322 implements ActionListener { 287 323 public void actionPerformed(ActionEvent event) { … … 298 334 if(file != null) { 299 335 file = file.getParentFile(); 300 CollectionConfiguration collect_cfg = newCollectionConfiguration(new File(file, Utility.META_DIR));336 BasicCollectionConfiguration collect_cfg = new BasicCollectionConfiguration(new File(file, Utility.META_DIR)); 301 337 Item item = new Item(file, collect_cfg.getName()); 302 338 base_collection.addItem(item); 303 339 base_collection.setSelectedItem(item); 304 } 340 } 305 341 } 306 342 } … … 336 372 } 337 373 338 private class CreateListener 339 implements ActionListener { 374 private class CreateListener 375 implements ActionListener { 376 340 377 public void actionPerformed(ActionEvent event) { 341 // Validate. 342 title_final = title.getText(); 343 if(title_final.length() == 0) { 344 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("NewCollectionPrompt.Title_Error"), Dictionary.get("NewCollectionPrompt.Error"), JOptionPane.ERROR_MESSAGE); 345 title.setForeground(Gatherer.config.getColor("coloring.error_foreground", false)); 346 title.setBackground(Gatherer.config.getColor("coloring.error_background", false)); 347 return; 348 } 349 // We must ensure that the collection title is unique. This is a pain in the nether regions as we are forced to load the collect.cfg of each other collection in turn looking for a conflicting title 350 else { 351 352 353 } 378 // Validate. 379 title_final = title.getText(); 380 if(title_final.length() == 0) { 381 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("NewCollectionPrompt.Title_Error"), Dictionary.get("NewCollectionPrompt.Error"), JOptionPane.ERROR_MESSAGE); 382 title.setForeground(Gatherer.config.getColor("coloring.error_foreground", false)); 383 title.setBackground(Gatherer.config.getColor("coloring.error_background", false)); 384 return; 385 } 386 // We must ensure that the collection title is unique. This is a pain in the nether regions as we are forced to load the collect.cfg of each other collection in turn looking for a conflicting title 387 else { 388 File collection_directory = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path)); 389 File children[] = collection_directory.listFiles(); 390 for(int i = 0; children != null && i < children.length; i++) { 391 if(children[i].isDirectory()) { 392 BasicCollectionConfiguration other_collection = new BasicCollectionConfiguration(new File(children[i], Utility.CONFIG_DIR)); 393 if(other_collection.getName().equalsIgnoreCase(title_final)) { 394 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("NewCollectionPrompt.Title_Clash"), Dictionary.get("NewCollectionPrompt.Error"), JOptionPane.ERROR_MESSAGE); 395 title.setForeground(Gatherer.config.getColor("coloring.error_foreground", false)); 396 title.setBackground(Gatherer.config.getColor("coloring.error_background", false)); 397 return; 398 } 399 other_collection = null; 400 } 401 } 402 } 403 354 404 /* Suppress filename 355 405 name_final = file.getText(); … … 382 432 host.setForeground(Gatherer.config.getColor("coloring.error_foreground", false)); 383 433 host.setBackground(Gatherer.config.getColor("coloring.error_background", false)); 384 return; 434 return; 385 435 } 386 436 */ … … 412 462 } 413 463 414 private class Item 464 private class Item 415 465 implements Comparable { 416 466 private File file; … … 435 485 436 486 /* 437 private class RestrictedTextField 487 private class RestrictedTextField 438 488 extends JTextField { 439 489 public RestrictedTextField(RestrictedTextDocument document, String value, int cols) { … … 445 495 } 446 496 447 private class RestrictedTextDocument 497 private class RestrictedTextDocument 448 498 extends PlainDocument { 449 499 private char block[]; … … 468 518 } 469 519 } 470 public void insertString(int offs, String str, AttributeSet a) 520 public void insertString(int offs, String str, AttributeSet a) 471 521 throws BadLocationException { 472 522 // Remove any blocked characters. … … 505 555 updateFilename(); 506 556 } 507 557 508 558 ** Gives notification that a portion of the document has been removed. * 509 559 public void removeUpdate(DocumentEvent e) { -
trunk/gli/src/org/greenstone/gatherer/gui/OpenCollectionDialog.java
r5593 r6051 48 48 import org.greenstone.gatherer.Dictionary; 49 49 import org.greenstone.gatherer.Gatherer; 50 import org.greenstone.gatherer.collection. CollectionConfiguration;50 import org.greenstone.gatherer.collection.BasicCollectionConfiguration; 51 51 import org.greenstone.gatherer.collection.CollectionManager; 52 import org.greenstone.gatherer.util.StaticStrings; 52 53 import org.greenstone.gatherer.util.Utility; 53 54 54 public class OpenCollectionDialog 55 public class OpenCollectionDialog 55 56 extends JFileChooser { 56 57 static final private ImageIcon LOCKED_COLLECTION_ICON = Utility.getImage("lcolicn.gif"); 57 58 static final private ImageIcon NORMAL_COLLECTION_ICON = Utility.getImage("ncolicn.gif"); 58 /** The name of the mouse listener that initiates editing on a double click. */ 59 /** The name of the mouse listener that initiates editing on a double click. */ 59 60 static final private String SINGLE_CLICK_LISTENER = "SingleClickListener"; 60 61 … … 81 82 } 82 83 83 public void destroy() { 84 public void destroy() { 84 85 } 85 86 … … 104 105 */ 105 106 static public void disableRename(Component c) { 106 if (c instanceof JList){ 107 if (c instanceof JList){ 107 108 EventListener[] listeners=c.getListeners(MouseListener.class); 108 109 for(int i=0; listeners != null && i < listeners.length; i++) { … … 122 123 } 123 124 } 124 } 125 } 125 126 126 127 127 128 /* The DescriptionPreview accessory is adapted from the ImagePreview.java (an example used by FileChooserDemo2.java). */ 128 private class DescriptionPreview 129 private class DescriptionPreview 129 130 extends JPanel 130 131 implements PropertyChangeListener { … … 153 154 if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop)) { 154 155 file = null; 155 update = true; 156 update = true; 156 157 } 157 158 // If a file became selected, find out which one. … … 170 171 File config_file = new File(file.getParentFile(), Utility.CONFIG_DIR); 171 172 if(config_file.exists()) { 172 CollectionConfiguration collect_cfg = new CollectionConfiguration(config_file); 173 BasicCollectionConfiguration collect_cfg = new BasicCollectionConfiguration(config_file); 174 text.setText(StaticStrings.SPEECH_CHARACTER + collect_cfg.getName() + StaticStrings.SPEECH_CHARACTER + StaticStrings.NEW_LINE_CHAR); 173 175 text.setText(collect_cfg.getDescription()); 174 176 text.setCaretPosition(0); … … 180 182 181 183 /** ImageFilter.java is a 1.4 example used by FileChooserDemo2.java. */ 182 private class GathererFilter 184 private class GathererFilter 183 185 extends FileFilter { 184 186 … … 196 198 private class GathererFileSystemView 197 199 extends FileSystemView { 198 200 199 201 private FileSystemView default_system_view = FileSystemView.getFileSystemView(); 200 202 201 203 /** Creates a new folder with a default folder name. */ 202 public File createNewFolder(File containingDir) 204 public File createNewFolder(File containingDir) 203 205 throws IOException { 204 206 return default_system_view.createNewFolder(containingDir); 205 } 207 } 206 208 207 209 /** Gets the list of shown (i.e. */ -
trunk/gli/src/org/greenstone/gatherer/gui/Preferences.java
r5847 r6051 13 13 import org.greenstone.gatherer.checklist.CheckList; 14 14 import org.greenstone.gatherer.checklist.Entry; 15 import org.greenstone.gatherer.gui.EmailField; 15 16 import org.greenstone.gatherer.gui.ModalDialog; 16 17 import org.greenstone.gatherer.gui.SimpleMenuBar; … … 24 25 25 26 private CheckList warning_preferences_check_list; 27 private EmailField email_field; 26 28 private JButton apply_button; 27 29 private JButton cancel_button; … … 39 41 private JCheckBox workflow_preview; 40 42 private JComboBox language_combobox; 43 private JLabel email_label; 41 44 private JLabel language_label; 42 45 private JLabel library_path_label; … … 51 54 private Preferences self; 52 55 53 static final Dimension LABEL_SIZE = new Dimension(1 50, 25);56 static final Dimension LABEL_SIZE = new Dimension(175, 25); 54 57 static final Dimension ROW_SIZE = new Dimension(640, 25); 55 58 static final Dimension SIZE = new Dimension(640, 345); … … 136 139 proxy_host_label = new JLabel(); 137 140 proxy_host_label.setPreferredSize(LABEL_SIZE); 138 Dictionary.registerText(proxy_host_label, "Preferences.Connection.Proxy_Host"); 141 Dictionary.registerText(proxy_host_label, "Preferences.Connection.Proxy_Host"); 139 142 proxy_host_field = new JTextField(Gatherer.config.getString("general.proxy_host", true)); 140 143 proxy_host_field.setEnabled(currently_enabled); … … 227 230 classes_folder = null; 228 231 232 // Users email 233 JPanel email_pane = new JPanel(); 234 email_label = new JLabel(); 235 email_label.setPreferredSize(LABEL_SIZE); 236 Dictionary.registerText(email_label, "Preferences.General.Email"); 237 email_field = new EmailField(Gatherer.config.getColor("coloring.error_background", false)); 238 email_field.setText(Gatherer.config.getEmail()); 239 Dictionary.registerTooltip(email_field, "Preferences.General.Email_Tooltip"); 240 229 241 // Extracted metadata 230 242 view_extracted_metadata_checkbox = new JCheckBox(); … … 255 267 256 268 // Layout 269 email_pane.setLayout(new BorderLayout()); 270 email_pane.add(email_label, BorderLayout.WEST); 271 email_pane.add(email_field, BorderLayout.CENTER); 272 257 273 language_pane.setLayout(new BorderLayout()); 258 274 language_pane.add(language_label, BorderLayout.WEST); … … 261 277 general_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 262 278 general_pane.setLayout(new GridLayout(5,1,0,5)); 279 general_pane.add(email_pane); 280 general_pane.add(language_pane); 263 281 general_pane.add(view_extracted_metadata_checkbox); 264 282 general_pane.add(show_file_size_checkbox); 265 general_pane.add(language_pane);266 283 267 284 return general_pane; … … 399 416 400 417 public void dispose() { 401 // Dispose 402 super.dispose(); 418 // Where's my code for unregistering all of the components?!? 419 420 // Dispose 421 super.dispose(); 403 422 } 404 423 … … 428 447 429 448 // General preferences 449 Gatherer.config.setEmail(email_field.getText()); 450 430 451 Gatherer.config.set("general.show_file_size", Configuration.COLLECTION_SPECIFIC, show_file_size_checkbox.isSelected()); 431 452 Gatherer.g_man.refreshTrees(DragTree.TREE_DISPLAY_CHANGED); … … 472 493 } 473 494 474 private class DictionaryEntry 495 private class DictionaryEntry 475 496 implements Comparable { 476 497 private Locale locale; … … 526 547 workflow_design.setSelected(element.getEnabled("design")); 527 548 workflow_export.setSelected(element.getEnabled("export")); 528 workflow_preview.setSelected(element.getEnabled("preview")); 549 workflow_preview.setSelected(element.getEnabled("preview")); 529 550 } 530 551 } … … 570 591 public String toString() { 571 592 if(text == null) { 572 text = element.getFirstChild().getNodeValue(); 593 text = element.getFirstChild().getNodeValue(); 573 594 } 574 595 return text; -
trunk/gli/src/org/greenstone/gatherer/gui/PreviewPane.java
r5815 r6051 49 49 50 50 public class PreviewPane 51 52 53 54 private int back_count= 0;55 56 private JButton back= null;57 private JButton forward= null;58 private JButton home= null;59 60 private JLabel status= null;61 62 63 64 65 66 51 extends JPanel { 52 53 private CalHTMLPane view = null; 54 private int back_count = 0; 55 private int forward_count = 0; 56 private JButton back = null; 57 private JButton forward = null; 58 private JButton home = null; 59 private JButton reload = null; 60 private JLabel status = null; 61 private Observer observer = null; 62 private URL homepage = null; 63 64 static final public String BLANK_PAGE = "<html><head><title>No Page</title></head><body></body></html>"; 65 66 public PreviewPane() { 67 67 super(); 68 68 … … 95 95 96 96 status = new JLabel(); 97 Dictionary.registerText(status, "Browser.Ready"); 98 99 100 97 Dictionary.registerText(status, "Browser.Ready"); 98 } 99 100 public void collectionChanged(boolean ready) { 101 101 // If we were showing a page, but that page is no longer available, then return to a blank page 102 102 if(!ready && homepage != null) { 103 104 103 homepage = null; 104 view.showHTMLDocument(BLANK_PAGE); 105 105 } 106 106 if (ready && Gatherer.config.exec_address != null) { 107 108 107 // reload the home page for the current collection 108 try { 109 109 // Now load the collection 110 Collection this_coll = Gatherer.c_man.getCollection(); 110 Collection this_collection = Gatherer.c_man.getCollection(); 111 String search_types = this_collection.cdm.searchtype_manager.getSearchTypes(); 111 112 String extra_args = ""; 112 String build_type = this_coll.getCollectionType(); 113 if (build_type.equals("mgpp")) { 114 // we need some more args on the url 115 String search_types = this_coll.getSearchTypes(); 116 if (search_types.equals("")) { 117 extra_args = "&ct=1&qt=0&qto=3"; 118 } else if (search_types.equals("plain")) { 119 extra_args = "&ct=1&qt=0&qto=1"; 120 } else if (search_types.equals("form")) { 121 extra_args = "&ct=1&qt=1&qto=2"; 122 } else if (search_types.equals("plain,form")) { 123 extra_args = "&ct=1&qt=0&qto=3"; 124 } else if (search_types.equals("form,plain")) { 125 extra_args = "&ct=1&qt=1&qto=3"; 126 } 127 } 128 129 homepage = new URL(Gatherer.config.exec_address.toString() + "?a=p&p=about&c=" + this_coll.getName()+extra_args); 113 if (search_types.length() > 0) { 114 // we need some more args on the url 115 if (search_types.equals("")) { 116 extra_args = "&ct=1&qt=0&qto=3"; 117 } else if (search_types.equals("plain")) { 118 extra_args = "&ct=1&qt=0&qto=1"; 119 } else if (search_types.equals("form")) { 120 extra_args = "&ct=1&qt=1&qto=2"; 121 } else if (search_types.equals("plain,form")) { 122 extra_args = "&ct=1&qt=0&qto=3"; 123 } else if (search_types.equals("form,plain")) { 124 extra_args = "&ct=1&qt=1&qto=3"; 125 } 126 } 127 128 homepage = new URL(Gatherer.config.exec_address.toString() + "?a=p&p=about&c=" + this_collection.getName() + extra_args); 130 129 String[] args = new String[1]; 131 130 args[0] = homepage.toString(); 132 131 Dictionary.registerText(status, "Browser.Loading", args); 133 132 view.showHTMLDocument(homepage, null, true); 134 135 133 } 134 catch (MalformedURLException exception) { 136 135 Gatherer.printStackTrace(exception); 137 138 } 139 140 141 136 } 137 } 138 } 139 140 public void display() { 142 141 JPanel control_pane = new JPanel(); 143 142 control_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); … … 157 156 add(a_panel, BorderLayout.CENTER); 158 157 add(status, BorderLayout.SOUTH); 159 160 161 162 163 158 } 159 160 /** This method is called when the user selects the 'Preview' tab from the views bar. Can be used to display a particular page or perform some other relevant tests (ensure internet connection to specified server maybe?) 161 */ 162 public void gainFocus() { 164 163 if(Gatherer.c_man.ready() && Gatherer.c_man.built()) { 165 164 if(homepage == null && Gatherer.config.exec_address != null) { 166 165 try { 167 168 169 170 171 172 166 // Now load the collection 167 homepage = new URL(Gatherer.config.exec_address.toString() + "?a=p&p=about&c=" + Gatherer.c_man.getCollection().getName()); 168 String[] args = new String[1]; 169 args[0] = homepage.toString(); 170 Dictionary.registerText(status, "Browser.Loading", args); 171 view.showHTMLDocument(homepage); 173 172 } 174 173 catch (MalformedURLException exception) { 175 176 } 177 174 Gatherer.printStackTrace(exception); 175 } 176 } 178 177 } 179 178 validate(); 180 181 182 179 } 180 181 public void configServer(String command) { 183 182 try { 184 185 186 187 188 189 190 183 String url = Gatherer.config.exec_address.toString() + command; 184 ///ystem.err.println("Action: " + url); 185 view.setLoadSynchronously(true); 186 view.showHTMLDocument(new URL(url)); 187 view.setLoadSynchronously(false); 188 ///ystem.err.println("Complete."); 189 url = null; 191 190 } 192 191 catch(Exception error) { 193 194 } 195 196 197 192 ///ystem.err.println("Bad URL."); 193 } 194 } 195 196 public void validate() { 198 197 back.setEnabled(back_count > 0); 199 198 home.setEnabled(homepage != null); 200 199 forward.setEnabled(forward_count > 0); 201 200 reload.setEnabled(homepage != null); 202 203 204 201 } 202 203 private class BackListener 205 204 implements ActionListener { 206 205 public void actionPerformed(ActionEvent event) { 207 208 209 210 211 } 212 213 214 206 view.goBack(); 207 back_count--; 208 forward_count++; 209 validate(); 210 } 211 } 212 213 private class ForwardListener 215 214 implements ActionListener { 216 215 public void actionPerformed(ActionEvent event) { 217 218 219 220 221 } 222 223 224 216 view.goForward(); 217 back_count++; 218 forward_count--; 219 validate(); 220 } 221 } 222 223 private class HomeListener 225 224 implements ActionListener { 226 225 public void actionPerformed(ActionEvent event) { 227 228 229 230 231 } 232 233 234 226 view.showHTMLDocument(homepage); 227 back_count++; 228 forward_count = 0; 229 validate(); 230 } 231 } 232 233 private class ReloadListener 235 234 implements ActionListener { 236 235 public void actionPerformed(ActionEvent event) { 237 238 } 239 240 241 236 view.reloadDocument(); 237 } 238 } 239 240 private class Observer 242 241 extends DefaultCalHTMLObserver { 243 242 public int state = CalCons.DOC_LOADED; 244 243 public void linkActivatedUpdate(CalHTMLPane pane, URL url, String target_frame, String j_name) { 245 246 247 244 back_count++; 245 forward_count = 0; 246 validate(); 248 247 } 249 248 250 249 public void linkFocusUpdate(CalHTMLPane pane, URL url) { 251 252 253 250 String[] args = new String[1]; 251 args[0] = url.toString(); 252 Dictionary.registerText(status, "Browser.Follow", args); 254 253 } 255 254 256 255 public void statusUpdate(CalHTMLPane pane, int state, URL url, int value, String message) { 257 258 259 260 261 256 this.state = state; 257 String[] args = new String[1]; 258 args[0] = url.toString(); 259 260 switch(state) { 262 261 // The Pane is attempting to connect to the given URL to receive data. 263 262 case CalCons.PRE_CONNECT: 264 263 ///ystem.err.println("Preconnect: " + state + " - " + message); 265 264 break; 266 265 // The Pane was unable to connect to the given URL or was unable to parse the content. Most likely this will be due to an incorrectly specified URL. The message argument may contain further details of the reason for failure. 267 266 case CalCons.PARSE_FAILED: 268 267 ///ystem.err.println("Parse Failed: " + state + " - " + message); 269 268 Dictionary.registerText(status, "Browser.CannotConnect", args); 270 269 break; 271 270 // The Pane has established a connection to the given URL and is receiving any content. 272 271 case CalCons.CONNECTED: 273 272 ///ystem.err.println("Connected: " + state + " - " + message); 274 273 Dictionary.registerText(status, "Browser.Loading", args); 275 274 break; 276 275 // The size of the content at the given URL is known and is contained in the value argument. 277 276 case CalCons.DOC_LENGTH: 278 277 ///ystem.err.println("Doc Length: " + state + " - " + message); 279 278 break; 280 279 // The title of the document for the given URL is known and is contained in the message argument. Only the title of a document in the Pane's top level frame will be sent to this method. If the document has no name, the message will be null, unless the document is a Frameset document in which case the message "Frameset" will be sent. 281 280 case CalCons.TITLE: 282 281 ///ystem.err.println("Title: " + state + " - " + message); 283 282 break; 284 283 // An exception has been thrown during parsing of the data from the URL. This will most likely be an IOException such as a server time-out. 285 284 case CalCons.PARSE_FAILED_POST_CONNECT: 286 285 ///ystem.err.println("Parse Failed Post Connect: " + state + " - " + message); 287 286 Dictionary.registerText(status, "Browser.TimedOut", args); 288 287 break; 289 288 // The document has been parsed but formatting cannot be completed because the document contains images of unspecified size. The parsing thread is waiting for image updates to give it the information it needs to format and display the document. 290 289 case CalCons.WAITING_FOR_IMAGES: 291 290 ///ystem.err.println("Waiting For Images: " + state + " - " + message + " - " + url.toString()); 292 291 break; 293 292 // All text and image data has been received, parsed and the document structure determined. 294 293 case CalCons.DOC_LOADED: 295 294 ///ystem.err.println("Doc Loaded: " + state + " - " + message); 296 295 Dictionary.registerText(status, "Browser.Ready"); 297 296 break; 298 299 } 300 297 } 298 } 299 } 301 300 } -
trunk/gli/src/org/greenstone/gatherer/gui/SimpleOpenCollectionDialog.java
r5939 r6051 35 35 import org.greenstone.gatherer.Dictionary; 36 36 import org.greenstone.gatherer.Gatherer; 37 import org.greenstone.gatherer.collection. CollectionConfiguration;37 import org.greenstone.gatherer.collection.BasicCollectionConfiguration; 38 38 import org.greenstone.gatherer.gui.ModalDialog; 39 39 import org.greenstone.gatherer.util.StaticStrings; … … 71 71 72 72 JPanel center_pane = new JPanel(); 73 73 74 74 JPanel collection_list_pane = new JPanel(); 75 75 JLabel collection_list_label = new JLabel(); … … 155 155 private class AdvancedListener 156 156 implements ActionListener { 157 157 158 158 public void actionPerformed(ActionEvent event) { 159 159 result = BROWSE_OPTION; … … 164 164 private class CancelListener 165 165 implements ActionListener { 166 166 167 167 public void actionPerformed(ActionEvent event) { 168 168 result = CANCEL_OPTION; 169 169 SimpleOpenCollectionDialog.this.dispose(); 170 170 } 171 } 171 } 172 172 173 173 private class CollectionListSelectionListener … … 192 192 } 193 193 else { 194 CollectionConfiguration collection_configuration = (CollectionConfiguration) collection_list.getSelectedValue();194 BasicCollectionConfiguration collection_configuration = (BasicCollectionConfiguration) collection_list.getSelectedValue(); 195 195 description_textarea.setText(collection_configuration.getDescription()); 196 196 description_textarea.setCaretPosition(0); … … 214 214 String collection_foldername = collection_folder.getName(); 215 215 if(!collection_folder.isFile() && !collection_foldername.equals(StaticStrings.MODEL_COLLECTION_NAME)) { 216 CollectionConfiguration collection_configuration = newCollectionConfiguration(new File(collection_folder, Utility.CONFIG_DIR));216 BasicCollectionConfiguration collection_configuration = new BasicCollectionConfiguration(new File(collection_folder, Utility.CONFIG_DIR)); 217 217 if(!collection_configuration.getName().equals(StaticStrings.ERROR_STR)) { 218 218 data.add(collection_configuration); … … 247 247 private class OpenListener 248 248 implements ActionListener { 249 249 250 250 public void actionPerformed(ActionEvent event) { 251 251 result = OK_OPTION; 252 CollectionConfiguration collection_configuration = (CollectionConfiguration) collection_list.getSelectedValue();252 BasicCollectionConfiguration collection_configuration = (BasicCollectionConfiguration) collection_list.getSelectedValue(); 253 253 File collect_cfg_file = collection_configuration.getFile(); 254 254 File etc_folder = collect_cfg_file.getParentFile(); … … 261 261 SimpleOpenCollectionDialog.this.dispose(); 262 262 } 263 } 263 } 264 264 } -
trunk/gli/src/org/greenstone/gatherer/gui/table/GTableModel.java
r6028 r6051 50 50 * @version 2.3b 51 51 */ 52 public class GTableModel 53 extends AbstractTableModel 52 public class GTableModel 53 extends AbstractTableModel 54 54 implements MSMListener { 55 55 … … 70 70 // Register this model with the msm manager. 71 71 if (Gatherer.c_man.ready()) { 72 Gatherer.c_man.getCollection().msm.addMSMListener(this); 72 Gatherer.c_man.getCollection().msm.addMSMListener(this); 73 73 } 74 74 } … … 200 200 // Ensure the position is within the current metadata 201 201 if (i >= current_metadata.size()) { 202 i = current_metadata.size() - 1;202 i = current_metadata.size() - 1; 203 203 } 204 204 205 205 // Select the same row as before, except if it would select a different element 206 206 ElementWrapper element = metadatum.getElement(); 207 if(i < 0) { 208 Gatherer.println("Could not find suitable row to select!"); 209 return; 210 } 207 211 Metadata newly_selected_metadatum = (Metadata) current_metadata.get(i); 208 212 if (!newly_selected_metadatum.getElement().equals(element)) { 209 // Try one row previous 210 i--; 211 newly_selected_metadatum = (Metadata) current_metadata.get(i); 212 if (!newly_selected_metadatum.getElement().equals(element)) { 213 Gatherer.println("Could not find suitable row to select!"); 214 return; 215 } 213 // Try one row previous 214 i--; 215 if(i < 0) { 216 Gatherer.println("Could not find suitable row to select!"); 217 return; 218 } 219 220 newly_selected_metadatum = (Metadata) current_metadata.get(i); 221 if (!newly_selected_metadatum.getElement().equals(element)) { 222 Gatherer.println("Could not find suitable row to select!"); 223 return; 224 } 216 225 } 217 226 … … 298 307 /** Determine if the given metadata is common to all selected file nodes given the context of the current view. */ 299 308 public boolean isCommon(Metadata entry) { 300 return (entry.getCount() == file_nodes.length);309 return (entry.getCount() >= file_nodes.length); 301 310 } 302 311 303 312 /** Determine if the given metadata is common to all selected file nodes given the context of the current view. */ 304 313 public boolean isCommon(int row) { … … 352 361 showInheritedMetadataWarning(); 353 362 } 354 363 355 364 // If the piece of metadata is in the list, increment its count 356 365 int index = current_metadata.indexOf(metadatum); … … 364 373 index = add(current_metadata, metadatum); 365 374 fireTableRowsInserted(index, index); 366 375 367 376 // Remember we have seen this element 368 377 if (known_elements.contains(element) == false) { -
trunk/gli/src/org/greenstone/gatherer/gui/tree/DragTreeCellRenderer.java
r5915 r6051 46 46 import org.greenstone.gatherer.util.Utility; 47 47 48 public class DragTreeCellRenderer 48 public class DragTreeCellRenderer 49 49 extends DefaultTreeCellRenderer { 50 50 51 51 private boolean in_focus = false; 52 52 private Color selection_background; 53 53 private Color selection_foreground; 54 55 static final private ImageIcon GREY_FOLDER = Utility.getImage("greyfolder.gif", true);56 static final private ImageIcon GREEN_FILE = Utility.getImage("greenfile.gif", true);57 static final private ImageIcon GREEN_FOLDER = Utility.getImage("greenfolder.gif", true);54 55 //static final private ImageIcon GREY_FOLDER = Utility.getImage("greyfolder.gif", true); 56 //static final private ImageIcon GREEN_FILE = Utility.getImage("greenfile.gif", true); 57 //static final private ImageIcon GREEN_FOLDER = Utility.getImage("greenfolder.gif", true); 58 58 59 59 public DragTreeCellRenderer() { … … 74 74 if(value instanceof FileNode) { 75 75 FileNode node = (FileNode) value; 76 76 77 77 String new_value = null; 78 78 if(Gatherer.config.get("general.show_file_size", Configuration.COLLECTION_SPECIFIC) && node.getFile() != null && !node.getAllowsChildren()) { … … 85 85 tree_cell = (JLabel) super.getTreeCellRendererComponent(tree, new_value, sel, expanded, leaf, row, hasFocus); 86 86 87 /* 87 88 if(node.getFile() == null || node.isFileSystemRoot()) { 88 ((JLabel)tree_cell).setIcon(GREY_FOLDER);89 ((JLabel)tree_cell).setIcon(GREY_FOLDER); 89 90 } 90 91 else if(node.isInCurrentCollection()) { 91 if(!node.getFile().isFile()) {92 if(!node.getFile().isFile()) { 92 93 ((JLabel)tree_cell).setIcon(GREEN_FOLDER); 93 }94 else {94 } 95 else { 95 96 ((JLabel)tree_cell).setIcon(GREEN_FILE); 96 }97 } 97 98 } 99 */ 98 100 } 99 101 else { … … 102 104 return tree_cell; 103 105 } 104 106 105 107 public void loseFocus() { 106 108 setBackgroundSelectionColor(Color.lightGray); -
trunk/gli/src/org/greenstone/gatherer/msm/ElementWrapper.java
r6043 r6051 50 50 import org.w3c.dom.*; 51 51 52 /** This class provides a convience wrapper around a DOM model Element to allow Components such as the MetadataTable to display this information properly. 52 /** This class provides a convience wrapper around a DOM model Element to allow Components such as the MetadataTable to display this information properly. 53 53 * @author John Thompson 54 54 * @version 2.3 55 55 */ 56 public class ElementWrapper 56 public class ElementWrapper 57 57 implements Comparable { 58 58 /** The DOM element this wrapper is wrapped around. */ … … 62 62 /** Constructor for elements with no namespace necessary. 63 63 * @param element The DOM <strong>Element</strong> this is to be based on. 64 */ 64 */ 65 65 public ElementWrapper(Element element) { 66 66 this.element = element; … … 69 69 this.namespace = parent.getAttribute("namespace"); 70 70 } 71 71 72 72 } 73 73 … … 94 94 return toString().compareTo(object.toString()); 95 95 } 96 /** Decrement the number of occurances of this metadata element. 96 /** Decrement the number of occurances of this metadata element. 97 97 * @see org.greenstone.gatherer.msm.MSMUtils 98 98 */ … … 179 179 } 180 180 181 /** Increment the number of occurances of this metadata element. 181 /** Increment the number of occurances of this metadata element. 182 182 * @see org.greenstone.gatherer.msm.MSMUtils 183 183 */ … … 185 185 MSMUtils.setOccurance(element, 1); 186 186 } 187 187 188 188 public boolean isHierarchy() { 189 189 return element.getAttribute(StaticStrings.HIERARCHY_ATTRIBUTE).equalsIgnoreCase(StaticStrings.TRUE_STR); … … 227 227 228 228 // Return just the element name, unless the element identifier differs 229 if (element_name_no_namespace.equals(element_identifier)) {229 //if (element_name_no_namespace.equals(element_identifier)) { 230 230 return element_name; 231 }232 else {233 return element_name + " (" + element_identifier + ")";234 }231 //} 232 //else { 233 // return element_name + " (" + element_identifier + ")"; 234 //} 235 235 } 236 236 } -
trunk/gli/src/org/greenstone/gatherer/msm/GDMDocument.java
r6029 r6051 45 45 */ 46 46 public class GDMDocument { 47 /** Record if the document this object is based on is up to date. */ 48 private boolean up_to_date = true; 49 /** The document this class sources its data from. */ 50 private Document base_document; 51 static final private String ACCUMULATE = "accumulate"; 52 /** The pattern to match when searching for directory level assignments. */ 53 static final private String DIRECTORY_FILENAME = ".*"; 54 static final private String DESCRIPTION_ELEMENT = "Description"; 55 static final private String FILENAME_ELEMENT = "FileName"; 56 static final private String FILESET_ELEMENT = "FileSet"; 57 static final private String HVALUE_ATTRIBUTE = "hvalue"; 58 static final private String MODE_ATTRIBUTE = "mode"; 59 static final private String OVERWRITE = "overwrite"; 60 61 /** Constructor which creates a brand new metadata.xml document. */ 62 public GDMDocument() { 47 /** Record if the document this object is based on is up to date. */ 48 private boolean up_to_date = true; 49 /** The document this class sources its data from. */ 50 private Document base_document; 51 static final private String ACCUMULATE = "accumulate"; 52 /** The pattern to match when searching for directory level assignments. */ 53 static final private String DIRECTORY_FILENAME = ".*"; 54 static final private String DESCRIPTION_ELEMENT = "Description"; 55 static final private String FILENAME_ELEMENT = "FileName"; 56 static final private String FILESET_ELEMENT = "FileSet"; 57 static final private String HVALUE_ATTRIBUTE = "hvalue"; 58 static final private String MODE_ATTRIBUTE = "mode"; 59 static final private String OVERWRITE = "overwrite"; 60 static final private String[] ALL_METADATA_TYPES = {StaticStrings.METADATA_ELEMENT, StaticStrings.EXTRACTED_METADATA_ELEMENT}; 61 62 /** Constructor which creates a brand new metadata.xml document. */ 63 public GDMDocument() { 63 64 // Create new document. We do this by loading a copy of the template. */ 64 65 this.base_document = Utility.parse(Utility.GREENSTONEDIRECTORYMETADATA_TEMPLATE, true); 65 66 67 68 66 } 67 68 /** Constructor which parses an existing metadata.xml document. */ 69 public GDMDocument(File file) { 69 70 try { 70 71 this.base_document = Utility.parse(file.getAbsolutePath(), false); 71 72 } 72 73 catch (Exception error) { 73 74 } 75 76 77 78 74 // Poorly formed, or completely invalid metadata.xml file! 75 } 76 } 77 78 /** Constructor which wraps around an existing metadata.xml document. */ 79 public GDMDocument(Document base_document) { 79 80 this.base_document = base_document; 80 81 82 83 81 } 82 83 /** Add this metadata to the named file. There is one tricky thing to consider. Whenever a metadata entry is added it is taken to be accumulating except if it is the first added, in which case it overwrites! Actually this gets worse, as we could have been told to append this metadata to a document which already inherits metadata. Thus we need a new argument to determine whether this add was triggered by an append or a replace. */ 84 public void addMetadata(String filename, Metadata metadata, boolean force_accumulate) { 84 85 Gatherer.println("Add '" + metadata + "' to " + (filename != null ? filename : "directory.")); 85 86 try { 86 87 88 89 90 91 92 87 // Retrieve the document element. 88 Element directorymetadata_element = base_document.getDocumentElement(); 89 // Iterate through the filesets looking for one that matches the given filename. 90 Element fileset_element = null; 91 boolean found = false; 92 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT); 93 for(int i = 0; !found && i < fileset_elements.getLength(); i++) { 93 94 fileset_element = (Element) fileset_elements.item(i); 94 95 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT); 95 96 for(int j = 0; !found && j < filename_elements.getLength(); j++) { 96 97 98 99 97 Element filename_element = (Element) filename_elements.item(j); 98 String filename_pattern = MSMUtils.getValue(filename_element); 99 // Have we found a match. If so break out of for loop. 100 if(filename != null && filename.matches(filename_pattern) && !filename_pattern.equals(DIRECTORY_FILENAME)) { 100 101 ///ystem.err.println("Adding to existing file fileset!"); 101 102 found = true; 102 103 103 } 104 else if(filename == null && filename_pattern.equals(DIRECTORY_FILENAME)) { 104 105 ///ystem.err.println("Adding to existing folder fileset!"); 105 106 ///ystem.err.println("filename_pattern = '" + filename_pattern + "'"); 106 107 found = true; 107 108 109 108 } 109 // No match. On to the next one. 110 else { 110 111 fileset_element = null; 111 112 113 114 } 115 116 117 118 112 } 113 filename_pattern = null; 114 filename_element = null; 115 } 116 } 117 fileset_elements = null; 118 // If we still haven't found an existing fileset, then its time to create one. 119 if(fileset_element == null) { 119 120 ///ystem.err.println("Creating a new fileset."); 120 121 fileset_element = base_document.createElement(FILESET_ELEMENT); … … 126 127 // If the filename is null then we add a directory metadata set as directorymetadata_element's first child 127 128 if(filename == null) { 128 129 129 filename_text = base_document.createTextNode(DIRECTORY_FILENAME); 130 if(directorymetadata_element.hasChildNodes()) { 130 131 directorymetadata_element.insertBefore(fileset_element, directorymetadata_element.getFirstChild()); 131 132 132 } 133 else { 133 134 directorymetadata_element.appendChild(fileset_element); 134 135 } 135 136 } 136 137 // Otherwise we just append the new fileset to directorymetadata_element's children. 137 138 else { 138 139 139 filename_text = base_document.createTextNode(filename); 140 directorymetadata_element.appendChild(fileset_element); 140 141 } 141 142 filename_element.appendChild(filename_text); … … 143 144 description_element = null; 144 145 filename_element = null; 145 } 146 // Now, finally, we can add the metadata. 147 Element metadata_element = base_document.createElement(StaticStrings.METADATA_ELEMENT); 148 String name = metadata.getElement().getName(); 149 if(name.startsWith(Utility.EXTRACTED_METADATA_NAMESPACE)) { 150 name = name.substring(Utility.EXTRACTED_METADATA_NAMESPACE.length() + 1); 151 } 152 metadata_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name); 153 154 // To determine if this metadata entry should overwrite or accumulate we check if there are other entries with the same element in this fileset. 155 boolean will_accumulate = false; 156 NodeList sibling_description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT); 157 for(int k = 0; !will_accumulate && k < sibling_description_elements.getLength(); k++) { 146 } 147 // Now, finally, we can add the metadata. 148 Element metadata_element = null; 149 String name = metadata.getElement().getName(); 150 // If this is extracted metadata, we use a special element name that won't be recognized by greenstone 151 if(name.startsWith(Utility.EXTRACTED_METADATA_NAMESPACE)) { 152 metadata_element = base_document.createElement(ALL_METADATA_TYPES[1]); 153 name = name.substring(Utility.EXTRACTED_METADATA_NAMESPACE.length() + 1); 154 } 155 else { 156 metadata_element = base_document.createElement(ALL_METADATA_TYPES[0]); 157 } 158 metadata_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name); 159 160 // To determine if this metadata entry should overwrite or accumulate we check if there are other entries with the same element in this fileset. 161 boolean will_accumulate = false; 162 NodeList sibling_description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT); 163 for(int k = 0; !will_accumulate && k < sibling_description_elements.getLength(); k++) { 158 164 Element sibling_description_element = (Element) sibling_description_elements.item(k); 159 NodeList sibling_metadata_elements = sibling_description_element.getElementsByTagName(StaticStrings.METADATA_ELEMENT); 160 for(int l = 0; !will_accumulate && l < sibling_metadata_elements.getLength(); l++) { 161 Element sibling_metadata_element = (Element) sibling_metadata_elements.item(l); 162 // It appears that its possible that we can be asked to add the same metadata twice (especially after a copy action is cancelled then repeated). So we check if we have been asked to add exactly the same value twice. 163 if(sibling_metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equals(metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE))) { 164 // Check the values and return if they are the same. 165 if(metadata.getAbsoluteValue().equals(MSMUtils.getValue(sibling_metadata_element))) { 166 return; 167 } 168 will_accumulate = true; 169 } 170 sibling_metadata_element = null; 171 } 172 sibling_metadata_elements = null; 165 // We have to do this for each type of metadata 166 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) { 167 NodeList sibling_metadata_elements = sibling_description_element.getElementsByTagName(ALL_METADATA_TYPES[z]); 168 for(int l = 0; !will_accumulate && l < sibling_metadata_elements.getLength(); l++) { 169 Element sibling_metadata_element = (Element) sibling_metadata_elements.item(l); 170 // It appears that its possible that we can be asked to add the same metadata twice (especially after a copy action is cancelled then repeated). So we check if we have been asked to add exactly the same value twice. 171 if(sibling_metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equals(metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE))) { 172 // Check the values and return if they are the same. 173 if(metadata.getAbsoluteValue().equals(MSMUtils.getValue(sibling_metadata_element))) { 174 return; 175 } 176 will_accumulate = true; 177 } 178 sibling_metadata_element = null; 179 } 180 sibling_metadata_elements = null; 181 } 173 182 sibling_description_element = null; 174 175 176 183 } 184 sibling_description_elements = null; 185 if(will_accumulate || force_accumulate) { //mode.equals(ACCUMULATE)) { 177 186 metadata_element.setAttribute(MODE_ATTRIBUTE, ACCUMULATE); 178 187 } 179 188 // As we can't possibly store all the metadata in memory, nor can we ensure that the indexes written to file remain the same until the new time we look at this file, and to avoid having to open a rewrite every collection document whenever any value tree changes, I'm writing the value out as a full path string 180 189 GValueModel model = Gatherer.c_man.getCollection().msm.getValueTree(metadata.getElement()); … … 186 195 node_value = metadata.getAbsoluteValue(); 187 196 } 188 189 190 191 192 193 194 195 197 ///ystem.err.println("Creating node in GDMDocument: '" + node_value + "'"); 198 metadata_element.appendChild(base_document.createTextNode(node_value)); 199 // Retrieve the first description element for this fileset (there should only be one, but I'll play it safe). 200 NodeList description_elements = fileset_element.getElementsByTagName("Description"); 201 Element description_element = (Element) description_elements.item(0); 202 description_element.appendChild(metadata_element); 203 description_element = null; 204 metadata_element = null; 196 205 //mode = null; 197 198 199 206 fileset_element = null; 207 directorymetadata_element = null; 208 up_to_date = false; 200 209 } 201 210 catch (Exception error) { 202 203 } 204 205 206 211 Gatherer.printStackTrace(error); 212 } 213 } 214 215 public int countMetadata() { 207 216 int count = 0; 208 217 try { 209 210 211 212 213 218 // Retrieve the document element. 219 Element directorymetadata_element = base_document.getDocumentElement(); 220 // Iterate through the filesets, checking the FileName child element against the target file's name using regular expression matching. 221 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT); 222 for(int i = 0; i < fileset_elements.getLength(); i++) { 214 223 Element fileset_element = (Element) fileset_elements.item(i); 215 224 NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT); 216 225 for(int k = 0; k < description_elements.getLength(); k++) { 217 Element description_element = (Element) description_elements.item(k); 218 NodeList metadata_elements = description_element.getElementsByTagName(StaticStrings.METADATA_ELEMENT); 219 count = count + metadata_elements.getLength(); 220 metadata_elements = null; 221 description_element = null; 226 Element description_element = (Element) description_elements.item(k); 227 // We have to do this for each type of metadata 228 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) { 229 NodeList metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[z]); 230 count = count + metadata_elements.getLength(); 231 metadata_elements = null; 232 } 233 description_element = null; 222 234 } 223 235 description_elements = null; 224 236 fileset_element = null; 225 226 227 237 } 238 fileset_elements = null; 239 directorymetadata_element = null; 228 240 } 229 241 catch (Exception error) { 230 242 Gatherer.printStackTrace(error); 231 243 } 232 244 return count; 233 234 235 236 245 } 246 247 /** Retrieve the document this class is wrapping. */ 248 public Document getDocument() { 237 249 return base_document; 238 239 240 250 } 251 /** Get all of the metadata, including directory level, associated with this file. */ 252 public ArrayList getMetadata(String filename, boolean remove, ArrayList metadatum_so_far, File file, boolean append_folder_level) { 241 253 return getMetadata(filename, remove, metadatum_so_far, file, append_folder_level, false); 242 243 244 254 } 255 /** Retrieve the metadata associated with the given filename. Keep track of what metadata should be overwritten and what should be accumulated. Also make note of the source file, and remove the metadata if required. Finally if purge is set retrieve every piece of metadata in this file. */ 256 public ArrayList getMetadata(String filename, boolean remove, ArrayList metadatum_so_far, File file, boolean append_folder_level, boolean purge) { 245 257 Gatherer.println("Get metadata for " + filename); 246 258 ArrayList metadatum = null; 247 259 if(metadatum_so_far == null) { 248 260 metadatum = new ArrayList(); 249 261 } 250 262 else { 251 263 metadatum = metadatum_so_far; 252 264 } 253 265 try { 254 255 256 257 258 266 // Retrieve the document element. 267 Element directorymetadata_element = base_document.getDocumentElement(); 268 // Iterate through the filesets, checking the FileName child element against the target file's name using regular expression matching. 269 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT); 270 for(int i = 0; i < fileset_elements.getLength(); i++) { 259 271 Element fileset_element = (Element) fileset_elements.item(i); 260 272 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT); 261 273 for(int j = 0; j < filename_elements.getLength(); j++) { 262 263 264 274 Element filename_element = (Element) filename_elements.item(j); 275 String filename_text = MSMUtils.getValue(filename_element); 276 if((filename != null && (filename.matches(filename_text) || (append_folder_level && filename.indexOf(File.separator) != -1 && filename_text.equals(filename.substring(0, filename.indexOf(File.separator)))))) || ((filename == null || append_folder_level) && filename_text.equals(DIRECTORY_FILENAME)) || purge) { 265 277 // If they match add all of the metadata found in the Description child element, remembering to abide by desired mode (accumulate vs. overwrite). 278 // Normal metadata 266 279 NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT); 267 280 for(int k = 0; k < description_elements.getLength(); k++) { 268 Element description_element = (Element) description_elements.item(k); 269 NodeList metadata_elements = description_element.getElementsByTagName(StaticStrings.METADATA_ELEMENT); 270 for(int l = 0; l < metadata_elements.getLength(); l++) { 271 Element metadata_element = (Element) metadata_elements.item(l); 272 String raw_element = metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE); 273 //String language = metadata_element.getAttribute("language"); 274 String mode = metadata_element.getAttribute(MODE_ATTRIBUTE); 275 String raw_value = MSMUtils.getValue(metadata_element); 276 // Raw value is in GREENSTONE form, convert to DOM 277 raw_value = Codec.transform(raw_value, Codec.GREENSTONE_TO_DOM); 278 // ***** LEGACY SUPPORT ***** 279 // If this raw_value contains a '\' character, but no '\\', '[' or ']' characters, then replace the '\' with a '\\' 280 if(raw_value.indexOf(StaticStrings.ESCAPE_STR) != -1) { 281 Gatherer.println("Detected Legacy Path: " + raw_value); 282 raw_value = raw_value.replaceAll(StaticStrings.ESCAPE_PATTERN, StaticStrings.PIPE_STR); 283 Gatherer.println("Updated Path To: " + raw_value); 284 MSMUtils.setValue(metadata_element, raw_value); 281 Element description_element = (Element) description_elements.item(k); 282 // We have to do this for each type of metadata 283 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) { 284 NodeList metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[z]); 285 for(int l = 0; l < metadata_elements.getLength(); l++) { 286 Element metadata_element = (Element) metadata_elements.item(l); 287 String raw_element = metadata_element.getAttribute(StaticStrings.NAME_ATTRIBUTE); 288 //String language = metadata_element.getAttribute("language"); 289 String mode = metadata_element.getAttribute(MODE_ATTRIBUTE); 290 String raw_value = MSMUtils.getValue(metadata_element); 291 // Raw value is in GREENSTONE form, convert to DOM 292 raw_value = Codec.transform(raw_value, Codec.GREENSTONE_TO_DOM); 293 // ***** LEGACY SUPPORT ***** 294 // If this raw_value contains a '\' character, but no '\\', '[' or ']' characters, then replace the '\' with a '\\' 295 if(raw_value.indexOf(StaticStrings.ESCAPE_STR) != -1) { 296 Gatherer.println("Detected Legacy Path: " + raw_value); 297 raw_value = raw_value.replaceAll(StaticStrings.ESCAPE_PATTERN, StaticStrings.PIPE_STR); 298 Gatherer.println("Updated Path To: " + raw_value); 299 MSMUtils.setValue(metadata_element, raw_value); 300 } 301 // ************************** 302 // Using the element string and value, retrieve a matching Metadata object from the cache 303 Metadata metadata = null; 304 // If this element has hierarchy values then we must ensure the raw value is a full path, not an index. 305 // Try to retrieve an already comstructed piece of metadata from file - but not if we are purging, as this will stuff up anything that is still using that metadata - such as the GTable 306 if(GDMManager.metadata_cache.contains(raw_element, raw_value) && !purge) { 307 ///ystem.err.println("HIT! Retrieve metadata from cache: " + raw_element + " -> " + raw_value + "\n"); 308 metadata = (Metadata) GDMManager.metadata_cache.get(raw_element, raw_value); 309 } 310 else { 311 ElementWrapper element = Gatherer.c_man.getCollection().msm.getElement(raw_element); 312 if (element != null) { 313 GValueNode value = Metadata.getDefaultValueNode(element, raw_value); 314 ///ystem.err.println("Miss. Create new metadata: " + raw_element + " -> " + raw_value + "\n"); 315 metadata = new Metadata(element, value); 316 if(!purge) { 317 GDMManager.metadata_cache.put(raw_element, raw_value, metadata); 318 } 319 ///ystem.err.println("Added metadata to cache: " + raw_element + " -> " + raw_value + "\n"); 320 value = null; 321 element = null; 322 } 323 } 324 // check whether the metadata is null 325 if (metadata != null) { 326 // We determine whether this metadata is file or folder level 327 if(filename != null) { 328 ///ystem.err.println("Filename = " + filename); 329 ///ystem.err.println("filename_text = " + filename_text); 330 // If can only be file level if there is no folder path details in filename and if the filename matched the filename text node (it may have matched .* instead)! 331 if(filename.indexOf(File.separator) == -1 && filename.equals(filename_text)) { 332 metadata.setFileLevel(true); 333 ///ystem.err.println("File level!!!"); 334 } 335 else { 336 metadata.setFileLevel(false); 337 ///ystem.err.println("Inherited!!!"); 338 } 339 } 340 else { 341 ///ystem.err.println("Filename is null therefore this is file level metadata."); 342 metadata.setFileLevel(true); 343 } 344 metadata.setFile(file); 345 // If mode is overwrite, then remove any previous values for this metadata element. 346 if(mode.equals("accumulate")) { 347 metadata.setAccumulate(true); 348 } 349 else { 350 metadata.setAccumulate(false); 351 ///ystem.err.println("Metadata overwrites: " + metadata); 352 for(int m = metadatum.size() - 1; m >= 0; m--) { 353 Metadata old_metadata = (Metadata) metadatum.get(m); 354 if(old_metadata.getElement().equals(metadata.getElement())) { 355 metadatum.remove(m); 356 ///ystem.err.println("Removing overridden metadata: " + old_metadata); 357 } 358 old_metadata = null; 359 } 360 } 361 mode = null; 362 // Add the completed metadata and clean up 363 ///ystem.err.println("Adding metadata: " + metadata); 364 metadatum.add(metadata); 365 // Having found our metadata check if the value from the xml matches the one from the gvaluenode. If not update it. This happens whenever hierarchy information is involved (indexes rapidly become obsolete). 366 // If remove was set, remove it. We can only remove pure file level metadata, or folder level iff we were asked for folder level. 367 if(remove && ((filename != null && filename.matches(filename_text) && !filename_text.equals(DIRECTORY_FILENAME)) || (filename == null && filename_text.equals(DIRECTORY_FILENAME)))) { 368 ///ystem.err.println("Removing " + metadata + " from " + file); 369 description_element.removeChild(metadata_element); 370 // Remove the description element if empty. 371 if(!description_element.hasChildNodes()) { 372 fileset_element.removeChild(description_element); 373 } 374 } 375 else { 376 //String current_value = metadata.getAbsoluteValue(); 377 String current_value = Codec.transform(metadata.getValueNode().getFullPath(false), Codec.TEXT_TO_DOM); 378 ///ystem.err.println("Checking the current hfile: " + current_value); 379 ///ystem.err.println("Against whats in the hfile: " + current_value); 380 if(!raw_value.equals(current_value)) { 381 // Remove old text 382 while(metadata_element.hasChildNodes()) { 383 metadata_element.removeChild(metadata_element.getFirstChild()); 384 } 385 // Add new. 386 metadata_element.appendChild(base_document.createTextNode(current_value)); 387 } 388 } 389 } 390 metadata = null; 391 raw_value = null; 392 raw_element = null; 393 metadata_element = null; 394 } 395 metadata_elements = null; 285 396 } 286 // ************************** 287 // Using the element string and value, retrieve a matching Metadata object from the cache 288 Metadata metadata = null; 289 // If this element has hierarchy values then we must ensure the raw value is a full path, not an index. 290 // Try to retrieve an already comstructed piece of metadata from file - but not if we are purging, as this will stuff up anything that is still using that metadata - such as the GTable 291 if(GDMManager.metadata_cache.contains(raw_element, raw_value) && !purge) { 292 ///ystem.err.println("HIT! Retrieve metadata from cache: " + raw_element + " -> " + raw_value + "\n"); 293 metadata = (Metadata) GDMManager.metadata_cache.get(raw_element, raw_value); 294 } 295 else { 296 ElementWrapper element = Gatherer.c_man.getCollection().msm.getElement(raw_element); 297 if (element != null) { 298 299 GValueNode value = Metadata.getDefaultValueNode(element, raw_value); 300 ///ystem.err.println("Miss. Create new metadata: " + raw_element + " -> " + raw_value + "\n"); 301 metadata = new Metadata(element, value); 302 if(!purge) { 303 GDMManager.metadata_cache.put(raw_element, raw_value, metadata); 304 } 305 ///ystem.err.println("Added metadata to cache: " + raw_element + " -> " + raw_value + "\n"); 306 value = null; 307 element = null; 308 } 309 } 310 // check whether the metadata is null 311 if (metadata != null) { 312 // We determine whether this metadata is file or folder level 313 if(filename != null) { 314 ///ystem.err.println("Filename = " + filename); 315 ///ystem.err.println("filename_text = " + filename_text); 316 // If can only be file level if there is no folder path details in filename and if the filename matched the filename text node (it may have matched .* instead)! 317 if(filename.indexOf(File.separator) == -1 && filename.equals(filename_text)) { 318 metadata.setFileLevel(true); 319 ///ystem.err.println("File level!!!"); 320 } 321 else { 322 metadata.setFileLevel(false); 323 ///ystem.err.println("Inherited!!!"); 324 } 325 } 326 else { 327 ///ystem.err.println("Filename is null therefore this is file level metadata."); 328 metadata.setFileLevel(true); 329 } 330 metadata.setFile(file); 331 332 // If mode is overwrite, then remove any previous values for this metadata element. 333 if(mode.equals("accumulate")) { 334 metadata.setAccumulate(true); 335 } 336 else { 337 metadata.setAccumulate(false); 338 ///ystem.err.println("Metadata overwrites: " + metadata); 339 for(int m = metadatum.size() - 1; m >= 0; m--) { 340 Metadata old_metadata = (Metadata) metadatum.get(m); 341 if(old_metadata.getElement().equals(metadata.getElement())) { 342 metadatum.remove(m); 343 ///ystem.err.println("Removing overridden metadata: " + old_metadata); 344 } 345 old_metadata = null; 346 } 347 } 348 mode = null; 349 350 // Add the completed metadata and clean up 351 ///ystem.err.println("Adding metadata: " + metadata); 352 metadatum.add(metadata); 353 354 // Having found our metadata check if the value from the xml matches the one from the gvaluenode. If not update it. This happens whenever hierarchy information is involved (indexes rapidly become obsolete). 355 // If remove was set, remove it. We can only remove pure file level metadata, or folder level iff we were asked for folder level. 356 if(remove && ((filename != null && filename.matches(filename_text) && !filename_text.equals(DIRECTORY_FILENAME)) || (filename == null && filename_text.equals(DIRECTORY_FILENAME)))) { 357 ///ystem.err.println("Removing " + metadata + " from " + file); 358 description_element.removeChild(metadata_element); 359 // Remove the description element if empty. 360 if(!description_element.hasChildNodes()) { 361 fileset_element.removeChild(description_element); 362 } 363 } 364 else { 365 //String current_value = metadata.getAbsoluteValue(); 366 String current_value = Codec.transform(metadata.getValueNode().getFullPath(false), Codec.TEXT_TO_DOM); 367 ///ystem.err.println("Checking the current hfile: " + current_value); 368 ///ystem.err.println("Against whats in the hfile: " + current_value); 369 if(!raw_value.equals(current_value)) { 370 // Remove old text 371 while(metadata_element.hasChildNodes()) { 372 metadata_element.removeChild(metadata_element.getFirstChild()); 373 } 374 // Add new. 375 metadata_element.appendChild(base_document.createTextNode(current_value)); 376 } 377 } 378 } 379 metadata = null; 380 raw_value = null; 381 raw_element = null; 382 metadata_element = null; 383 } 384 metadata_elements = null; 385 description_element = null; 397 description_element = null; 386 398 } 387 399 description_elements = null; 388 389 390 400 } 401 filename_text = null; 402 filename_element = null; 391 403 } 392 404 // If the file set no longer has any description entries, remove it entirely 393 405 NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT); 394 406 if(description_elements.getLength() == 0) { 395 407 directorymetadata_element.removeChild(fileset_element); 396 408 } 397 409 description_elements = null; 398 410 filename_elements = null; 399 411 fileset_element = null; 400 401 402 412 } 413 fileset_elements = null; 414 directorymetadata_element = null; 403 415 } 404 416 catch (Exception error) { 405 417 Gatherer.self.printStackTrace(error); 406 418 } 407 419 ///ystem.err.println("Found " + metadatum.size() + " pieces of metadata."); 408 420 return metadatum; 409 410 411 412 421 } 422 423 /** Determine if this document has been saved recently, and thus xml file version is up to date. */ 424 public boolean isUpToDate() { 413 425 return false; 414 415 416 417 426 } 427 428 /** Determine is this is a valid Greenstone Directory Metadata file. It may of course just be some xml file with the name metadata.xml. */ 429 public boolean isValid() { 418 430 // Just determine if the doctype is GreenstoneDirectoryMetadata and root node is called DirectoryMetadata. 419 431 String doctype_name = base_document.getDoctype().getName(); 420 432 String root_name = base_document.getDocumentElement().getTagName(); 421 433 return ((doctype_name.equals("GreenstoneDirectoryMetadata") && root_name.equals("GreenstoneDirectoryMetadata")) || (doctype_name.equals("DirectoryMetadata") && root_name.equals("DirectoryMetadata"))); 422 } 423 /** Remove the given directory level metadata from this document. All directory level metadata is available under the FileSet with filename '.*'. There is at least one nasty case to consider, where the first overwriting metadata entry, of several with the same element, is removed. In this case the next entry must become overwrite to ensure proper inheritance. */ 424 public void removeMetadata(String filename, Metadata metadata) { 434 } 435 /** Remove the given directory level metadata from this document. All directory level metadata is available under the FileSet with filename '.*'. There is at least one nasty case to consider, where the first overwriting metadata entry, of several with the same element, is removed. In this case the next entry must become overwrite to ensure proper inheritance. */ 436 public void removeMetadata(String filename, Metadata metadata) { 437 Gatherer.println("Remove metadata: " + metadata + "\nFrom filename: " + filename); 425 438 try { 426 427 428 429 430 431 432 433 434 439 boolean found = false; 440 boolean first_metadata_element_found = true; 441 boolean make_next_metadata_element_overwrite = false; 442 boolean remove_fileset = false; 443 // Retrieve the document element. 444 Element directorymetadata_element = base_document.getDocumentElement(); 445 // Iterate through the filesets looking for the directory level one. 446 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT); 447 for(int i = 0; !found && i < fileset_elements.getLength(); i++) { 435 448 Element fileset_element = (Element) fileset_elements.item(i); 436 449 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT); 437 450 for(int j = 0; !found && j < filename_elements.getLength(); j++) { 438 439 440 451 Element filename_element = (Element) filename_elements.item(j); 452 String filename_text = MSMUtils.getValue(filename_element); 453 if((filename != null && filename.matches(filename_text) && !filename.equals(DIRECTORY_FILENAME)) || (filename == null && filename_text.equals(DIRECTORY_FILENAME))) { 441 454 // Retrieve the Metadata Element for this fileset, and iterate through them looking for the one which we are to remove. 442 455 NodeList description_elements = fileset_element.getElementsByTagName("Description"); 443 456 for(int k = 0; !found && k < description_elements.getLength(); k++) { 444 Element description_element = (Element) description_elements.item(k); 445 NodeList metadata_elements = description_element.getElementsByTagName(StaticStrings.METADATA_ELEMENT); 446 for(int l = 0; (!found || !make_next_metadata_element_overwrite) && l < metadata_elements.getLength(); l++) { 447 Element metadata_element = (Element) metadata_elements.item(l); 448 String element = metadata_element.getAttribute("name"); 449 String value = MSMUtils.getValue(metadata_element); 450 // See if this is the metadata we wish to remove 451 if(element.equals(metadata.getElement().getName())) { 452 if(value.equals(metadata.getAbsoluteValue())) { 453 // Remove it 454 ///ystem.err.println("Remove " + element + "-" + value); 455 description_element.removeChild(metadata_element); 456 found = true; 457 // If this was the first metadata with this element found, and it was set to overwrite, then we have to ensure that the next metadata with this element found (if any) is changed to be overwrite now. 458 if(first_metadata_element_found && !metadata.accumulates()) { 459 ///ystem.err.println("First of this element found!"); 460 make_next_metadata_element_overwrite = true; 461 } 462 } 463 // If this was the first metadata we've found with the element of the one to be removed set first found to false. 464 else if(first_metadata_element_found) { 465 ///ystem.err.println("Found a matching element: " + element + "=" + value); 466 first_metadata_element_found = false; 467 } 468 // Otherwise we should make this metadata overwrite as requested. 469 else if(make_next_metadata_element_overwrite) { 470 ///ystem.err.println("Changing to overwrite: " + element + "=" + value); 471 metadata_element.setAttribute(MODE_ATTRIBUTE, ""); 472 } 457 Element description_element = (Element) description_elements.item(k); 458 // We have to do this for each type of metadata 459 for(int z = 0; z < ALL_METADATA_TYPES.length; z++) { 460 NodeList metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[z]); 461 for(int l = 0; (!found || !make_next_metadata_element_overwrite) && l < metadata_elements.getLength(); l++) { 462 Element metadata_element = (Element) metadata_elements.item(l); 463 String element = metadata_element.getAttribute("name"); 464 String value = MSMUtils.getValue(metadata_element); 465 // See if this is the metadata we wish to remove 466 if(element.equals(metadata.getElement().getName())) { 467 if(value.equals(metadata.getAbsoluteValue())) { 468 // Remove it 469 ///ystem.err.println("Remove " + element + "-" + value); 470 description_element.removeChild(metadata_element); 471 found = true; 472 // If this was the first metadata with this element found, and it was set to overwrite, then we have to ensure that the next metadata with this element found (if any) is changed to be overwrite now. 473 if(first_metadata_element_found && !metadata.accumulates()) { 474 ///ystem.err.println("First of this element found!"); 475 make_next_metadata_element_overwrite = true; 476 } 477 } 478 // If this was the first metadata we've found with the element of the one to be removed set first found to false. 479 else if(first_metadata_element_found) { 480 ///ystem.err.println("Found a matching element: " + element + "=" + value); 481 first_metadata_element_found = false; 482 } 483 // Otherwise we should make this metadata overwrite as requested. 484 else if(make_next_metadata_element_overwrite) { 485 ///ystem.err.println("Changing to overwrite: " + element + "=" + value); 486 metadata_element.setAttribute(MODE_ATTRIBUTE, ""); 487 } 488 } 489 value = null; 490 element = null; 491 metadata_element = null; 492 } 493 metadata_elements = description_element.getElementsByTagName(ALL_METADATA_TYPES[z]); 494 // If we found it, removed it, and now the description tag has no children, mark the fileset for removal 495 if(metadata_elements.getLength() == 0) { 496 remove_fileset = true; 497 } 498 metadata_elements = null; 473 499 } 474 value = null; 475 element = null; 476 metadata_element = null; 477 } 478 metadata_elements = description_element.getElementsByTagName(StaticStrings.METADATA_ELEMENT); 479 // If we found it, removed it, and now the description tag has no children, mark the fileset for removal 480 if(metadata_elements.getLength() == 0) { 481 remove_fileset = true; 482 } 483 metadata_elements = null; 484 description_element = null; 500 description_element = null; 485 501 } 486 502 description_elements = null; 487 488 489 503 } 504 filename_text = null; 505 filename_element = null; 490 506 } 491 507 filename_elements = null; 492 508 if(found && remove_fileset) { 493 509 directorymetadata_element.removeChild(fileset_element); 494 510 } 495 511 fileset_element = null; 496 497 498 499 512 } 513 fileset_elements = null; 514 directorymetadata_element = null; 515 up_to_date = false; 500 516 } 501 517 catch (Exception error) { 502 503 } 504 505 506 507 518 Gatherer.printStackTrace(error); 519 } 520 } 521 522 /** Change the up to date flag. */ 523 public void setUpToDate(boolean up_to_date) { 508 524 this.up_to_date = up_to_date; 509 525 } 510 526 } -
trunk/gli/src/org/greenstone/gatherer/msm/GreenstoneArchiveParser.java
r6047 r6051 139 139 for(int k = 0; !found && k < metadatum.size(); k++) { 140 140 Metadata sibling = (Metadata) metadatum.get(k); 141 ///ystem.err.println("Comparing " + element + " to " + sibling.getElement()); 141 142 if(element.equals(sibling.getElement())) { 143 ///ystem.err.println("Removing metadata for: " + sibling); 142 144 Gatherer.c_man.getCollection().gdm.metadataChanged(new MSMEvent(this, System.currentTimeMillis(), target_file, sibling, null)); 143 145 } -
trunk/gli/src/org/greenstone/gatherer/shell/GShell.java
r6049 r6051 108 108 return process_running; 109 109 } 110 110 111 111 /** Constructor gatherer all the data required to create a new process, and emit meaningfull messages. 112 112 * @param args A <strong>String[]</strong> containing the arguments to the process thread, including the name of the executable. … … 143 143 } */ 144 144 /** Any threaded class must include this method to allow the thread body to be run. */ 145 public void run() { 146 if(progress != null) { 147 progress.start(); 148 } 149 // Determine if the user has asked for an outfile. 150 String out_name = null; 151 BufferedOutputStream bos = null; 152 if(type == IMPORT || type == BUILD) { 153 if(type == IMPORT) { 154 out_name = (String) Gatherer.c_man.getCollection().build_options.getImportValue("out"); 155 } 156 else { 157 out_name = (String) Gatherer.c_man.getCollection().build_options.getBuildValue("out"); 158 } 159 if(out_name != null && out_name.length() > 0) { 145 public void run() { 146 if(progress != null) { 147 progress.start(); 148 } 149 // Determine if the user has asked for an outfile. 150 String out_name = null; 151 BufferedOutputStream bos = null; 152 if(type == IMPORT || type == BUILD) { 153 if(type == IMPORT) { 154 out_name = (String) Gatherer.c_man.getCollection().build_options.getImportValue("out"); 155 } 156 else { 157 out_name = (String) Gatherer.c_man.getCollection().build_options.getBuildValue("out"); 158 } 159 if(out_name != null && out_name.length() > 0) { 160 try { 161 bos = new BufferedOutputStream(new FileOutputStream(new File(out_name), true)); 162 } 163 catch (Exception error) { 164 Gatherer.printStackTrace(error); 165 } 166 } 167 } 168 // Issue a processBegun event 169 fireProcessBegun(type, status); 160 170 try { 161 bos = new BufferedOutputStream(new FileOutputStream(new File(out_name), true));162 }163 catch (Exception error) {164 Gatherer.printStackTrace(error);165 }166 }167 }168 // Issue a processBegun event169 fireProcessBegun(type, status);170 try {171 171 172 172 String command = ""; … … 176 176 ///ystem.err.println("Command: " + command); 177 177 fireMessage(type, Dictionary.get("GShell.Command") + ": " + command, status); 178 178 179 179 Runtime rt = Runtime.getRuntime(); 180 180 Process prcs = rt.exec(args); … … 184 184 //BufferedReader stdinbr = new BufferedReader( stdinisr ); 185 185 // Captures the std err of a program and pipes it into std in of java 186 186 187 187 StringBuffer eline_buffer = new StringBuffer(); 188 188 StringBuffer stdline_buffer = new StringBuffer(); … … 191 191 if(eisr.ready()) { 192 192 int c = eisr.read(); 193 ///atherer.println("eisr: '" + (char) c + "'"); 193 194 if(c == '\n' || c == '\r') { 194 195 if(eline_buffer.length() > 0) { 195 196 String eline = eline_buffer.toString(); 196 /// ystem.err.print("*");197 ///atherer.println("* " + eline + " *"); 197 198 if(progress != null) { 198 199 progress.parse(eline); … … 218 219 else if(stdisr.ready()) { 219 220 int c = stdisr.read(); 221 ///atherer.println("eisr: '" + (char) c + "'"); 220 222 if(c == '\n' || c == '\r') { 221 223 if(stdline_buffer.length() > 0) { 222 224 String stdline = stdline_buffer.toString(); 223 /// ystem.err.print("+");225 ///atherer.println("+ " + stdline + " +"); 224 226 fireMessage(type, typeAsString(type) + "> " + stdline, status); 225 227 stdline = null; … … 240 242 } 241 243 244 // Of course, just because the process is finished doesn't mean the incoming streams are empty. Unfortunately I've got no chance of preserving order, so I'll process the error stream first, then the out stream 245 while(eisr.ready()) { 246 int c = eisr.read(); 247 ///atherer.println("eisr: '" + (char) c + "'"); 248 if(c == '\n' || c == '\r') { 249 if(eline_buffer.length() > 0) { 250 String eline = eline_buffer.toString(); 251 ///atherer.println("* " + eline + " *"); 252 if(progress != null) { 253 progress.parse(eline); 254 } 255 if(bos != null) { 256 try { 257 bos.write(eline.getBytes(), 0, eline.length()); 258 } 259 catch(Exception error) { 260 Gatherer.printStackTrace(error); 261 } 262 } 263 fireMessage(type, typeAsString(type) + "> " + eline, status); 264 eline = null; 265 eline_buffer = new StringBuffer(); 266 } 267 } 268 else { 269 eline_buffer.append((char)c); 270 } 271 } 272 while(stdisr.ready()) { 273 int c = stdisr.read(); 274 ///atherer.println("eisr: '" + (char) c + "'"); 275 if(c == '\n' || c == '\r') { 276 if(stdline_buffer.length() > 0) { 277 String stdline = stdline_buffer.toString(); 278 ///atherer.println("+ " + stdline + " +"); 279 fireMessage(type, typeAsString(type) + "> " + stdline, status); 280 stdline = null; 281 stdline_buffer = new StringBuffer(); 282 } 283 } 284 else { 285 stdline_buffer.append((char)c); 286 } 287 } 288 289 // Ensure that any messages still remaining in the string buffers are fired off. 290 if(eline_buffer.length() > 0) { 291 String eline = eline_buffer.toString(); 292 if(progress != null) { 293 progress.parse(eline); 294 } 295 if(bos != null) { 296 try { 297 bos.write(eline.getBytes(), 0, eline.length()); 298 } 299 catch(Exception error) { 300 Gatherer.printStackTrace(error); 301 } 302 } 303 fireMessage(type, typeAsString(type) + "> " + eline, status); 304 eline = null; 305 } 306 307 if(stdline_buffer.length() > 0) { 308 String stdline = stdline_buffer.toString(); 309 fireMessage(type, typeAsString(type) + "> " + stdline, status); 310 stdline = null; 311 } 312 242 313 if(!hasSignalledStop()) { 243 314 // Now display final message based on exit value 244 315 prcs.waitFor(); 245 316 246 317 if(prcs.exitValue() == 0) { 247 318 status = OK; … … 332 403 } 333 404 334 /** Method to determine if the user, via the progress monitor, has signalled stop. 405 /** Method to determine if the user, via the progress monitor, has signalled stop. 335 406 * @return A <strong>boolean</strong> indicating if the user wanted to stop. 336 407 */ -
trunk/gli/src/org/greenstone/gatherer/util/Codec.java
r5877 r6051 147 147 // Transform plain html text into greenstone encoding 148 148 String[] text_to_greenstone = { 149 149 150 150 "\\[", "[", 151 151 "\\]", "]", 152 152 "\"", """, 153 "\'", "'",154 153 "\n", "\\\\n" 155 154 }; 155 // "\'", "'", 156 156 // removed "\\\\", "\\|", 157 157 TRANSFORMS.put(TEXT_TO_GREENSTONE, text_to_greenstone); … … 179 179 } 180 180 181 static public String transform(String raw, String transform) { 181 static public String transform(String raw, String transform) { 182 if(raw == null) { 183 return raw; 184 } 182 185 ///ystem.err.println("Transforming by "+transform+":\n" + raw); 183 186 String processed = (String) CACHE.get(transform, raw); -
trunk/gli/src/org/greenstone/gatherer/util/StaticStrings.java
r6030 r6051 32 32 /** Were you to guess that this is a class object choc-a-block full of static stringy goodness, you'd be right. They come in several flavours: Those ending _STR are strings you might find as values in XML, _ELEMENT are element names, _ATTRIBUTE are attribute names, _CHAR are particular characters while _CHARACTER are also characters but expressed as strings (for regex purposes ie startsWith, endsWith, indexOf and replaceAll); _PATTERN are strings which require extra escaping to put them through regex. Finally anything else is just a static string used within GLI. */ 33 33 public class StaticStrings { 34 static final public char CLOSEBRACKET_CHAR = ']'; 35 static final public char DOUBLEQUOTE_CHAR = '\"'; 36 static final public char BACKSLASH_CHAR = '\\'; 34 37 static final public char FORWARDSLASH_CHAR = '/'; 35 38 static final public char NEW_LINE_CHAR = '\n'; 39 static final public char OPENBRACKET_CHAR = '['; 36 40 static final public char PIPE_CHAR = '|'; 41 static final public char SINGLEQUOTE_CHAR = '\''; 42 static final public char SPACE_CHAR = ' '; 37 43 static final public char STAR_CHAR = '*'; 38 44 static final public String ABSTRACT_ELEMENT = "Abstract"; … … 41 47 static final public String ASSIGNED_ATTRIBUTE = "assigned"; 42 48 static final public String AT_CHARACTER = "@"; 49 static final public String BUILD_TYPE_STR = "buildtype"; 43 50 static final public String CCS_STR = "ccs"; 44 51 static final public String CLASSES_FOLDER = "classes"; … … 76 83 static final public String ENGLISH_LANGUAGE_STR = "en"; 77 84 static final public String ENUM_STR = "enum"; 85 static final public String EQUALS_CHARACTER = "="; 78 86 static final public String ERROR_STR = "Error"; 79 87 static final public String ESCAPE_PATTERN = "\\\\"; … … 81 89 static final public String EXCLAIMATION_CHARACTER = "!"; 82 90 static final public String EXCLUDE_STR = "exclude"; 91 static final public String EXTRACTED_METADATA_ELEMENT = "XMetadata"; 83 92 static final public String EXTRACTED_NAMESPACE = "ex."; 84 93 static final public String FALSE_STR = "false"; … … 146 155 static final public String PROPERTIES_FILE_EXTENSION = ".properties"; 147 156 static final public String PSEUDO_COLLECTCONFIGURATION_XML = "xml/CollectionConfig.xml"; 148 //static final public String QUOTE_CHARACTER = "\"";149 157 static final public String RBRACKET_CHARACTER = "]"; 150 158 static final public String RBRACKET_PATTERN = "\\]";
Note:
See TracChangeset
for help on using the changeset viewer.