Changeset 4366 for trunk/gli/src/org/greenstone/gatherer/collection
- Timestamp:
- 2003-05-27T15:57:37+12:00 (21 years ago)
- Location:
- trunk/gli/src/org/greenstone/gatherer/collection
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gli/src/org/greenstone/gatherer/collection/BuildOptions.java
r4293 r4366 15 15 /** Build options uses the argument list found in config.xml and the current settings from the loaded collection configuration to represent the options the user wants to use during import and build. If there are no arguments stored in config.xml, or if the user indicates the argument are out of date, this class tries to parse new ones. */ 16 16 public class BuildOptions { 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 17 /** The root element of the build argument tree. */ 18 private Element build_arguments_element; 19 /** The root element of the build values tree. */ 20 private Element build_values_element; 21 /** The root element of the import argument tree. */ 22 private Element import_arguments_element; 23 /** The root element of the import values tree. */ 24 private Element import_values_element; 25 /** A cache of previously created build arguments. */ 26 private Hashtable build_arguments_cache = new Hashtable(); 27 /** A cache of previously created import arguments. */ 28 private Hashtable import_arguments_cache = new Hashtable(); 29 /** The name of an argument element. */ 30 static final private String ARGUMENT = "Argument"; 31 /** The name of the enabled attribute. */ 32 static final private String ENABLED = "enabled"; 33 /** The name of the 'false' value. */ 34 static final private String FALSE = "false"; 35 /** The name of a name attribute. */ 36 static final private String NAME = "name"; 37 /** The name of an option element. */ 38 static final private String OPTION = "Option"; 39 /** The name of the 'true' value. */ 40 static final private String TRUE = "true"; 41 /** When constructing a BuildOptions object we first try to retrieve the valid arguments from config.xml. If that fails we then try to parse the arguments noticed when calling import.pl -xml and buildcol.pl -xml. If that also fails, we load the default arguments from the xml template library. */ 42 public BuildOptions(Element build_values_element, Element import_values_element) { 43 // Try to retrieve the arguments for import and build. 44 build_arguments_element = Gatherer.config.getArguments("buildcol.pl"); 45 import_arguments_element = Gatherer.config.getArguments("import.pl"); 46 // If that fails try to reconstruct the arguments 47 if(build_arguments_element == null || import_arguments_element == null) { 48 build_arguments_element = loadArguments("buildcol.pl"); 49 import_arguments_element = loadArguments("import.pl"); 50 50 // And if that too fails, load the default argument templates 51 if(build_arguments_element == null || import_arguments_element == null) { 52 Document build_document = Utility.parse("xml" + File.separator + "buildcol.xml", true); 53 build_arguments_element = build_document.getDocumentElement(); 54 build_document = null; 55 Document import_document = Utility.parse("xml" + File.separator + "import.xml", true); 56 import_arguments_element = import_document.getDocumentElement(); 57 import_document = null; 58 ///atherer.println("Loaded default BO arguments from templates."); 51 if(build_arguments_element == null || import_arguments_element == null) { 52 Document build_document = Utility.parse("xml" + File.separator + "buildcol.xml", true); 53 build_arguments_element = build_document.getDocumentElement(); 54 build_document = null; 55 Document import_document = Utility.parse("xml" + File.separator + "import.xml", true); 56 import_arguments_element = import_document.getDocumentElement(); 57 import_document = null; 58 ///atherer.println("Loaded default BO arguments from templates."); 59 } 60 else { 61 ///atherer.println("Loaded BO arguments from scripts."); 62 } 63 // By now we should definately have the arguments. However the reason we are here is because they are not stored in the config.xml file, to make sure they are stored now. 64 Gatherer.config.setArguments(build_arguments_element); 65 Gatherer.config.setArguments(import_arguments_element); 66 } 67 else { 68 Gatherer.println("Loaded BO arguments from config.xml"); 69 } 70 // Now take a note of the values too. 71 this.build_values_element = build_values_element; 72 this.import_values_element = import_values_element; 73 } 74 75 /** Retrieve the arguments associated with a certain type of action, ie import or build. */ 76 public String[] getArguments(boolean build) { 77 String arguments[] = null; 78 NodeList argument_list = null; 79 if(build) { 80 argument_list = build_values_element.getElementsByTagName(ARGUMENT); 81 } 82 else { 83 argument_list = import_values_element.getElementsByTagName(ARGUMENT); 84 } 85 for(int i = 0; i < argument_list.getLength(); i++) { 86 String[] temp = new String[2]; 87 Element argument = (Element) argument_list.item(i); 88 ArrayTools.add(arguments, argument.getAttribute(NAME)); 89 String value = MSMUtils.getValue(argument); 90 if(value != null && value.length() > 0) { 91 ArrayTools.add(arguments, value); 92 } 93 } 94 return arguments; 95 } 96 97 /** Retrieve the indexth argument belonging to build. */ 98 public Argument getBuildArgument(int index) { 99 Argument argument = null; 100 // Try to find the argument in the cache. 101 SoftReference reference = (SoftReference) build_arguments_cache.get(new Integer(index)); 102 if(reference != null) { 103 argument = (Argument) reference.get(); 104 } 105 // Otherwise generate a new argument. 106 if(argument == null) { 107 argument = getArgument(build_arguments_element, index); 108 } 109 return argument; 110 } 111 112 /** Retrieve the number of arguments involved in building. */ 113 public int getBuildArgumentCount() { 114 NodeList build_options = build_arguments_element.getElementsByTagName(OPTION); 115 return build_options.getLength(); 116 } 117 118 /** Retrieve the value of a certain build argument. */ 119 public String getBuildValue(String name) { 120 return getValue(build_values_element, name, false); 121 } 122 123 /** Determine if the named argument value is enabled or disabled. */ 124 public boolean getBuildValueEnabled(String name) { 125 boolean result = false; 126 String value = getValue(build_values_element, name, true); 127 if(value != null && value.length() > 0) { 128 result = (value.equalsIgnoreCase(TRUE)); 129 } 130 return result; 131 } 132 133 /** Retrieve all of the build values as a String array ready to added to the buildcol.pl call. */ 134 public String[] getBuildValues() { 135 return getValues(build_values_element); 136 } 137 138 /** Retrieve the indexth argument belonging to import. */ 139 public Argument getImportArgument(int index) { 140 Argument argument = null; 141 // Try to find the argument in the cache. 142 SoftReference reference = (SoftReference) import_arguments_cache.get(new Integer(index)); 143 if(reference != null) { 144 argument = (Argument) reference.get(); 145 } 146 // Otherwise generate a new argument. 147 if(argument == null) { 148 argument = getArgument(import_arguments_element, index); 149 } 150 return argument; 151 } 152 153 /** Retrieve the number of arguments involved in importing. */ 154 public int getImportArgumentCount() { 155 NodeList import_options = import_arguments_element.getElementsByTagName(OPTION); 156 return import_options.getLength(); 157 } 158 159 /** Retrieve the value of a certain build argument. */ 160 public String getImportValue(String name) { 161 return getValue(import_values_element, name, false); 162 } 163 164 /** Determine if the named argument value is enabled or disabled. */ 165 public boolean getImportValueEnabled(String name) { 166 boolean result = false; 167 String value = getValue(import_values_element, name, true); 168 if(value != null && value.length() > 0) { 169 result = (value.equalsIgnoreCase(TRUE)); 170 } 171 return result; 172 } 173 174 /** Retrieve all of the import arguments in a form ready to be sent out to a shell process. */ 175 public String[] getImportValues() { 176 return getValues(import_values_element); 177 } 178 179 /** Set the value of a build argument. */ 180 public void setBuildValue(String name, boolean enable, String value) { 181 setValue(build_values_element, name, enable, value); 182 } 183 184 /** Set the value of a build argument. */ 185 public void setImportValue(String name, boolean enable, String value) { 186 setValue(import_values_element, name, enable, value); 187 } 188 189 /** Remove the given build value. */ 190 public void removeBuildValue(String name) { 191 removeValue(build_values_element, name); 192 } 193 194 /** Remove the given import value. */ 195 public void removeImportValue(String name) { 196 removeValue(import_values_element, name); 197 } 198 199 /** Retrieve the indexth element from the given set of arguments. */ 200 private Argument getArgument(Element arguments_element, int index) { 201 Argument argument = null; 202 try { 203 NodeList option_list = arguments_element.getElementsByTagName(OPTION); 204 if(0 <= index && index < option_list.getLength()) { 205 // Retrieve the appropriate argument 206 Element option = (Element) option_list.item(index); 207 // Iterate through this option elements children, making note of any details we find. 208 argument = new Argument(); 209 for(Node node = option.getFirstChild(); node != null; node = node.getNextSibling()) { 210 String node_name = node.getNodeName(); 211 if(node_name.equals("Name")) { 212 argument.setName(MSMUtils.getValue(node)); 213 } 214 else if(node_name.equals("Desc")) { 215 argument.setDesc(MSMUtils.getValue(node)); 216 } 217 else if(node_name.equals("Type")) { 218 argument.setType(MSMUtils.getValue(node)); 219 } 220 else if(node_name.equals("Default")) { 221 argument.setDefault(MSMUtils.getValue(node)); 222 } 223 else if(node_name.equals("List")) { 224 // Two final loops are required to parse lists. 225 for(Node value = node.getFirstChild(); value != null; value = value.getNextSibling()) { 226 if(value.getNodeName().equals("Value")) { 227 String key = null; 228 String desc = ""; 229 for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) { 230 node_name = subvalue.getNodeName(); 231 if(node_name.equals("Name")) { 232 key = MSMUtils.getValue(subvalue); 233 } 234 else if(node_name.equals("Desc")) { 235 desc = MSMUtils.getValue(subvalue); 236 } 59 237 } 60 else{61 ///atherer.println("Loaded BO arguments from scripts.");238 if(key != null) { 239 argument.addOption(key, desc); 62 240 } 63 // By now we should definately have the arguments. However the reason we are here is because they are not stored in the config.xml file, to make sure they are stored now. 64 Gatherer.config.setArguments(build_arguments_element); 65 Gatherer.config.setArguments(import_arguments_element); 66 } 67 else { 68 Gatherer.println("Loaded BO arguments from config.xml"); 69 } 70 // Now take a note of the values too. 71 this.build_values_element = build_values_element; 72 this.import_values_element = import_values_element; 73 } 74 75 /** Retrieve the arguments associated with a certain type of action, ie import or build. */ 76 public String[] getArguments(boolean build) { 77 String arguments[] = null; 78 NodeList argument_list = null; 79 if(build) { 80 argument_list = build_values_element.getElementsByTagName(ARGUMENT); 81 } 82 else { 83 argument_list = import_values_element.getElementsByTagName(ARGUMENT); 84 } 85 for(int i = 0; i < argument_list.getLength(); i++) { 86 String[] temp = new String[2]; 87 Element argument = (Element) argument_list.item(i); 88 ArrayTools.add(arguments, argument.getAttribute(NAME)); 89 String value = MSMUtils.getValue(argument); 90 if(value != null && value.length() > 0) { 91 ArrayTools.add(arguments, value); 92 } 93 } 94 return arguments; 95 } 96 97 /** Retrieve the indexth argument belonging to build. */ 98 public Argument getBuildArgument(int index) { 99 Argument argument = null; 100 // Try to find the argument in the cache. 101 SoftReference reference = (SoftReference) build_arguments_cache.get(new Integer(index)); 102 if(reference != null) { 103 argument = (Argument) reference.get(); 104 } 105 // Otherwise generate a new argument. 106 if(argument == null) { 107 argument = getArgument(build_arguments_element, index); 108 } 109 return argument; 110 } 111 112 /** Retrieve the number of arguments involved in building. */ 113 public int getBuildArgumentCount() { 114 NodeList build_options = build_arguments_element.getElementsByTagName(OPTION); 115 return build_options.getLength(); 116 } 117 118 /** Retrieve the value of a certain build argument. */ 119 public String getBuildValue(String name) { 120 return getValue(build_values_element, name, false); 121 } 122 123 /** Determine if the named argument value is enabled or disabled. */ 124 public boolean getBuildValueEnabled(String name) { 125 boolean result = false; 126 String value = getValue(build_values_element, name, true); 127 if(value != null && value.length() > 0) { 128 result = (value.equalsIgnoreCase(TRUE)); 129 } 130 return result; 131 } 132 133 /** Retrieve all of the build values as a String array ready to added to the buildcol.pl call. */ 134 public String[] getBuildValues() { 135 return getValues(build_values_element); 136 } 137 138 /** Retrieve the indexth argument belonging to import. */ 139 public Argument getImportArgument(int index) { 140 Argument argument = null; 141 // Try to find the argument in the cache. 142 SoftReference reference = (SoftReference) import_arguments_cache.get(new Integer(index)); 143 if(reference != null) { 144 argument = (Argument) reference.get(); 145 } 146 // Otherwise generate a new argument. 147 if(argument == null) { 148 argument = getArgument(import_arguments_element, index); 149 } 150 return argument; 151 } 152 153 /** Retrieve the number of arguments involved in importing. */ 154 public int getImportArgumentCount() { 155 NodeList import_options = import_arguments_element.getElementsByTagName(OPTION); 156 return import_options.getLength(); 157 } 158 159 /** Retrieve the value of a certain build argument. */ 160 public String getImportValue(String name) { 161 return getValue(import_values_element, name, false); 162 } 163 164 /** Determine if the named argument value is enabled or disabled. */ 165 public boolean getImportValueEnabled(String name) { 166 boolean result = false; 167 String value = getValue(import_values_element, name, true); 168 if(value != null && value.length() > 0) { 169 result = (value.equalsIgnoreCase(TRUE)); 170 } 171 return result; 172 } 173 174 /** Retrieve all of the import arguments in a form ready to be sent out to a shell process. */ 175 public String[] getImportValues() { 176 return getValues(import_values_element); 177 } 178 179 /** Set the value of a build argument. */ 180 public void setBuildValue(String name, boolean enable, String value) { 181 setValue(build_values_element, name, enable, value); 182 } 183 184 /** Set the value of a build argument. */ 185 public void setImportValue(String name, boolean enable, String value) { 186 setValue(import_values_element, name, enable, value); 187 } 188 189 /** Remove the given build value. */ 190 public void removeBuildValue(String name) { 191 removeValue(build_values_element, name); 192 } 193 194 /** Remove the given import value. */ 195 public void removeImportValue(String name) { 196 removeValue(import_values_element, name); 197 } 198 199 /** Retrieve the indexth element from the given set of arguments. */ 200 private Argument getArgument(Element arguments_element, int index) { 201 Argument argument = null; 202 try { 203 NodeList option_list = arguments_element.getElementsByTagName(OPTION); 204 if(0 <= index && index < option_list.getLength()) { 205 // Retrieve the appropriate argument 206 Element option = (Element) option_list.item(index); 207 // Iterate through this option elements children, making note of any details we find. 208 argument = new Argument(); 209 for(Node node = option.getFirstChild(); node != null; node = node.getNextSibling()) { 210 String node_name = node.getNodeName(); 211 if(node_name.equals("Name")) { 212 argument.setName(MSMUtils.getValue(node)); 213 } 214 else if(node_name.equals("Desc")) { 215 argument.setDesc(MSMUtils.getValue(node)); 216 } 217 else if(node_name.equals("Type")) { 218 argument.setType(MSMUtils.getValue(node)); 219 } 220 else if(node_name.equals("Default")) { 221 argument.setDefault(MSMUtils.getValue(node)); 222 } 223 else if(node_name.equals("List")) { 224 // Two final loops are required to parse lists. 225 for(Node value = node.getFirstChild(); value != null; value = value.getNextSibling()) { 226 if(value.getNodeName().equals("Value")) { 227 String key = null; 228 String desc = ""; 229 for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) { 230 node_name = subvalue.getNodeName(); 231 if(node_name.equals("Name")) { 232 key = MSMUtils.getValue(subvalue); 233 } 234 else if(node_name.equals("Desc")) { 235 desc = MSMUtils.getValue(subvalue); 236 } 237 } 238 if(key != null) { 239 argument.addOption(key, desc); 240 } 241 } 242 } 243 } 244 else if(node_name.equals("Required")) { 245 String v = MSMUtils.getValue(node); 246 if(v != null && v.equals("yes")) { 247 argument.setRequired(true); 248 } 249 } 250 } 251 } 252 } 253 catch (Exception error) { 254 Gatherer.println("Error in BuildOptions.getArgument(): " + error); 255 Gatherer.printStackTrace(error); 256 } 257 return argument; 258 } 259 260 private String getValue(Element arguments_element, String name, boolean is_enabled) { 261 String result = null; 262 try { 263 NodeList arguments = arguments_element.getElementsByTagName(ARGUMENT); 264 for(int i = 0; result == null && i < arguments.getLength(); i++) { 265 Element argument_element = (Element) arguments.item(i); 266 // Is this the argument we want. 267 if(argument_element.getAttribute(NAME).equalsIgnoreCase(name)) { 268 // Are we simply determining if this argument is enabled 269 if(is_enabled) { 270 result = argument_element.getAttribute(ENABLED); 271 } 272 else { 273 String argument_value = MSMUtils.getValue(argument_element); 274 if(argument_value != null) { 275 result = argument_value; 276 } 277 argument_value = null; 278 } 279 } 280 argument_element = null; 281 } 282 arguments = null; 283 } 284 catch (Exception error) { 285 Gatherer.printStackTrace(error); 286 } 287 return result; 288 } 289 290 private String[] getValues(Element arguments_element) { 291 ArrayList values = new ArrayList(); 292 try { 293 NodeList arguments = arguments_element.getElementsByTagName(ARGUMENT); 294 for(int i = 0; i < arguments.getLength(); i++) { 295 Element argument_element = (Element) arguments.item(i); 296 // Determine if this argument is enabled. 297 if(argument_element.getAttribute(ENABLED).equalsIgnoreCase(TRUE)) { 298 // First store the name of the argument prefixed with a '-' 299 values.add("-" + argument_element.getAttribute(NAME)); 300 // Now retrieve the value. 301 String argument_value = MSMUtils.getValue(argument_element); 302 // If there is a value, tokenize it by commas only. 303 if(argument_value != null && argument_value.length() > 0) { 304 values.add(argument_value); 305 } 306 argument_value = null; 307 } 308 argument_element = null; 309 } 310 arguments = null; 311 } 312 catch (Exception error) { 313 Gatherer.printStackTrace(error); 314 } 315 return ArrayTools.arrayListToStringArray(values); 316 } 317 318 private Element loadArguments(String filename) { 319 Element arguments_element = null; 320 // Run the required program. 321 /** @todo - I never finished implementing this. Have to test that the perl script handles being loaded in this way. 322 try { 323 String args[] = new String[3]; 324 args[0] = Gatherer.config.perl_path; 325 args[1] = filename; 326 args[2] = "-xml"; 241 } 242 } 243 } 244 else if(node_name.equals("Required")) { 245 String v = MSMUtils.getValue(node); 246 if(v != null && v.equals("yes")) { 247 argument.setRequired(true); 248 } 249 } 250 } 251 } 252 } 253 catch (Exception error) { 254 Gatherer.println("Error in BuildOptions.getArgument(): " + error); 255 Gatherer.printStackTrace(error); 256 } 257 return argument; 258 } 259 260 private String getValue(Element arguments_element, String name, boolean is_enabled) { 261 String result = null; 262 try { 263 NodeList arguments = arguments_element.getElementsByTagName(ARGUMENT); 264 for(int i = 0; result == null && i < arguments.getLength(); i++) { 265 Element argument_element = (Element) arguments.item(i); 266 // Is this the argument we want. 267 if(argument_element.getAttribute(NAME).equalsIgnoreCase(name)) { 268 // Are we simply determining if this argument is enabled 269 if(is_enabled) { 270 result = argument_element.getAttribute(ENABLED); 271 } 272 else { 273 String argument_value = MSMUtils.getValue(argument_element); 274 if(argument_value != null) { 275 result = argument_value; 276 } 277 argument_value = null; 278 } 279 } 280 argument_element = null; 281 } 282 arguments = null; 283 } 284 catch (Exception error) { 285 Gatherer.printStackTrace(error); 286 } 287 return result; 288 } 289 290 private String[] getValues(Element arguments_element) { 291 ArrayList values = new ArrayList(); 292 try { 293 NodeList arguments = arguments_element.getElementsByTagName(ARGUMENT); 294 for(int i = 0; i < arguments.getLength(); i++) { 295 Element argument_element = (Element) arguments.item(i); 296 // Determine if this argument is enabled. 297 if(argument_element.getAttribute(ENABLED).equalsIgnoreCase(TRUE)) { 298 // First store the name of the argument prefixed with a '-' 299 values.add("-" + argument_element.getAttribute(NAME)); 300 // Now retrieve the value. 301 String argument_value = MSMUtils.getValue(argument_element); 302 // If there is a value, tokenize it by commas only. 303 if(argument_value != null && argument_value.length() > 0) { 304 values.add(argument_value); 305 } 306 argument_value = null; 307 } 308 argument_element = null; 309 } 310 arguments = null; 311 } 312 catch (Exception error) { 313 Gatherer.printStackTrace(error); 314 } 315 return ArrayTools.arrayListToStringArray(values); 316 } 317 318 private Element loadArguments(String filename) { 319 Element arguments_element = null; 320 // Run the required program. 321 /** @todo - I never finished implementing this. Have to test that the perl script handles being loaded in this way. 322 try { 323 String args[] = new String[3]; 324 args[0] = Gatherer.config.perl_path; 325 args[1] = filename; 326 args[2] = "-xml"; 327 327 // Create the process. 328 328 Runtime runtime = Runtime.getRuntime(); … … 334 334 Document document = parser.getDocument(); 335 335 arguments_element = document.getDocumentElement(); 336 337 336 } 337 catch (Exception error) { 338 338 Gatherer.println("Error in BuildOptions.loadArguments(): " + error); 339 339 Gatherer.printStackTrace(error); 340 }341 */342 return arguments_element;343 }344 345 /** Set the state of some build or import argument. Note that value may be either a single String, and ArrayList of Strings or null. If enable is false then any existing argument for the named argument is disabled. */346 public void setValue(Element arguments_element, String name, boolean enable, String value) {347 ///ystem.err.println("Set value: " + (arguments_element == build_values_element ? "Build" : "Import") + ", " + name + ", " + enable + ", " + value);348 try {349 Document document = arguments_element.getOwnerDocument();350 NodeList arguments = arguments_element.getElementsByTagName(ARGUMENT);351 boolean found = false;352 for(int i = 0; i < arguments.getLength(); i++) {353 Element argument_element = (Element) arguments.item(i);354 // If this the argument named.355 if(argument_element.getAttribute(NAME).equalsIgnoreCase(name)) {356 found = true;357 // Set whether this argument is enabled358 argument_element.setAttribute(ENABLED, (enable ? TRUE : FALSE));359 // Now we set the value, depending or what it is.360 if(value == null) {361 // Nothing to do.362 }363 else {364 // Remove existing text nodes.365 while(argument_element.hasChildNodes()) {366 argument_element.removeChild(argument_element.getFirstChild());367 }368 argument_element.appendChild(document.createTextNode((String)value));369 }370 }371 argument_element = null;372 340 } 341 */ 342 return arguments_element; 343 } 344 345 /** Set the state of some build or import argument. Note that value may be either a single String, and ArrayList of Strings or null. If enable is false then any existing argument for the named argument is disabled. */ 346 public void setValue(Element arguments_element, String name, boolean enable, String value) { 347 ///ystem.err.println("Set value: " + (arguments_element == build_values_element ? "Build" : "Import") + ", " + name + ", " + enable + ", " + value); 348 try { 349 Document document = arguments_element.getOwnerDocument(); 350 NodeList arguments = arguments_element.getElementsByTagName(ARGUMENT); 351 boolean found = false; 352 for(int i = 0; i < arguments.getLength(); i++) { 353 Element argument_element = (Element) arguments.item(i); 354 // If this the argument named. 355 if(argument_element.getAttribute(NAME).equalsIgnoreCase(name)) { 356 found = true; 357 // Set whether this argument is enabled 358 argument_element.setAttribute(ENABLED, (enable ? TRUE : FALSE)); 359 // Now we set the value, depending or what it is. 360 if(value == null) { 361 // Nothing to do. 362 } 363 else { 364 // Remove existing text nodes. 365 while(argument_element.hasChildNodes()) { 366 argument_element.removeChild(argument_element.getFirstChild()); 367 } 368 argument_element.appendChild(document.createTextNode((String)value)); 369 } 370 } 371 argument_element = null; 372 } 373 373 // If we haven't found an instance of this argument, but should have, then add it. 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 374 if(!found && (enable || value != null)) { 375 Element argument_element = document.createElement(ARGUMENT); 376 argument_element.setAttribute(NAME, name); 377 argument_element.setAttribute(ENABLED, (enable ? TRUE : FALSE)); 378 // Now we set the value, depending or what it is. 379 if(value == null) { 380 // Nothing to do. 381 } 382 else { 383 argument_element.appendChild(document.createTextNode((String)value)); 384 } 385 arguments_element.appendChild(argument_element); 386 } 387 arguments = null; 388 document = null; 389 389 // Make sure the collection knows to save. 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 390 Gatherer.c_man.getCollection().setSaved(false); 391 } 392 catch (Exception error) { 393 Gatherer.printStackTrace(error); 394 } 395 } 396 397 /** Remove the named value from the given arguments element. */ 398 private void removeValue(Element arguments_element, String name) { 399 try { 400 NodeList arguments = arguments_element.getElementsByTagName(ARGUMENT); 401 boolean found = false; 402 for(int i = 0; !found && i < arguments.getLength(); i++) { 403 Element argument_element = (Element) arguments.item(i); 404 // Is this the argument we want. 405 if(argument_element.getAttribute(NAME).equalsIgnoreCase(name)) { 406 arguments_element.removeChild(argument_element); 407 found = true; 408 } 409 argument_element = null; 410 } 411 arguments = null; 412 } 413 catch (Exception error) { 414 Gatherer.printStackTrace(error); 415 } 416 } 417 417 } -
trunk/gli/src/org/greenstone/gatherer/collection/Collection.java
r4293 r4366 56 56 */ 57 57 public class Collection { 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 58 /** A reference to the BuildOptions. */ 59 public BuildOptions build_options; 60 /** A reference to the Collection Design Manager. */ 61 public CollectionDesignManager cdm; 62 /** A reference to the Greenstone Directory Metadata Manager. */ 63 public GDMManager gdm; 64 /** A reference to the Metadata Set Manager. */ 65 public MetadataSetManager msm; 66 /** <i>true</i> if the currently loaded collection has been saved since the last significant change, <i>false</i> otherwise. */ 67 private boolean saved = false; 68 /** The collectio configuration file for this collection. */ 69 private CollectionConfiguration collect_cfg; 70 /** The document around which this collection class is based. */ 71 private Document document; 72 /** The file the collection is in (the file may not actually exist, such in the case of a legacy collection)! */ 73 private File file; 74 /** The name of the argument element. */ 75 static final private String ARGUMENT = "Argument"; 76 /** The name of the build element. */ 77 static final private String BUILD = "Build"; 78 /** The name of the built attribute. */ 79 static final private String BUILT = "built"; 80 /** The name of the build config element. */ 81 static final private String BUILD_CONFIG = "BuildConfig"; 82 /** The name of the collection xml template. */ 83 static final private String COLLECTION_XML_TEMPLATE = "xml" + File.separator + "template.col"; 84 /** The name of the directory mappings element. */ 85 static final private String DIRECTORY_MAPPINGS = "DirectoryMappings"; 86 /** The name of the file attribute. */ 87 static final private String FILE = "file"; 88 /** The name of the import element. */ 89 static final private String IMPORT = "Import"; 90 /** The name of the imported attribute. */ 91 static final private String IMPORTED = "imported"; 92 /** The name of the mapping element. */ 93 static final private String MAPPING = "Mapping"; 94 /** The name of the name attribute. */ 95 static final private String NAME = "name"; 96 /** The name of the true value. */ 97 static final private String TRUE = "true"; 98 /** Constructor. */ 99 public Collection(File collection_xml) { 100 this.file = collection_xml; 101 // Try to load this collections details. 102 document = Utility.parse(collection_xml, false); 103 // If that fails load the default settings for a collection. 104 if(document == null) { 105 document = Utility.parse(COLLECTION_XML_TEMPLATE, true); 106 } 107 // Point the Configuration class at our gatherer config arguments. 108 Gatherer.config.setCollectionConfiguration(document); 109 // We also attempt to parse the collection configuration file. 110 collect_cfg = new CollectionConfiguration(new File(collection_xml.getParentFile(), Utility.CONFIG_DIR)); 111 // Finally create all of the child managers that are directly dependant on a collection 112 build_options = new BuildOptions(getBuildValues(), getImportValues()); 113 } 114 /** Add a special directory mapping. */ 115 public boolean addDirectoryMapping(String name, File file) { 116 boolean result = false; 117 try { 118 Element document_element = document.getDocumentElement(); 119 Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS); 120 120 // Ensure the name isn't already in use. 121 122 123 124 125 126 127 128 129 121 boolean found = false; 122 NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING); 123 for(int i = 0; !found && i < mappings.getLength(); i++) { 124 Element mapping_element = (Element) mappings.item(i); 125 if(mapping_element.getAttribute(NAME).equalsIgnoreCase(name)) { 126 found = true; 127 } 128 mapping_element = null; 129 } 130 130 // Otherwise add the mapping. 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 131 if(!found) { 132 Element mapping_element = document.createElement(MAPPING); 133 mapping_element.setAttribute(NAME, name); 134 mapping_element.setAttribute(FILE, file.toString()); 135 directory_mappings_element.appendChild(mapping_element); 136 result = true; 137 mapping_element = null; 138 } 139 mappings = null; 140 directory_mappings_element = null; 141 document_element = null; 142 saved = false; 143 } 144 catch (Exception error) { 145 Gatherer.printStackTrace(error); 146 } 147 return result; 148 } 149 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 150 /** Destructor. 151 * @see org.greenstone.gatherer.collection.CollectionModel */ 152 public void destroy() { 153 cdm.destroy(); 154 gdm.destroy(); 155 msm.destroy(); 156 Gatherer.config.setCollectionConfiguration(null); 157 cdm = null; 158 document = null; 159 gdm = null; 160 msm = null; 161 } 162 /** Determine whether this collection has been successfully built in the past. 163 * @return <i>true</i> if the collection has been built, <i>false</i> otherwise. 164 */ 165 public boolean getBuilt() { 166 return get(BUILT); 167 } 168 /** Calculates the number of documents in this collection. */ 169 public int getDocumentCount() { 170 return getCount((TreeNode)Gatherer.c_man.getRecordSet().getRoot(), false); 171 } 172 /** Retrieve the description of this collection. 173 * @return The description as a <strong>String</strong>. 174 */ 175 public String getDescription() { 176 return collect_cfg.getDescription(); 177 } 178 /** Retrieve a specific directory mapping associated with this collection. 179 * @param name The name of the mapping to retrieve as a <strong>String</strong>. 180 * @return The <strong>File</strong> this name maps to, or <i>null</i> if no such mapping. 181 */ 182 public File getDirectoryMapping(String name) { 183 File result = null; 184 try { 185 Element document_element = document.getDocumentElement(); 186 Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS); 187 187 // Ensure the name isn't already in use. 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 188 boolean found = false; 189 NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING); 190 for(int i = 0; !found && i < mappings.getLength(); i++) { 191 Element mapping_element = (Element) mappings.item(i); 192 if(mapping_element.getAttribute(NAME).equalsIgnoreCase(name)) { 193 result = new File(MSMUtils.getValue(mapping_element)); 194 found = true; 195 } 196 mapping_element = null; 197 } 198 mappings = null; 199 directory_mappings_element = null; 200 document_element = null; 201 } 202 catch(Exception error) { 203 Gatherer.printStackTrace(error); 204 } 205 return result; 206 } 207 /** Retrieve the special directory mappings associated with this collection. 208 * @return A <strong>HashMap</strong> containing mappings from names to directories. 209 */ 210 public HashMap getDirectoryMappings() { 211 HashMap special_directories = new HashMap(); 212 try { 213 Element document_element = document.getDocumentElement(); 214 Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS); 215 215 // Ensure the name isn't already in use. 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 216 boolean found = false; 217 NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING); 218 for(int i = 0; !found && i < mappings.getLength(); i++) { 219 Element mapping_element = (Element) mappings.item(i); 220 String name = mapping_element.getAttribute(NAME); 221 File file = new File(mapping_element.getAttribute(FILE)); 222 special_directories.put(name, file); 223 file = null; 224 name = null; 225 mapping_element = null; 226 } 227 mappings = null; 228 directory_mappings_element = null; 229 document_element = null; 230 } 231 catch(Exception error) { 232 Gatherer.printStackTrace(error); 233 } 234 return special_directories; 235 } 236 /** Retrieve the authors email for this collection. 237 * @return The email as a <strong>String</strong>. 238 */ 239 public String getEmail() { 240 return collect_cfg.getCreator(); 241 } 242 /** Counts the number of folders used in the current record set. */ 243 public int getFolderCount() { 244 return getCount((TreeNode)Gatherer.c_man.getRecordSet().getRoot(), true); 245 } 246 /** Determine if this collection has had an import action run upon it since the last major change. 247 * @return <i>true</i> if an import has occured, <i>false</i> otherwise. 248 */ 249 public boolean getImported() { 250 return get(IMPORTED); 251 } 252 /** Retrieve the short name for this collection. 253 * @return The name as a <strong>String</strong>. 254 */ 255 public String getName() { 256 return file.getParentFile().getName(); 257 } 258 /** Determine if this collection has been saved since the last major change. 259 * @return <i>true</i> if it has been saved recently, <i>false</i> otherwise. 260 */ 261 public boolean getSaved() { 262 return saved; 263 } 264 /** Retrieve the title of this collection. 265 * @return The title as a <strong>String</strong>. 266 */ 267 public String getTitle() { 268 return collect_cfg.getName(); 269 } 270 /** Remove a previously defined special directory mapping. 271 * @param name The name of the mapping to remove as a <strong>String</strong>. 272 * @return The <strong>File</strong> of the mapping removed. 273 */ 274 public File removeDirectoryMapping(String name) { 275 File file = null; 276 try { 277 Element document_element = document.getDocumentElement(); 278 Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS); 279 279 // Ensure the name isn't already in use. 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 280 boolean found = false; 281 NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING); 282 for(int i = 0; !found && i < mappings.getLength(); i++) { 283 Element mapping_element = (Element) mappings.item(i); 284 if(mapping_element.getAttribute(NAME).equalsIgnoreCase(name)) { 285 file = new File(MSMUtils.getValue(mapping_element)); 286 directory_mappings_element.removeChild(mapping_element); 287 found = true; 288 } 289 mapping_element = null; 290 } 291 mappings = null; 292 directory_mappings_element = null; 293 document_element = null; 294 saved = false; 295 } 296 catch(Exception error) { 297 Gatherer.printStackTrace(error); 298 } 299 return file; 300 } 301 /** Save this xml document to the given file. */ 302 public void save() { 303 Utility.export(document, file); 304 } 305 /** Set the value of built to the given value. 306 * @param value The new value for built, <i>true</i> if the collection has been built successfully, <i>false</i> otherwise. 307 */ 308 public void setBuilt(boolean value) { 309 set(BUILT, value); 310 saved = false; 311 } 312 /** Set the value of imported to the given value. 313 * @param value The new value for imported, <i>true</i> if the collection has been imported successfully, <i>false</i> otherwise. 314 */ 315 public void setImported(boolean value) { 316 set(IMPORTED, value); 317 saved = false; 318 } 319 /** Set the value of saved to the given value. 320 * @param value The new value for saved, <i>true</i> if the collection has been saved recently, <i>false</i> otherwise. 321 */ 322 public void setSaved(boolean value) { 323 saved = value; 324 } 325 /** Set the value of title to the given value. 326 * @param title The new <strong>String</strong> title. 327 */ 328 public void setTitle(String title) { 329 collect_cfg.setName(title); 330 } 331 /** Method called to return a textual representation of a class, which in this case is the collections title. 332 * @return A <strong>String</strong> containing the collections title. 333 */ 334 public String toString() { 335 return collect_cfg.getName(); 336 } 337 /** Get the value of a collection argument. */ 338 private boolean get(String name) { 339 boolean result = false; 340 try { 341 Element document_element = document.getDocumentElement(); 342 NodeList arguments = document_element.getElementsByTagName(ARGUMENT); 343 boolean found = false; 344 for(int i = 0; !found && i < arguments.getLength(); i++) { 345 Element argument_element = (Element) arguments.item(i); 346 if(argument_element.getParentNode() == document_element) { 347 if(argument_element.getAttribute(NAME).equalsIgnoreCase(BUILT)) { 348 String value = MSMUtils.getValue(argument_element); 349 if(value.equalsIgnoreCase(TRUE)) { 350 result = true; 351 } 352 found = true; 353 value = null; 354 } 355 } 356 argument_element = null; 357 } 358 arguments = null; 359 document_element = null; 360 } 361 catch (Exception error) { 362 Gatherer.printStackTrace(error); 363 } 364 return result; 365 } 366 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 367 /** Method to retrieve the current build options associated with this Collection. */ 368 private Element getBuildValues() { 369 Element build_values_element = null; 370 try { 371 Element document_element = document.getDocumentElement(); 372 Element build_config_element = (Element) MSMUtils.getNodeFromNamed(document_element, BUILD_CONFIG); 373 build_values_element = (Element) MSMUtils.getNodeFromNamed(build_config_element, BUILD); 374 build_config_element = null; 375 document_element = null; 376 } 377 catch (Exception error) { 378 Gatherer.printStackTrace(error); 379 } 380 return build_values_element; 381 } 382 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 383 /** Count either documents or folders, depending on the state of the given boolean. */ 384 private int getCount(TreeNode node, boolean folders) { 385 int count = 0; 386 File file = ((FileNode)node).getFile(); 387 if(file.isFile() && !folders) { 388 count++; 389 } 390 else if(file.isDirectory() && folders) { 391 count++; 392 } 393 for(int i = 0; i < node.getChildCount(); i++) { 394 count = count + getCount(node.getChildAt(i), folders); 395 } 396 return count; 397 } 398 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 399 /** Method to retrieve the current import options associated with this Collection. */ 400 public Element getImportValues() { 401 Element import_values_element = null; 402 try { 403 Element document_element = document.getDocumentElement(); 404 Element build_config_element = (Element) MSMUtils.getNodeFromNamed(document_element, BUILD_CONFIG); 405 import_values_element = (Element) MSMUtils.getNodeFromNamed(build_config_element, IMPORT); 406 build_config_element = null; 407 document_element = null; 408 } 409 catch (Exception error) { 410 Gatherer.printStackTrace(error); 411 } 412 return import_values_element; 413 } 414 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 415 /** Set the value of a collection argument. */ 416 private void set(String name, boolean value) { 417 try { 418 Element document_element = document.getDocumentElement(); 419 NodeList arguments = document_element.getElementsByTagName(ARGUMENT); 420 boolean found = false; 421 for(int i = 0; !found && i < arguments.getLength(); i++) { 422 Element argument_element = (Element) arguments.item(i); 423 if(argument_element.getParentNode() == document_element) { 424 if(argument_element.getAttribute(NAME).equalsIgnoreCase(BUILT)) { 425 // Strip any current value nodes. 426 while(argument_element.hasChildNodes()) { 427 argument_element.removeChild(argument_element.getFirstChild()); 428 } 429 // Append new value 430 argument_element.appendChild(document.createTextNode(value ? "true" : "false")); 431 } 432 } 433 argument_element = null; 434 } 435 arguments = null; 436 document_element = null; 437 } 438 catch (Exception error) { 439 Gatherer.printStackTrace(error); 440 } 441 } 442 442 } -
trunk/gli/src/org/greenstone/gatherer/collection/CollectionConfiguration.java
r4293 r4366 10 10 public class CollectionConfiguration { 11 11 12 13 14 15 16 17 18 19 12 private Element creator_element; 13 private Element description_element; 14 private Element maintainer_element; 15 private Element name_element; 16 private String creator; 17 private String description; 18 private String maintainer; 19 private String name; 20 20 21 22 23 24 21 public CollectionConfiguration(File file) { 22 try { 23 String filename = file.getName().toLowerCase(); 24 if(filename.endsWith(".xml")) { 25 25 26 } 27 else if(filename.endsWith(".cfg")) { 28 FileReader fr = new FileReader(file); 29 BufferedReader br = new BufferedReader(fr); 30 String command = null; 31 while((command = br.readLine()) != null) { 32 if(command.length() > 0) { 33 // We have to test the end of command for the special character '\'. If found, remove it and append the next line, then repeat. 34 while(command.trim().endsWith("\\")) { 35 command = command.substring(0, command.lastIndexOf("\\")); 36 String next_line = br.readLine(); 37 if(next_line != null) { 38 command = command + next_line; 39 } 40 next_line = null; 41 } 42 CommandTokenizer tokenizer = new CommandTokenizer(command); 43 if(tokenizer.countTokens() >= 2) { 44 String temp = tokenizer.nextToken(); 45 if(temp.equalsIgnoreCase("creator")) { 46 creator = tokenizer.nextToken(); 47 } 48 else if(temp.equalsIgnoreCase("maintainer")) { 49 maintainer = tokenizer.nextToken(); 50 } 51 else if(temp.equalsIgnoreCase("collectionmeta")) { 52 temp = tokenizer.nextToken(); 53 if(temp.equalsIgnoreCase("collectionname")) { 54 temp = tokenizer.nextToken(); 55 if(temp.startsWith("[") && temp.endsWith("]")) { 56 String language = temp.substring(temp.indexOf("=") + 1, temp.length() - 1); 57 if(name == null || language.equalsIgnoreCase(Gatherer.dictionary.getLanguage())) { 58 name = Utility.decodeGreenstone(tokenizer.nextToken()); 59 } 60 } 61 else if(name == null) { 62 name = Utility.decodeGreenstone(temp); 63 } 64 if(name != null && name.startsWith("\"") && name.endsWith("\"")) { 65 name = name.substring(1, name.length() - 1); 66 } 26 67 } 27 else if(filename.endsWith(".cfg")) { 28 FileReader fr = new FileReader(file); 29 BufferedReader br = new BufferedReader(fr); 30 String command = null; 31 while((command = br.readLine()) != null) { 32 if(command.length() > 0) { 33 // We have to test the end of command for the special character '\'. If found, remove it and append the next line, then repeat. 34 while(command.trim().endsWith("\\")) { 35 command = command.substring(0, command.lastIndexOf("\\")); 36 String next_line = br.readLine(); 37 if(next_line != null) { 38 command = command + next_line; 39 } 40 next_line = null; 41 } 42 CommandTokenizer tokenizer = new CommandTokenizer(command); 43 if(tokenizer.countTokens() >= 2) { 44 String temp = tokenizer.nextToken(); 45 if(temp.equalsIgnoreCase("creator")) { 46 creator = tokenizer.nextToken(); 47 } 48 else if(temp.equalsIgnoreCase("maintainer")) { 49 maintainer = tokenizer.nextToken(); 50 } 51 else if(temp.equalsIgnoreCase("collectionmeta")) { 52 temp = tokenizer.nextToken(); 53 if(temp.equalsIgnoreCase("collectionname")) { 54 temp = tokenizer.nextToken(); 55 if(temp.startsWith("[") && temp.endsWith("]")) { 56 String language = temp.substring(temp.indexOf("=") + 1, temp.length() - 1); 57 if(name == null || language.equalsIgnoreCase(Gatherer.dictionary.getLanguage())) { 58 name = Utility.decodeGreenstone(tokenizer.nextToken()); 59 } 60 } 61 else if(name == null) { 62 name = Utility.decodeGreenstone(temp); 63 } 64 if(name != null && name.startsWith("\"") && name.endsWith("\"")) { 65 name = name.substring(1, name.length() - 1); 66 } 67 } 68 else if(temp.equalsIgnoreCase("collectionextra")) { 69 temp = tokenizer.nextToken(); 70 ///ystem.err.println("Read: " + temp); 71 if(temp.startsWith("[") && temp.endsWith("]")) { 72 String language = temp.substring(temp.indexOf("=") + 1, temp.length() - 1); 73 ///ystem.err.println("Try to match " + language + " to " + Gatherer.dictionary.getLanguage()); 74 if(description == null || language.equalsIgnoreCase(Gatherer.dictionary.getLanguage())) { 75 description = Utility.decodeGreenstone(tokenizer.nextToken()); 76 ///ystem.err.println("Found language match, or first match: " + description); 77 } 78 } 79 else if(description == null) { 80 description = Utility.decodeGreenstone(temp); 81 ///ystem.err.println("Found first match: " + description); 82 } 83 if(description != null && description.startsWith("\"") && description.endsWith("\"")) { 84 description = description.substring(1, description.length() - 1); 85 } 86 } 87 } 88 temp = null; 89 } 90 tokenizer = null; 91 } 92 } 93 command = null; 94 br.close(); 95 br = null; 96 fr.close(); 97 fr = null; 68 else if(temp.equalsIgnoreCase("collectionextra")) { 69 temp = tokenizer.nextToken(); 70 ///ystem.err.println("Read: " + temp); 71 if(temp.startsWith("[") && temp.endsWith("]")) { 72 String language = temp.substring(temp.indexOf("=") + 1, temp.length() - 1); 73 ///ystem.err.println("Try to match " + language + " to " + Gatherer.dictionary.getLanguage()); 74 if(description == null || language.equalsIgnoreCase(Gatherer.dictionary.getLanguage())) { 75 description = Utility.decodeGreenstone(tokenizer.nextToken()); 76 ///ystem.err.println("Found language match, or first match: " + description); 77 } 78 } 79 else if(description == null) { 80 description = Utility.decodeGreenstone(temp); 81 ///ystem.err.println("Found first match: " + description); 82 } 83 if(description != null && description.startsWith("\"") && description.endsWith("\"")) { 84 description = description.substring(1, description.length() - 1); 85 } 98 86 } 87 } 88 temp = null; 89 } 90 tokenizer = null; 91 } 92 } 93 command = null; 94 br.close(); 95 br = null; 96 fr.close(); 97 fr = null; 98 } 99 99 ///ystem.err.println("Parsed collect.cfg"); 100 100 ///ystem.err.println("name = " + name); … … 102 102 ///ystem.err.println("maintainer = " + maintainer); 103 103 ///ystem.err.println("description = " + description); 104 105 106 107 108 109 104 } 105 catch(Exception error) { 106 Gatherer.println("Error in CollectionConfiguration.<init>(): " + error); 107 Gatherer.printStackTrace(error); 108 } 109 } 110 110 111 112 113 114 115 116 117 118 119 120 111 public String getCreator() { 112 String result = ""; 113 if(creator_element != null) { 114 result = MSMUtils.getValue(creator_element); 115 } 116 else if(creator != null) { 117 result = creator; 118 } 119 return result; 120 } 121 121 122 123 124 125 126 127 128 129 130 131 122 public String getDescription() { 123 String result = ""; 124 if(description_element != null) { 125 result = MSMUtils.getValue(description_element); 126 } 127 else if(description != null) { 128 result = description; 129 } 130 return result; 131 } 132 132 133 134 135 136 137 138 139 140 141 142 133 public String getMaintainer() { 134 String result = ""; 135 if(maintainer_element != null) { 136 result = MSMUtils.getValue(maintainer_element); 137 } 138 else if(maintainer != null) { 139 result = maintainer; 140 } 141 return result; 142 } 143 143 144 145 146 147 148 149 150 151 152 153 144 public String getName() { 145 String result = "Error"; 146 if(name_element != null) { 147 result = MSMUtils.getValue(name_element); 148 } 149 else if(name != null) { 150 result = name; 151 } 152 return result; 153 } 154 154 155 156 157 155 public void setName(String name) { 156 /** @todo */ 157 } 158 158 } -
trunk/gli/src/org/greenstone/gatherer/collection/CollectionManager.java
r4351 r4366 76 76 */ 77 77 public class CollectionManager 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 78 implements GShellListener, MSMListener { 79 /** A reference to the metadata set manager. 80 * @deprecated 81 */ 82 public MetadataSetManager msm; 83 /** A reference to the undo manager. Although only one instance is shared between all collections, the undo queues are emptied between each. */ 84 public UndoManager undo; 85 /** Are we currently in the process of building? */ 86 private boolean building = false; 87 /** Are we currently in the process of importing? */ 88 private boolean importing = false; 89 /** The collection this manager is managing! */ 90 private Collection collection = null; 91 /** The collection_model. */ 92 private FileSystemModel collection_model = null; 93 /** The workspace model. This becomes invalid on a collection change. */ 94 private FileSystemModel workspace_model = null; 95 /** An inner class listener responsible for noting tree changes and resetting saved when they occur. */ 96 private FMTreeModelListener fm_tree_model_listener = null; 97 /** The monitor resposible for parsing the build process. */ 98 private GShellProgressMonitor build_monitor = null; 99 /** The monitor resposible for parsing the copy process. */ 100 private GShellProgressMonitor copy_monitor = null; 101 /** The monitor resposible for parsing the import process. */ 102 private GShellProgressMonitor import_monitor = null; 103 104 private int special_case = -1; 105 /** The name of the standard lock file. */ 106 static final public String LOCK_FILE = "gatherer.lck"; 107 static final public int NO_SPECIAL_CASE = -1; 108 static final public int SPECIAL_DLS = 0; 109 /** Constructor. */ 110 public CollectionManager() { 111 // Initialisation. 112 this.building = false; 113 this.importing = false; 114 this.collection = null; 115 this.undo = new UndoManager(); 116 } 117 /** Add a special directory mapping. 118 118 * @param name The name for this directory mapping as a <strong>String</strong>. 119 119 * @param file The directory this mapping maps to as a <strong>File</strong>. 120 120 */ 121 122 121 public void addDirectoryMapping(String name, File file) { 122 if(ready()) { 123 123 // Update the information stored in the collection 124 124 collection.addDirectoryMapping(name, file); 125 125 // Now update the tree 126 127 128 129 130 131 132 126 FileSystemModel model = (FileSystemModel) Gatherer.g_man.collection_pane.getWorkspaceTree().getModel(); 127 FileNode parent = (FileNode) model.getRoot(); 128 FileNode target = new FileNode(file, name); 129 SynchronizedTreeModelTools.insertNodeInto(model, parent, target); 130 } 131 } 132 /** This method calls the builcol.pl scripts via a GShell so as to not lock up the processor. 133 133 * @see org.greenstone.gatherer.Configuration 134 134 * @see org.greenstone.gatherer.Gatherer … … 141 141 * @see org.greenstone.gatherer.util.Utility 142 142 */ 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 143 public void buildCollection() { 144 Gatherer.println("Building collection"); 145 building = true; 146 147 String args[]; 148 if(Utility.isWindows()) { 149 args = new String[4]; 150 args[0] = Gatherer.config.perl_path; 151 args[1] = "-S"; 152 args[2] = Gatherer.config.getScriptPath() + "buildcol.pl"; 153 args[3] = collection.getName(); 154 } 155 else { 156 args = new String[2]; 157 args[0] = Gatherer.config.getScriptPath() + "buildcol.pl"; 158 args[1] = collection.getName(); 159 } 160 args = ArrayTools.add(args, collection.build_options.getBuildValues()); 161 GShell shell = new GShell(args, GShell.BUILD, Message.BUILDING, this, build_monitor, GShell.GSHELL_BUILD); 162 shell.addGShellListener(Gatherer.g_man.create_pane); 163 shell.start(); 164 } 165 /** Used to determine whether the currently active collection has been built. 166 166 * @return A boolean indicating the built status of the collection. 167 167 */ 168 169 170 171 172 173 174 175 * @see org.greenstone.gatherer.Gatherer 176 * @see org.greenstone.gatherer.collection.Collection 177 * @see org.greenstone.gatherer.util.Utility 178 */ 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 168 public boolean built() { 169 if(collection != null) { 170 return collection.getBuilt(); 171 } 172 return false; 173 } 174 /** Called to close the current collection and remove its lock file. 175 * @see org.greenstone.gatherer.Gatherer 176 * @see org.greenstone.gatherer.collection.Collection 177 * @see org.greenstone.gatherer.util.Utility 178 */ 179 public void closeCollection() { 180 // Remove the lock on this file, then remove the collection. 181 File lock_file = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator + LOCK_FILE); 182 lock_file.delete(); 183 collection.msm.destroy(); 184 collection = null; 185 collection_model = null; 186 workspace_model = null; 187 undo.clear(); 188 Gatherer.config.setCollectionConfiguration(null); 189 Gatherer.g_man.collectionChanged(false); 190 } 191 192 /** Method that is called whenever something has changed in the configuration of this collection. */ 193 public void configurationChanged() { 194 if(collection != null) { 195 collection.setSaved(false); 196 } 197 } 198 199 /** Used to set the current collection to the given collection. Note that this call should -always- be proceeded by a ready call, and if the colection is ready and the saved flag is unset then the user should be prompted to save. Also note that this method creates yet another GShell to run buildcol.pl. */ 200 public void createCollection(String description, String email, String name, String title, File base_collection_directory, ArrayList metadata_sets) { 201 special_case = NO_SPECIAL_CASE; 202 try { 203 203 // Create a progress monitor. 204 204 ProgressMonitor progress = new ProgressMonitor(Gatherer.g_man, get("Creating_New"), "mkcol.pl", 0, 7); 205 205 // Create the new collection. 206 207 206 makeCollection(description, email, name, title); 207 progress.setProgress(1); 208 208 209 209 // ACTIVE_DIR/gimport/ 210 210 String a_dir = Utility.getCollectionDir(Gatherer.config.gsdl_path) + name + File.separator; 211 211 212 212 // Has to be done before creating greenstone directory metadata manager. 213 214 215 216 217 218 213 File gimport_dir_temp = new File(Utility.getImportDir(a_dir)+"temp.dat"); 214 File gimport_dir = gimport_dir_temp.getParentFile(); 215 gimport_dir.mkdirs(); 216 if(progress != null) { 217 progress.setNote(get("Gimport_Created")); 218 } 219 219 220 220 // ACTIVE_DIR/gcache/ 221 222 223 224 225 226 221 File gcache_dir_temp = new File(Utility.getCacheDir(a_dir)+"temp.dat"); 222 File gcache_dir = gcache_dir_temp.getParentFile(); 223 gcache_dir.mkdirs(); 224 if(progress != null) { 225 progress.setNote(get("Gcache_Created")); 226 } 227 227 228 228 // ACTIVE_DIR/log/ 229 230 231 232 233 234 229 File log_dir_temp = new File(Utility.getLogDir(a_dir)+"temp.dat"); 230 File log_dir = log_dir_temp.getParentFile(); 231 log_dir.mkdirs(); 232 if(progress != null) { 233 progress.setNote(get("Log_Created")); 234 } 235 235 236 236 progress.setProgress(2); 237 237 238 238 // Now create the collection object around the directory. 239 240 241 242 239 collection = new Collection(new File(a_dir, name + ".col")); 240 collection.msm = new MetadataSetManager(); 241 msm = collection.msm; // Legacy 242 collection.msm.load(); 243 243 // Import default metadata sets if any. 244 245 246 247 244 for(int i = 0; metadata_sets != null && i < metadata_sets.size(); i++) { 245 MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i); 246 collection.msm.importMDS(metadata_set.getFile(), false); 247 } 248 248 249 249 // Before we create the CollectionDesignManager we have to check if we are basing it upon some other collection. 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 250 if(base_collection_directory != null) { 251 // If so our first step is to correctly generate an import profile for our collection from this base collection. 252 // Try to import any existing metadata sets for this collection. Look in base_collection_directory/metadata and import any metadata sets found. 253 File base_metadata = new File(base_collection_directory, Utility.METADATA_DIR); 254 if(base_metadata.exists()) { 255 File[] possible_metadata_sets = base_metadata.listFiles(); 256 for(int i = 0; possible_metadata_sets != null && i < possible_metadata_sets.length; i++) { 257 String filename = possible_metadata_sets[i].getName(); 258 if(filename.endsWith(".mds")) { 259 ///ystem.err.println("Found a metadata set. Importing: " + possible_metadata_sets[i].getAbsolutePath()); 260 collection.msm.importMDS(possible_metadata_sets[i], false); 261 } 262 } 263 } 264 // If no sets were imported, then create a new metadata with this new collections name. Note that if this is one of the 'big five' collections then I already know the importing mappings as well. 265 boolean skip_import_phase = false; 266 if(collection.msm.getSets().size() == 0) { 267 CollectionConfiguration col_con = new CollectionConfiguration(new File(base_collection_directory, Utility.CONFIG_DIR)); 268 // If the source collection is one of the 'big five' then we know what the metadata set is. 269 String collection_name = col_con.getName(); 270 // Demo collection - part of the DLS 271 if(collection_name.equals(Utility.COLLECTION_DEMO) || collection_name.equals(Utility.COLLECTION_DLS)) { 272 special_case = SPECIAL_DLS; 273 String demo_directory = (new File(base_collection_directory.getParentFile(), Utility.COLLECTION_DEMO_DIRECTORY)).getAbsolutePath(); 274 String dls_directory = (new File(base_collection_directory.getParentFile(), Utility.COLLECTION_DLS_DIRECTORY)).getAbsolutePath(); 275 // Add the dls.mds 276 collection.msm.importMDS(new File(Utility.METADATA_DIR + Utility.DLS_MDS), false); 277 // Add the mappings for the dls (even if its not present). 278 collection.msm.profiler.addAction(dls_directory, "AZList", "dls.AZList"); 279 collection.msm.profiler.addAction(dls_directory, "Keyword", "dls.Keyword"); 280 collection.msm.profiler.addAction(dls_directory, "Language", "dls.Language"); 281 collection.msm.profiler.addAction(dls_directory, "Organization", "dls.Organization"); 282 collection.msm.profiler.addAction(dls_directory, "Subject", "dls.Subject"); 283 collection.msm.profiler.addAction(dls_directory, "Title", "dls.Title"); 284 // Add the mappings for the demo dls (even if its not present). 285 collection.msm.profiler.addAction(demo_directory, "AZList", "dls.AZList"); 286 collection.msm.profiler.addAction(demo_directory, "Keyword", "dls.Keyword"); 287 collection.msm.profiler.addAction(demo_directory, "Language", "dls.Language"); 288 collection.msm.profiler.addAction(demo_directory, "Organization", "dls.Organization"); 289 collection.msm.profiler.addAction(demo_directory, "Subject", "dls.Subject"); 290 collection.msm.profiler.addAction(demo_directory, "Title", "dls.Title"); 291 // Skip the import phase 292 skip_import_phase = true; 293 } 294 // Prompt the user so that they can choose at least one initial metadata set. We're sneaky here and just create a ncm_prompt 295 else { 296 NewCollectionMetadataPrompt ncm_prompt = new NewCollectionMetadataPrompt(); 297 // If cancelled then they really do mean to start a collection with no metadata sets. 298 if(!ncm_prompt.isCancelled()) { 299 ArrayList initial_sets = ncm_prompt.getSets(); 300 for(int i = 0; initial_sets != null && i < initial_sets.size(); i++) { 301 MetadataSet metadata_set = (MetadataSet) initial_sets.get(i); 302 collection.msm.importMDS(metadata_set.getFile(), false); 303 metadata_set = null; 304 } 305 initial_sets = null; 306 } 307 ncm_prompt.dispose(); 308 ncm_prompt = null; 309 } 310 } 311 // Do a dry metadata import run over the entire base collection, recording profile mappings. We do this by finding the archive files, and then iterating over them using the GreenstoneArchiveParser to retrieve metadata from them. We then process the importing of new metadata elements using the selectElement prompt used in a file action metadata import. However the big change is that we don't actually import any metadata, just create importing profiles. 312 File base_archives = new File(base_collection_directory, Utility.ARCHIVE_DIR); 313 if(!skip_import_phase && base_archives.exists()) { 314 ///ystem.err.println("Found archives directory."); 315 } 316 // Failing that we do a dummy run over the files in the collection. 317 else if(!skip_import_phase) { 318 ///ystem.err.println("No archives directory. Searching files for metadata.xml information."); 319 // Find the import directory 320 File base_import = new File(base_collection_directory, Utility.IMPORT_DIR); 321 if(!base_import.exists()) { 322 base_import = new File(base_collection_directory, Utility.OLD_IMPORT_DIR); 323 } 324 if(base_import.exists()) { 325 searchForMetadata(base_import); 326 } 327 // And if that fails then we must have been asked by Satan himself to build the very digital collections of hell, because they don't match any goodly greenstone collection I have ever seen, so you can't blame me if I can't import them. 328 } 329 // Now we update our collect.cfg 330 updateCollectionCFG(new File(base_collection_directory, Utility.CONFIG_DIR), new File(a_dir, Utility.CONFIG_DIR), description, email, title); 331 } 332 333 collection.cdm = new CollectionDesignManager(); 334 collection.gdm = new GDMManager(); 335 336 progress.setProgress(3); 337 337 338 338 // Has to be done after creating metadata set manager. 339 340 341 342 343 344 345 346 347 339 File gmeta_dir_temp = new File(getCollectionMetadata()+"temp.dat"); 340 File gmeta_dir = gmeta_dir_temp.getParentFile(); 341 gmeta_dir.mkdirs(); 342 if(progress != null) { 343 progress.setNote("GMeta created"); 344 } 345 progress.setProgress(4); 346 347 progress.setProgress(6); 348 348 // Register ourselves as being interested in what the msm has to say. 349 349 collection.msm.addMSMListener(this); 350 350 // Create a lock file. 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 351 File lock_file = new File(a_dir, LOCK_FILE); 352 FileOutputStream out = new FileOutputStream(lock_file); 353 out.write(LOCK_FILE.getBytes()); 354 out.close(); 355 out = null; 356 progress.setProgress(7); 357 String args[] = new String[1]; 358 args[0] = name; 359 progress.setNote(get("Session_Ready", args)); 360 progress.close(); 361 } 362 catch (Exception error) { 363 Gatherer.printStackTrace(error); 364 } 365 // Done. 366 if(Gatherer.g_man != null) { 367 workspace_model = null; 368 Gatherer.g_man.collectionChanged(ready()); 369 } 370 } 371 372 public void createLockFile(File destination) { 373 try { 374 Document default_lockfile = Utility.parse("xml" + File.separator + LOCK_FILE, true); 375 String user_name = System.getProperty("user.name"); 376 Element person_element = (Element) MSMUtils.getNodeFromNamed(default_lockfile.getDocumentElement(), "User"); 377 person_element.appendChild(default_lockfile.createTextNode(user_name)); 378 person_element = null; 379 user_name = null; 380 String machine_name = Utility.getMachineName(); 381 Element machine_element = (Element) MSMUtils.getNodeFromNamed(default_lockfile.getDocumentElement(), "Machine"); 382 machine_element.appendChild(default_lockfile.createTextNode(machine_name)); 383 machine_element = null; 384 machine_name = null; 385 String date_time = Utility.getDateString(); 386 Element date_element = (Element) MSMUtils.getNodeFromNamed(default_lockfile.getDocumentElement(), "Date"); 387 date_element.appendChild(default_lockfile.createTextNode(date_time)); 388 date_element = null; 389 date_time = null; 390 Utility.export(default_lockfile, destination); 391 } 392 catch (Exception error) { 393 Gatherer.printStackTrace(error); 394 } 395 } 396 397 /** Method that is called whenever an element within a set is changed or modified. We want to mark the collection so that it needs saving again. 398 398 * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired. 399 399 * @see org.greenstone.gatherer.collection.Collection 400 400 */ 401 402 403 404 405 401 public void elementChanged(MSMEvent event) { 402 // This means the state of the collections has changed, so we should set saved to false. 403 collection.setSaved(false); 404 } 405 /** Used to retrieve the build options associated with the currently loaded collection. If none yet exist, default ones are created. 406 406 * @return A <strong>BuildOptions</strong> object containing the build options for the current collection. 407 407 * @see org.greenstone.gatherer.collection.Collection 408 408 */ 409 410 411 412 413 409 public BuildOptions getBuildOptions() { 410 return collection.build_options; 411 } 412 413 /** Retrieve the current collection. 414 414 * @return The <strong>Collection</strong> itself. 415 415 */ 416 417 418 419 416 public Collection getCollection() { 417 return collection; 418 } 419 /** Constructs the absolute filename of the collection archive directory, which should resemble "$GSDLHOME/collect/<col_name>/archive/" 420 420 * @return A <strong>String</strong> containing the filename. 421 421 * @see org.greenstone.gatherer.Configuration … … 424 424 * @see org.greenstone.gatherer.util.Utility 425 425 */ 426 427 428 429 426 public String getCollectionArchive() { 427 return Utility.getArchiveDir(Gatherer.config.gsdl_path, collection.getName()); 428 } 429 /** Constructs the absolute filename of the collection building directory, which should resemble "$GSDLHOME/collect/<col_name>/building/" 430 430 * @return A <strong>String</strong> containing the filename. 431 431 * @see org.greenstone.gatherer.Configuration … … 434 434 * @see org.greenstone.gatherer.util.Utility 435 435 */ 436 437 438 439 436 public String getCollectionBuild() { 437 return Utility.getBuildDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator); 438 } 439 /** Constructs the absolute filename of the collection cache directory, which should resemble "$GSDLHOME/collect/<col_name>/gcache/" 440 440 * @return A <strong>String</strong> containing the filename. 441 441 * @see org.greenstone.gatherer.Configuration … … 444 444 * @see org.greenstone.gatherer.util.Utility 445 445 */ 446 447 448 449 446 public String getCollectionCache() { 447 return Utility.getCacheDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator); 448 } 449 /** Constructs the absolute filename of the collection config file, which should resemble "$GSDLHOME/collect/<col_name>/etc/collect.cfg" 450 450 * @return A <strong>String</strong> containing the filename. 451 451 * @see org.greenstone.gatherer.Configuration … … 454 454 * @see org.greenstone.gatherer.util.Utility 455 455 */ 456 457 458 459 460 456 public String getCollectionConfig() { 457 return Utility.getConfigDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator); 458 } 459 460 /** Constructs the absolute filename of the collection directory, which should resemble "$GSDLHOME/collect/<col_name>" 461 461 * @return A <strong>String</strong> containing the directory name. 462 462 * @see org.greenstone.gatherer.Configuration … … 465 465 * @see org.greenstone.gatherer.util.Utility 466 466 */ 467 468 469 470 471 467 public String getCollectionDirectory() { 468 return Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator; 469 } 470 471 /** Constructs the absolute filename of the collection etc directory, which should resemble "$GSDLHOME/collect/<col_name>/etc/" 472 472 * @return A <strong>String</strong> containing the filename. 473 473 * @see org.greenstone.gatherer.Configuration … … 476 476 * @see org.greenstone.gatherer.util.Utility 477 477 */ 478 479 480 481 478 public String getCollectionEtc() { 479 return Utility.getEtcDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator); 480 } 481 /** Constructs the absolute filename of the collection file, which should resemble "$GSDLHOME/collect/<col_name>/<col_name>.col" 482 482 * @return A <strong>String</strong> containing the filename. 483 483 * @see org.greenstone.gatherer.Configuration … … 486 486 * @see org.greenstone.gatherer.util.Utility 487 487 */ 488 489 490 491 488 public String getCollectionFilename() { 489 return Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator + collection.getName() + ".col"; 490 } 491 /** Constructs the absolute filename of the collection import directory, which should resemble "$GSDLHOME/collect/<col_name>/gimport/" 492 492 * @return A <strong>String</strong> containing the filename. 493 493 * @see org.greenstone.gatherer.Configuration … … 496 496 * @see org.greenstone.gatherer.util.Utility 497 497 */ 498 499 500 501 498 public String getCollectionImport() { 499 return Utility.getImportDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator); 500 } 501 /** Constructs the absolute filename of the collection index directory, which should resemble "$GSDLHOME/collect/<col_name>/index/" 502 502 * @return A <strong>String</strong> containing the filename. 503 503 * @see org.greenstone.gatherer.Configuration … … 506 506 * @see org.greenstone.gatherer.util.Utility 507 507 */ 508 509 510 511 508 public String getCollectionIndex() { 509 return Utility.getIndexDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator); 510 } 511 /** Constructs the absolute filename of the collection log directory, which should resemble "$GSDLHOME/collect/<col_name>/log/" 512 512 * @return A <strong>String</strong> containing the filename. 513 513 * @see org.greenstone.gatherer.Configuration … … 516 516 * @see org.greenstone.gatherer.util.Utility 517 517 */ 518 519 520 521 518 public String getCollectionLog() { 519 return Utility.getLogDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator); 520 } 521 /** Constructs the absolute filename of the collection metadata directory, which should resemble "$GSDLHOME/collect/<col_name>/metadata/" 522 522 * @return A <strong>String</strong> containing the filename. 523 523 * @see org.greenstone.gatherer.Configuration … … 526 526 * @see org.greenstone.gatherer.util.Utility 527 527 */ 528 529 530 531 532 533 534 535 536 528 public String getCollectionMetadata() { 529 return Utility.getMetadataDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator); 530 } 531 532 public String getCollectionOldImport() { 533 return Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator + Utility.OLD_IMPORT_DIR; 534 } 535 536 /** This method either returns the title of the current collection, or a placeholder string of 'No Collection'. 537 537 * @return A <strong>String</strong> which represents what we wish to display for a collection title. 538 538 * @see org.greenstone.gatherer.collection.Collection 539 539 */ 540 541 542 543 544 545 546 547 548 549 540 public String getCollectionTitle() { 541 if(collection != null) { 542 return collection.getTitle(); 543 } 544 return get("Collection.No_Collection"); 545 } 546 547 /** Retrieve the record set (tree model) associated with the current collection. */ 548 public TreeModel getRecordSet() { 549 if(collection_model == null && collection != null) { 550 550 // Check if the gimport directory exists, and if so use it. 551 552 553 554 555 556 557 558 559 560 561 551 File gimport_directory = new File(getCollectionImport()); 552 if(gimport_directory.exists()) { 553 // Generate a new FileSystemModel based on the collection gimport directory. 554 collection_model = new FileSystemModel(new FileNode(gimport_directory, false)); 555 } 556 else { 557 ///ystem.err.println("No gimport directory exists."); 558 // Otherwise default to the import directory. If it doesn't exist, there aint much more I can do. 559 // Generate a new FileSystemModel based on the collection import directory. 560 collection_model = new FileSystemModel(new FileNode(new File(getCollectionOldImport()), false)); 561 } 562 562 // Ensure that the manager is a change listener for the tree. 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 563 if(fm_tree_model_listener == null) { 564 fm_tree_model_listener = new FMTreeModelListener(); 565 } 566 collection_model.addTreeModelListener(fm_tree_model_listener); 567 } 568 return collection_model; 569 } 570 /** Create and return the model behind the workspace tree. Quite an extensive method, as it must first map known greenstone collections, then the local file system and finally any public or private download workspaces. */ 571 public TreeModel getWorkspace() { 572 if(workspace_model != null) { 573 return workspace_model; 574 } 575 // Create the workspace tree. 576 FileNode workspace_root = new FileNode("ABS_ROOT"); 577 workspace_model = new FileSystemModel(workspace_root); 578 // Create and add Greenstone collections node. 579 // Starting at the collection directory of gsdl... 580 File start = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path)); 581 FileNode world_root = new FileNode(get("Tree.World")); 582 workspace_root.insert(world_root); 583 // For each of the children directories, which are collections... 584 File cols[] = start.listFiles(); 585 ArrayTools.sort(cols); 586 // We add their import and gimport directories, but only if its not our current collection. 587 for(int i = 0; cols != null && i < cols.length; i++) { 588 if(collection == null || !(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName()).equals(cols[i].getAbsolutePath())) { 589 File dirs[] = cols[i].listFiles(); 590 ArrayTools.sort(dirs); 591 File import_dir = new File(cols[i], "gimport"); 592 if(!import_dir.exists()) { 593 import_dir = new File(cols[i], "import"); 594 } 595 if(import_dir.exists()) { 596 FileNode collection_root = new FileNode(import_dir, cols[i].getName(), true); 597 world_root.insert(collection_root); 598 collection_root = null; 599 } 600 import_dir = null; 601 } 602 } 603 // Create Local File space. 604 // Get all the available roots mounted on the system. 605 File roots[] = File.listRoots(); 606 // If there is just one root use it as the tree root (linux) 607 if(roots != null) { 608 FileNode file_root; 609 String name = get("Tree.Root"); 610 if(roots.length == 1) { 611 file_root = new FileNode(roots[0], name); 612 workspace_root.insert(file_root); 613 } 614 614 // Otherwise build a dummy node which has these nodes as 615 615 // children. 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 616 else { 617 file_root = new FileNode(name); 618 workspace_root.insert(file_root); 619 // Hopefully this does an alphabetic sort. 620 ArrayTools.sort(roots); 621 for(int i = 0; i < roots.length; i++) { 622 FileNode child_root = new FileNode(roots[i]); 623 file_root.insert(child_root); 624 child_root = null; 625 } 626 } 627 name = null; 628 file_root = null; 629 } 630 // If mirroring is enabled show the public and private caches. 631 if(Gatherer.config.get("workflow.mirror", false)) { 632 632 // Add Public workspace 633 634 633 FileNode public_root = new FileNode(new File(Utility.CACHE_DIR), get("Tree.Public")); 634 workspace_root.insert(public_root); 635 635 // Add Private workspace if a collection has been loaded. 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 636 if(ready()) { 637 FileNode private_root = new FileNode(new File(getCollectionCache()), get("Tree.Private")); 638 workspace_root.insert(private_root); 639 } 640 } 641 // Finally we retrieve and map any predefined special directories. 642 if(ready()) { 643 HashMap mappings = collection.getDirectoryMappings(); 644 for(Iterator names = mappings.keySet().iterator(); names.hasNext(); ) { 645 String name = (String) names.next(); 646 File file = (File) mappings.get(name); 647 FileNode special_root = new FileNode(file, name); 648 //workspace_root.insert(special_root); 649 SynchronizedTreeModelTools.insertNodeInto(workspace_model, workspace_root, special_root); 650 } 651 } 652 return workspace_model; 653 } 654 /** This method when called, creates a new GShell in order to run the import.pl script. 655 655 * @see org.greenstone.gatherer.Configuration 656 656 * @see org.greenstone.gatherer.Gatherer … … 662 662 * @see org.greenstone.gatherer.util.Utility 663 663 */ 664 665 664 public void importCollection() { 665 if(!saved()) { 666 666 // Force save. 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 667 try { 668 SaveCollectionTask save_task = new SaveCollectionTask(collection); 669 save_task.setImportAfter(true); 670 save_task.start(); 671 } 672 catch(Exception error) { 673 Gatherer.printStackTrace(error); 674 } 675 } 676 else { 677 importing = true; 678 String args[]; 679 if(Utility.isWindows()) { 680 args = new String[6]; 681 args[0] = Gatherer.config.perl_path; 682 args[1] = "-S"; 683 args[2] = Gatherer.config.getScriptPath() + "import.pl"; 684 args[3] = "-importdir"; 685 args[4] = getCollectionImport(); 686 args[5] = collection.getName(); 687 } 688 else { 689 args = new String[4]; 690 args[0] = Gatherer.config.getScriptPath() + "import.pl"; 691 args[1] = "-importdir"; 692 args[2] = getCollectionImport(); 693 args[3] = collection.getName(); 694 } 695 args = ArrayTools.add(args, collection.build_options.getImportValues()); 696 GShell shell = new GShell(args, GShell.IMPORT, Message.BUILDING, this, import_monitor, GShell.GSHELL_IMPORT); 697 shell.addGShellListener(Gatherer.g_man.create_pane); 698 shell.start(); 699 } 700 } 701 /** Attempts to load the given collection. Currently uses simple serialization of the collection class. 702 702 * @param location The path to the collection as a <strong>String</strong>. 703 703 * @see org.greenstone.gatherer.Configuration … … 709 709 * @see org.greenstone.gatherer.util.Utility 710 710 */ 711 712 713 714 715 716 717 718 711 public boolean loadCollection(String location) { 712 ///ystem.err.println("Load Collection '" + location + "'"); 713 String[] args2 = new String[1]; 714 args2[0] = location; 715 boolean result = false; 716 // Check we have actually been given a .col file. 717 if(location.endsWith(".col")) { 718 File collection_file = new File(location); 719 719 // Ensure that the directory exists. 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 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 720 File collection_directory = collection_file.getParentFile(); 721 if(collection_directory.exists()) { 722 String name = collection_directory.getName(); 723 File lock_file = new File(collection_file.getParentFile(), LOCK_FILE); 724 // Now determine if a lock already exists on this collection. 725 int choice = LockFileDialog.YES_OPTION; 726 if(lock_file.exists()) { 727 LockFileDialog dialog = new LockFileDialog(Gatherer.g_man, name, lock_file); 728 choice = dialog.getChoice(); 729 } 730 if(choice == LockFileDialog.YES_OPTION) { 731 try { 732 if(lock_file.exists()) { 733 lock_file.delete(); 734 } 735 // Create a lock file. 736 createLockFile(lock_file); 737 // Open the collection file 738 collection = new Collection(collection_file); 739 collection.msm = new MetadataSetManager(); 740 msm = collection.msm; // Legacy 741 collection.msm.load(); 742 collection.cdm = new CollectionDesignManager(); 743 collection.gdm = new GDMManager(); 744 // Tell everyone that it worked. 745 Gatherer.println(get("Loading_Successful", name)); 746 // Now we need to hook up classes that depend on messages from the metadata set manager to keep their content fresh. 747 collection.msm.addMSMListener(this); 748 // We're done. Let everyone know. 749 if(Gatherer.g_man != null) { 750 workspace_model = null; 751 Gatherer.g_man.collectionChanged(ready()); 752 } 753 result = true; 754 } catch (Exception error) { 755 // There is obviously no existing collection present. 756 Gatherer.printStackTrace(error); 757 JOptionPane.showMessageDialog(Gatherer.g_man, get("Cannot_Open", args2), get("General.Error"), JOptionPane.ERROR_MESSAGE); 758 } 759 } 760 lock_file = null; 761 } 762 else { 763 JOptionPane.showMessageDialog(Gatherer.g_man, get("CollectionManager.File_Not_Found", args2), get("General.Error"), JOptionPane.ERROR_MESSAGE); 764 } 765 collection_directory = null; 766 } 767 else { 768 JOptionPane.showMessageDialog(Gatherer.g_man, get("Not_Col_File", args2), get("General.Error"), JOptionPane.ERROR_MESSAGE); 769 Gatherer.println("Not a Gatherer Collection."); 770 } 771 args2 = null; 772 return result; 773 } 774 775 public void makeCollection(String description, String email, String name, String title) { 776 // Run the mkcol command. 777 String command[]; 778 if(Utility.isWindows()) { 779 if(description == null || email == null || title == null) { 780 command = new String[4]; 781 } 782 else { 783 command = new String[10]; 784 } 785 command[0] = Gatherer.config.perl_path; 786 command[1] = "-S"; 787 command[2] = Gatherer.config.getScriptPath() + "mkcol.pl"; 788 if(description == null || email == null || title == null) { 789 command[3] = name; 790 } 791 else { 792 command[3] = "-title"; 793 command[4] = title; 794 command[5] = "-creator"; 795 command[6] = email; 796 command[7] = "-about"; 797 command[8] = description; 798 command[9] = name; 799 } 800 } 801 else { 802 if(description == null || email == null || title == null) { 803 command = new String[2]; 804 command[0] = "mkcol.pl"; 805 command[1] = name; 806 } 807 else { 808 command = new String[8]; 809 command[0] = "mkcol.pl"; 810 command[1] = "-title"; 811 command[2] = title; 812 command[3] = "-creator"; 813 command[4] = email; 814 command[5] = "-about"; 815 command[6] = description; 816 command[7] = name; 817 } 818 } 819 GShell process = new GShell(command, GShell.NEW, Message.COLLECT, this, null, GShell.GSHELL_NEW); 820 process.addGShellListener(this); 821 process.run(); // Don't bother threading this... yet 822 } 823 824 /** Any implementation of GShellListener must include this method to allow the GShell to send messages to listeners. However in this case the CollectionManager is in no way interested in what the messages are, just the import events which have a specific type and are handled elsewhere. Thus we can safely ignore this event. 825 825 * @param event A <strong>GShellEvent</strong> which contains a the message. 826 826 */ 827 828 829 827 public synchronized void message(GShellEvent event) { 828 } 829 /** Called whenever the metadata value changes in some way, such as the addition of a new value. We want to mark the collection so that it needs saving again. 830 830 * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired. 831 831 * @see org.greenstone.gatherer.collection.Collection 832 832 */ 833 834 835 836 837 833 public void metadataChanged(MSMEvent event) { 834 // Again this change means we need to save the collection again. 835 collection.setSaved(false); 836 } 837 /** This call is fired whenever a process within a GShell created by this class begins. 838 838 * @param event A <strong>GShellEvent</strong> containing information about the GShell process. 839 839 * @see org.greenstone.gatherer.Gatherer … … 841 841 * @see org.greenstone.gatherer.shell.GShell 842 842 */ 843 844 845 846 847 848 843 public synchronized void processBegun(GShellEvent event) { 844 ///ystem.err.println("ProcessBegun " + event.getType()); 845 // If this is one of the types where we wish to lock user control 846 Gatherer.g_man.lockCollection((event.getType() == GShell.IMPORT), true); 847 } 848 /** This call is fired whenever a process within a GShell created by this class ends. 849 849 * @param event A <strong>GShellEvent</strong> containing information about the GShell process. 850 850 * @see org.greenstone.gatherer.Gatherer … … 852 852 * @see org.greenstone.gatherer.shell.GShell 853 853 */ 854 855 856 857 858 859 854 public synchronized void processComplete(GShellEvent event) { 855 ///ystem.err.println("ProcessComplete " + event.getType()); 856 Gatherer.g_man.lockCollection((event.getType() == GShell.IMPORT), false); 857 ///ystem.err.println("Recieved process complete event - " + event); 858 // If we were running an import, now run a build. 859 if(event.getType() == GShell.IMPORT && event.getStatus() != GShell.ERROR) { 860 860 // Finish import. 861 862 863 864 865 861 collection.setImported(true); 862 buildCollection(); 863 } 864 // If we were running a build, now is when we move files across. 865 else if(event.getType() == GShell.BUILD && event.getStatus() != GShell.ERROR) { 866 866 ///ystem.err.println("Installing collection."); 867 868 867 installCollection(); 868 collection.setBuilt(true); 869 869 // If we have a local library running (that we know about) then we ask it to add our newly create collection 870 870 ///ystem.err.println("Check if we should reset local server."); 871 872 873 874 871 if(Gatherer.config.exec_file != null) { 872 ///ystem.err.println("Local Library Found!"); 873 Gatherer.g_man.preview_pane.configServer(GSDLSiteConfig.ADD_COMMAND + collection.getName()); 874 } 875 875 //else { 876 876 ///ystem.err.println("GLI can't recognize a local library."); 877 877 //} 878 878 // Signal collection changed. 879 880 881 882 883 884 885 886 887 879 workspace_model = null; 880 Gatherer.g_man.collectionChanged(ready()); 881 JOptionPane.showMessageDialog(Gatherer.g_man, get("Preview_Ready"), get("Preview_Ready_Title"), JOptionPane.INFORMATION_MESSAGE); 882 } 883 else if(event.getType() == GShell.BUILD && event.getStatus() == GShell.ERROR) { 884 JOptionPane.showMessageDialog(Gatherer.g_man, get("Preview_Ready_Failed"), get("Preview_Ready_Title"), JOptionPane.ERROR_MESSAGE); 885 } 886 } 887 /** Determine if the manager is ready for actions apon its collection. 888 888 * @return A <i>boolean</i> which is <i>true</i> to indicate a collection has been loaded and thus the collection is ready for editing, <i>false</i> otherwise. 889 889 */ 890 891 892 893 894 895 896 897 * @see org.greenstone.gatherer.collection.Collection 898 */ 899 900 901 890 public boolean ready() { 891 if(collection != null) { 892 return true; 893 } 894 return false; 895 } 896 /** Called to refresh the models upon which the trees are based. 897 * @see org.greenstone.gatherer.collection.Collection 898 */ 899 public void refreshTrees() { 900 } 901 /** This method associates the collection build monitor with the build monitor created in CreatePane. 902 902 * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the build monitor. 903 903 */ 904 905 906 907 904 public void registerBuildMonitor(GShellProgressMonitor monitor) { 905 build_monitor = monitor; 906 } 907 /** This method associates the collection copy monitor with the copy monitor created in CreatePane. 908 908 * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the copy monitor. 909 909 */ 910 911 912 913 910 public void registerCopyMonitor(GShellProgressMonitor monitor) { 911 copy_monitor = monitor; 912 } 913 /** This method associates the collection import monitor with the import monitor created in CreatePane. 914 914 * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the import monitor. 915 915 */ 916 917 918 919 916 public void registerImportMonitor(GShellProgressMonitor monitor) { 917 import_monitor = monitor; 918 } 919 /** Remove a previously assigned special directory mapping. 920 920 * @param name The symbolic name of the special directory mapping to remove as a <strong>String</strong>. 921 921 * @return The <strong>File</strong> of the mapping removed. 922 922 */ 923 924 925 923 public File removeDirectoryMapping(FileNode target) { 924 File file = null; 925 if(ready()) { 926 926 // Remove from collection, remembering file 927 927 file = collection.removeDirectoryMapping(target.toString()); 928 928 // Update tree. 929 930 931 932 933 934 929 FileSystemModel model = (FileSystemModel) Gatherer.g_man.collection_pane.getWorkspaceTree().getModel(); 930 SynchronizedTreeModelTools.removeNodeFromParent(model, target); 931 } 932 return file; 933 } 934 /** Used to check whether all open collections have a 'saved' state. 935 935 * @return A <i>boolean</i> which is <i>true</i> if the collection has been saved. 936 936 * @see org.greenstone.gatherer.collection.Collection 937 937 */ 938 939 940 941 942 943 944 945 938 public boolean saved() { 939 boolean result = true; 940 if(collection != null) { 941 result = collection.getSaved(); 942 } 943 return result; 944 } 945 /** Saves a collection by serializing it to file. 946 946 * @param close_after <i>true</i> to cause the Gatherer to close the collection once save is complete, <i>false</i> otherwise. 947 947 * @param exit_after <i>true</i> to cause the Gatherer to exit once save is complete, <i>false</i> otherwise. … … 952 952 * @see org.greenstone.gatherer.collection.Collection 953 953 */ 954 955 956 957 958 959 960 961 962 963 954 public void saveCollection(boolean close_after, boolean exit_after) { 955 try { 956 SaveCollectionTask save_task = new SaveCollectionTask(collection, close_after, exit_after); 957 save_task.start(); 958 } 959 catch(Exception error) { 960 Gatherer.printStackTrace(error); 961 } 962 } 963 /** Saves the current collection to a new filename, then restores the original collection. Finally opens the collection copy. 964 964 * @param name The name collection name. 965 965 */ 966 967 968 969 970 971 972 973 974 975 976 977 966 public void saveCollectionAs(String name) { 967 // We need to do this in a separate thread so create a SaveCollectionAsTask 968 try { 969 SaveCollectionTask save_task = new SaveCollectionTask(collection, name); 970 save_task.start(); 971 } 972 catch(Exception error) { 973 Gatherer.printStackTrace(error); 974 } 975 } 976 977 /** Method that is called whenever the metadata set collection changes in some way, such as the addition of a new set or the merging of two sets. We want to mark the collection so that it needs saving again. 978 978 * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired. 979 979 * @see org.greenstone.gatherer.collection.Collection 980 980 */ 981 982 983 984 985 986 987 988 989 990 981 public void setChanged(MSMEvent event) { 982 // Invalidate saved 983 collection.setSaved(false); 984 } 985 986 /** Updates the given workspace tree model to reference the private cache of the currently loaded collection. */ 987 public void updatePrivateWorkspace(DefaultTreeModel model) { 988 // Add Private workspace if a collection has been loaded. 989 if(ready() && !Gatherer.config.get("workflow.mirror", true)) { 990 FileNode root = (FileNode)model.getRoot(); 991 991 // Remove old private workspace 992 993 992 FileNode old = (FileNode)model.getChild(root, 2); 993 model.removeNodeFromParent(old); 994 994 // Create and insert new. 995 996 997 998 999 995 FileNode private_workspace = new FileNode(new File(getCollectionCache()), get("Tree.Private")); 996 model.insertNodeInto(private_workspace, root, 2); 997 } 998 } 999 /** Called whenever the value tree of an metadata element changes in some way, such as the addition of a new value. We want to mark the collection so that it needs saving again. 1000 1000 * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired. 1001 1001 * @see org.greenstone.gatherer.collection.Collection 1002 1002 */ 1003 1004 1005 1006 1003 public void valueChanged(MSMEvent event) { 1004 collection.setSaved(false); 1005 } 1006 /** Used to retrive a value from the dictionary based on the key. 1007 1007 * @param key A <strong>String</strong> indicating what value to retrieve. 1008 1008 * @return A <strong>String</strong> representing the value. 1009 1009 */ 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1010 private String get(String key) { 1011 return get(key, (String[])null); 1012 } 1013 1014 /** Used to retrive a value from the dictionary based on the key. */ 1015 private String get(String key, String arg) { 1016 String[] args = new String[1]; 1017 args[0] = arg; 1018 return get(key, args); 1019 } 1020 1021 /** Used to retrive a value from the dictionary based on the key, and an array of arguments. 1022 1022 * @param key A <strong>String</strong> indicating what value to retrieve. 1023 1023 * @param args A <strong>String[]</strong> of arguments to be inserted into the phrase. 1024 1024 * @return A <strong>String</strong> representing the value. 1025 1025 */ 1026 1027 1028 1029 1030 1031 1032 1033 * @see org.greenstone.gatherer.Gatherer 1034 * @see org.greenstone.gatherer.util.Utility 1035 */ 1036 1037 1026 private String get(String key, String args[]) { 1027 if(key.indexOf('.') == -1) { 1028 key = "CollectionManager." + key; 1029 } 1030 return Gatherer.dictionary.get(key, args); 1031 } 1032 /** Install collection by moving its files from building to index after a successful build. 1033 * @see org.greenstone.gatherer.Gatherer 1034 * @see org.greenstone.gatherer.util.Utility 1035 */ 1036 private void installCollection() { 1037 Gatherer.println("Build complete. Moving files."); 1038 1038 1039 1039 try { 1040 1040 // We have to ensure that the local library 1041 1042 1043 1044 1041 if(Gatherer.config.exec_file != null) { 1042 ///ystem.err.println("Local Library Found!"); 1043 Gatherer.g_man.preview_pane.configServer(GSDLSiteConfig.RELEASE_COMMAND + collection.getName()); 1044 } 1045 1045 1046 1047 1048 1046 File index_dir = new File(getCollectionIndex(), "temp.txt"); 1047 index_dir = index_dir.getParentFile(); 1048 Gatherer.println("Index = " + index_dir.getAbsolutePath()); 1049 1049 1050 1051 1052 1053 1054 1055 1056 1050 if(index_dir.exists()) { 1051 Utility.delete(index_dir); 1052 } 1053 1054 if(index_dir.exists()) { 1055 throw(new Exception("Index directory cannot be removed.")); 1056 } 1057 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1058 File build_dir = new File(getCollectionBuild(), "temp.txt"); 1059 build_dir = build_dir.getParentFile(); 1060 Gatherer.println("Build = " + build_dir.getAbsolutePath()); 1061 build_dir.renameTo(index_dir); 1062 1063 File new_build = new File(getCollectionBuild(), "temp.txt"); 1064 new_build = new_build.getParentFile(); 1065 1066 if(new_build.exists()) { 1067 throw(new Exception("Build directory cannot be moved.")); 1068 } 1069 1070 new_build.mkdir(); 1071 } 1072 catch (Exception exception) { 1073 JOptionPane.showMessageDialog(Gatherer.g_man, "Exception detected during collection install.\nMost likely caused by Windows or Local Library holding locks on files:\n" + exception.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); 1074 } 1075 } 1076 /** Creates and dispatches a message given the initial details. 1077 1077 * @param level An <i>int</i> indicating the message level for this message. 1078 1078 * @param message A <strong>String</strong> which contains the payload of this message. … … 1080 1080 * @see org.greenstone.gatherer.Message 1081 1081 */ 1082 private void message(int level, String message) { 1083 Message msg = new Message(Message.COLLECT, level, message); 1084 if(Gatherer.g_man != null) { 1085 Gatherer.log.add(msg); 1086 } else { 1087 Gatherer.println(msg.toString()); 1088 } 1089 } 1090 1091 private boolean searchArchivesForMetadata(File archive_directory) { 1092 /** @todo - ensure GreenstoneArchiveParser works as expected. */ 1093 return true; 1094 } 1095 1096 private boolean searchForMetadata(File current_file) { 1097 boolean cancelled = false; 1098 if(current_file.isFile() && current_file.getName().equals(Utility.METADATA_XML)) { 1099 cancelled = collection.msm.searchForMetadata(null, new FileNode(current_file), false, true); // A dummy run only. 1100 } 1101 else { 1102 File[] children_files = current_file.listFiles(); 1103 for(int i = 0; !cancelled && children_files != null && i < children_files.length; i++) { 1104 cancelled = searchForMetadata(children_files[i]); 1082 private void message(int level, String message) { 1083 Message msg = new Message(Message.COLLECT, level, message); 1084 if(Gatherer.g_man != null) { 1085 Gatherer.log.add(msg); 1086 } else { 1087 Gatherer.println(msg.toString()); 1088 } 1089 } 1090 1091 private boolean searchArchivesForMetadata(File archive_directory) { 1092 /** @todo - ensure GreenstoneArchiveParser works as expected. */ 1093 return true; 1094 } 1095 1096 private boolean searchForMetadata(File current_file) { 1097 boolean cancelled = false; 1098 if(current_file.isFile() && current_file.getName().equals(Utility.METADATA_XML)) { 1099 cancelled = collection.msm.searchForMetadata(null, new FileNode(current_file), false, true); // A dummy run only. 1100 } 1101 else { 1102 File[] children_files = current_file.listFiles(); 1103 for(int i = 0; !cancelled && children_files != null && i < children_files.length; i++) { 1104 cancelled = searchForMetadata(children_files[i]); 1105 } 1106 } 1107 return cancelled; 1108 } 1109 1110 private void updateCollectionCFG(File base_cfg, File new_cfg, String description, String email, String title) { 1111 boolean first_name = true; 1112 boolean first_extra = true; 1113 String collection_path = (base_cfg.getParentFile().getParentFile()).getAbsolutePath(); 1114 1115 HashMap mappings = collection.msm.profiler.getActions(collection_path); 1116 1117 // 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. 1118 try { 1119 BufferedReader in = new BufferedReader(new FileReader(base_cfg)); 1120 BufferedWriter out = new BufferedWriter(new FileWriter(new_cfg, false)); // Overwrite whats there. 1121 String command = null; 1122 while((command = in.readLine()) != null) { 1123 // We have to test the end of command for the special character '\'. If found, remove it and append the next line, then repeat. 1124 while(command.trim().endsWith("\\")) { 1125 command = command.substring(0, command.lastIndexOf("\\")); 1126 String next_line = in.readLine(); 1127 if(next_line != null) { 1128 command = command + next_line; 1129 } 1130 } 1131 ///ystem.err.println("Read: " + command); 1132 // Now we've finished parsing a line, determine what to do with it. 1133 String command_lc = command.toLowerCase(); 1134 // We replace the creator string with our own. 1135 if(command_lc.startsWith(Utility.CFG_CREATOR)) { 1136 write(out, Utility.CFG_CREATOR + " " + email); 1137 } 1138 else if(command_lc.startsWith(Utility.CFG_MAINTAINER)) { 1139 write(out, Utility.CFG_MAINTAINER + " " + email); 1140 } 1141 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONNAME)) { 1142 if(first_name) { 1143 write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONNAME + " \"" + title + "\""); 1144 first_name = false; 1145 } 1146 } 1147 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA)) { 1148 if(first_extra) { 1149 write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA + " \"" + description + "\""); 1150 first_extra = false; 1151 } 1152 } 1153 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_ICONCOLLECTION)) { 1154 write(out, Utility.CFG_COLLECTIONMETA_ICONCOLLECTION + " \"\""); 1155 } 1156 1157 // 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. 1158 else if(special_case == SPECIAL_DLS && command_lc.equals("classify hierarchy -hfile azlist.txt -metadata azlist -sort title -buttonname title -hlist_at_top")) { 1159 write(out, "classify AZList -metadata dls.Title -buttonname Title"); 1160 } 1161 else if(command_lc.startsWith(Utility.CFG_CLASSIFY)) { 1162 StringTokenizer tokenizer = new StringTokenizer(command); 1163 StringBuffer text = new StringBuffer(tokenizer.nextToken()); 1164 // Read in the classifier command watching for hfile, metadata and sort arguments. 1165 String buttonname = null; 1166 String hfile = null; 1167 String new_metadata = null; 1168 String old_metadata = null; 1169 while(tokenizer.hasMoreTokens()) { 1170 String token = tokenizer.nextToken(); 1171 if(token.equals(Utility.CFG_CLASSIFY_HFILE)) { 1172 if(tokenizer.hasMoreTokens()) { 1173 text.append(" "); 1174 text.append(token); 1175 token = tokenizer.nextToken(); 1176 hfile = token; 1177 } 1178 } 1179 else if(token.equals(Utility.CFG_CLASSIFY_METADATA)) { 1180 if(tokenizer.hasMoreTokens()) { 1181 text.append(" "); 1182 text.append(token); 1183 String temp_metadata = tokenizer.nextToken(); 1184 String replacement = (String) mappings.get(temp_metadata); 1185 if(replacement != null) { 1186 token = replacement; 1187 old_metadata = temp_metadata; 1188 new_metadata = replacement; 1105 1189 } 1106 } 1107 return cancelled; 1108 } 1109 1110 private void updateCollectionCFG(File base_cfg, File new_cfg, String description, String email, String title) { 1111 boolean first_name = true; 1112 boolean first_extra = true; 1113 String collection_path = (base_cfg.getParentFile().getParentFile()).getAbsolutePath(); 1114 1115 HashMap mappings = collection.msm.profiler.getActions(collection_path); 1116 1117 // 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. 1118 try { 1119 BufferedReader in = new BufferedReader(new FileReader(base_cfg)); 1120 BufferedWriter out = new BufferedWriter(new FileWriter(new_cfg, false)); // Overwrite whats there. 1121 String command = null; 1122 while((command = in.readLine()) != null) { 1123 // We have to test the end of command for the special character '\'. If found, remove it and append the next line, then repeat. 1124 while(command.trim().endsWith("\\")) { 1125 command = command.substring(0, command.lastIndexOf("\\")); 1126 String next_line = in.readLine(); 1127 if(next_line != null) { 1128 command = command + next_line; 1129 } 1130 } 1131 ///ystem.err.println("Read: " + command); 1132 // Now we've finished parsing a line, determine what to do with it. 1133 String command_lc = command.toLowerCase(); 1134 // We replace the creator string with our own. 1135 if(command_lc.startsWith(Utility.CFG_CREATOR)) { 1136 write(out, Utility.CFG_CREATOR + " " + email); 1137 } 1138 else if(command_lc.startsWith(Utility.CFG_MAINTAINER)) { 1139 write(out, Utility.CFG_MAINTAINER + " " + email); 1140 } 1141 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONNAME)) { 1142 if(first_name) { 1143 write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONNAME + " \"" + title + "\""); 1144 first_name = false; 1145 } 1146 } 1147 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA)) { 1148 if(first_extra) { 1149 write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA + " \"" + description + "\""); 1150 first_extra = false; 1151 } 1152 } 1153 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_ICONCOLLECTION)) { 1154 write(out, Utility.CFG_COLLECTIONMETA_ICONCOLLECTION + " \"\""); 1155 } 1156 1157 // 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. 1158 else if(special_case == SPECIAL_DLS && command_lc.equals("classify hierarchy -hfile azlist.txt -metadata azlist -sort title -buttonname title -hlist_at_top")) { 1159 write(out, "classify AZList -metadata dls.Title -buttonname Title"); 1160 } 1161 else if(command_lc.startsWith(Utility.CFG_CLASSIFY)) { 1162 StringTokenizer tokenizer = new StringTokenizer(command); 1163 StringBuffer text = new StringBuffer(tokenizer.nextToken()); 1164 // Read in the classifier command watching for hfile, metadata and sort arguments. 1165 String buttonname = null; 1166 String hfile = null; 1167 String new_metadata = null; 1168 String old_metadata = null; 1169 while(tokenizer.hasMoreTokens()) { 1170 String token = tokenizer.nextToken(); 1171 if(token.equals(Utility.CFG_CLASSIFY_HFILE)) { 1172 if(tokenizer.hasMoreTokens()) { 1173 text.append(" "); 1174 text.append(token); 1175 token = tokenizer.nextToken(); 1176 hfile = token; 1177 } 1178 } 1179 else if(token.equals(Utility.CFG_CLASSIFY_METADATA)) { 1180 if(tokenizer.hasMoreTokens()) { 1181 text.append(" "); 1182 text.append(token); 1183 String temp_metadata = tokenizer.nextToken(); 1184 String replacement = (String) mappings.get(temp_metadata); 1185 if(replacement != null) { 1186 token = replacement; 1187 old_metadata = temp_metadata; 1188 new_metadata = replacement; 1189 } 1190 else { 1191 token = temp_metadata; 1192 } 1193 temp_metadata = null; 1194 replacement = null; 1195 } 1196 } 1197 else if(token.equals(Utility.CFG_CLASSIFY_SORT)) { 1198 if(tokenizer.hasMoreTokens()) { 1199 text.append(" "); 1200 text.append(token); 1201 String temp_metadata = tokenizer.nextToken(); 1202 String replacement = (String) mappings.get(temp_metadata); 1203 if(replacement != null) { 1204 token = replacement; 1205 } 1206 else { 1207 token = temp_metadata; 1208 } 1209 temp_metadata = null; 1210 replacement = null; 1211 } 1212 } 1213 else if(token.equals(Utility.CFG_CLASSIFY_BUTTONNAME)) { 1214 buttonname = token; 1215 } 1216 text.append(' '); 1217 text.append(token); 1218 token = null; 1219 } 1220 tokenizer = null; 1221 1222 // If we replaced the metadata argument and didn't encounter a buttonname, then add one now pointing back to the old metadata name in order to accomodate macro files which required such names (buttonname is metadata name by default)! 1223 if(old_metadata != null && new_metadata != null && buttonname == null) { 1224 text.append(' '); 1225 text.append(Utility.CFG_CLASSIFY_BUTTONNAME); 1226 text.append(' '); 1227 text.append(old_metadata); 1228 } 1229 command = text.toString(); 1230 // Replace the hfile if we found it 1231 if(hfile != null && new_metadata != null) { 1232 command = command.replaceAll(hfile, new_metadata + ".txt"); 1233 } 1234 buttonname = null; 1235 hfile = null; 1236 new_metadata = null; 1237 old_metadata = null; 1238 write(out, command); 1239 } 1240 else { 1241 // There is still one special case, that of the format command. In such a command we have to search for [<target>] to ensure we don't change parts of the format which have nothing to do with the metadata elements. 1242 boolean format_command = command_lc.startsWith(Utility.CFG_FORMAT); 1243 // Replace mapping strings 1244 if(mappings != null) { 1245 for(Iterator keys = mappings.keySet().iterator(); keys.hasNext(); ) { 1246 String target = (String) keys.next(); 1247 String replacement = (String) mappings.get(target); 1248 if(format_command) { 1249 target = "\\[" + target + "\\]"; 1250 replacement = "{Or}{[" + replacement + "]," + target + "}"; 1251 } 1252 command = command.replaceAll(target, replacement); 1253 } 1254 } 1255 write(out, command); 1256 } 1190 else { 1191 token = temp_metadata; 1257 1192 } 1258 in.close(); 1259 in = null; 1260 out.flush(); 1261 out.close(); 1262 out = null; 1263 } 1264 catch(Exception error) { 1265 Gatherer.printStackTrace(error); 1266 } 1267 // All done, I hope. 1268 } 1269 1270 private void write(BufferedWriter out, String message) 1271 throws Exception { 1272 ///ystem.err.println("Writing: " + message); 1273 out.write(message, 0, message.length()); 1274 out.newLine(); 1275 } 1276 1277 /** The CollectionManager class is getting too confusing by half so I'll implement this TreeModelListener in a private class to make responsibility clear. */ 1278 private class FMTreeModelListener 1279 implements TreeModelListener { 1280 /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false. 1193 temp_metadata = null; 1194 replacement = null; 1195 } 1196 } 1197 else if(token.equals(Utility.CFG_CLASSIFY_SORT)) { 1198 if(tokenizer.hasMoreTokens()) { 1199 text.append(" "); 1200 text.append(token); 1201 String temp_metadata = tokenizer.nextToken(); 1202 String replacement = (String) mappings.get(temp_metadata); 1203 if(replacement != null) { 1204 token = replacement; 1205 } 1206 else { 1207 token = temp_metadata; 1208 } 1209 temp_metadata = null; 1210 replacement = null; 1211 } 1212 } 1213 else if(token.equals(Utility.CFG_CLASSIFY_BUTTONNAME)) { 1214 buttonname = token; 1215 } 1216 text.append(' '); 1217 text.append(token); 1218 token = null; 1219 } 1220 tokenizer = null; 1221 1222 // If we replaced the metadata argument and didn't encounter a buttonname, then add one now pointing back to the old metadata name in order to accomodate macro files which required such names (buttonname is metadata name by default)! 1223 if(old_metadata != null && new_metadata != null && buttonname == null) { 1224 text.append(' '); 1225 text.append(Utility.CFG_CLASSIFY_BUTTONNAME); 1226 text.append(' '); 1227 text.append(old_metadata); 1228 } 1229 command = text.toString(); 1230 // Replace the hfile if we found it 1231 if(hfile != null && new_metadata != null) { 1232 command = command.replaceAll(hfile, new_metadata + ".txt"); 1233 } 1234 buttonname = null; 1235 hfile = null; 1236 new_metadata = null; 1237 old_metadata = null; 1238 write(out, command); 1239 } 1240 else { 1241 // There is still one special case, that of the format command. In such a command we have to search for [<target>] to ensure we don't change parts of the format which have nothing to do with the metadata elements. 1242 boolean format_command = command_lc.startsWith(Utility.CFG_FORMAT); 1243 // Replace mapping strings 1244 if(mappings != null) { 1245 for(Iterator keys = mappings.keySet().iterator(); keys.hasNext(); ) { 1246 String target = (String) keys.next(); 1247 String replacement = (String) mappings.get(target); 1248 if(format_command) { 1249 target = "\\[" + target + "\\]"; 1250 replacement = "{Or}{[" + replacement + "]," + target + "}"; 1251 } 1252 command = command.replaceAll(target, replacement); 1253 } 1254 } 1255 write(out, command); 1256 } 1257 } 1258 in.close(); 1259 in = null; 1260 out.flush(); 1261 out.close(); 1262 out = null; 1263 } 1264 catch(Exception error) { 1265 Gatherer.printStackTrace(error); 1266 } 1267 // All done, I hope. 1268 } 1269 1270 private void write(BufferedWriter out, String message) 1271 throws Exception { 1272 ///ystem.err.println("Writing: " + message); 1273 out.write(message, 0, message.length()); 1274 out.newLine(); 1275 } 1276 1277 /** The CollectionManager class is getting too confusing by half so I'll implement this TreeModelListener in a private class to make responsibility clear. */ 1278 private class FMTreeModelListener 1279 implements TreeModelListener { 1280 /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false. 1281 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree. 1282 */ 1283 public void treeNodesChanged(TreeModelEvent event) { 1284 if(collection != null) { 1285 collection.setSaved(false); 1286 } 1287 } 1288 /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false. 1281 1289 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree. 1282 1290 */ 1283 public void treeNodesChanged(TreeModelEvent event) {1284 1285 1286 1287 1288 1291 public void treeNodesInserted(TreeModelEvent event) { 1292 if(collection != null) { 1293 collection.setSaved(false); 1294 } 1295 } 1296 /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false. 1289 1297 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree. 1290 1298 */ 1291 public void treeNodesInserted(TreeModelEvent event) {1292 1293 1294 1295 1296 1299 public void treeNodesRemoved(TreeModelEvent event) { 1300 if(collection != null) { 1301 collection.setSaved(false); 1302 } 1303 } 1304 /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false. 1297 1305 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree. 1298 1306 */ 1299 public void treeNodesRemoved(TreeModelEvent event) { 1300 if(collection != null) { 1301 collection.setSaved(false); 1302 } 1303 } 1304 /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false. 1305 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree. 1306 */ 1307 public void treeStructureChanged(TreeModelEvent event) { 1308 if(collection != null) { 1309 collection.setSaved(false); 1310 } 1311 } 1312 } 1307 public void treeStructureChanged(TreeModelEvent event) { 1308 if(collection != null) { 1309 collection.setSaved(false); 1310 } 1311 } 1312 } 1313 1313 } -
trunk/gli/src/org/greenstone/gatherer/collection/DeleteCollectionPrompt.java
r4293 r4366 50 50 */ 51 51 public class DeleteCollectionPrompt 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 52 extends JDialog { 53 /** The currently selected collection for deletion. */ 54 private Collection collection = null; 55 /** The model behind the list. */ 56 private DefaultListModel list_model = null; 57 /** A reference to ourself so any inner-classes get dispose of us. */ 58 private DeleteCollectionPrompt prompt = null; 59 /** The close button, which exits the prompt without deleting anything. */ 60 private JButton close_button = null; 61 /** The ok button which causes the selected collection to be deleted. */ 62 private JButton ok_button = null; 63 /** The confirmation check box. */ 64 private JCheckBox confirmation = null; 65 /** The label above details. */ 66 private JLabel details_label = null; 67 /** The label above the list. */ 68 private JLabel list_label = null; 69 /** The list of available collections. */ 70 private JList list = null; 71 /** The text area used to display details about the collection selected. */ 72 private JTextArea details = null; 73 /** A string array used to pass arguments to the phrase retrieval method. */ 74 private String args[] = null; 75 /** The size of the delete prompt screen. */ 76 public static final Dimension SIZE = new Dimension(500, 500); 77 /** Constructor. 78 * @see org.greenstone.gatherer.collection.DeleteCollectionPrompt.CloseButtonListener 79 * @see org.greenstone.gatherer.collection.DeleteCollectionPrompt.CollectionListListener 80 * @see org.greenstone.gatherer.collection.DeleteCollectionPrompt.ConfirmationCheckBoxListener 81 * @see org.greenstone.gatherer.collection.DeleteCollectionPrompt.OKButtonListener 82 */ 83 public DeleteCollectionPrompt() { 84 super(); 85 this.close_button = new JButton(get("General.Close", null)); 86 this.confirmation = new JCheckBox(get("Confirm_Delete", null)); 87 this.details = new JTextArea(); 88 this.details_label = new JLabel(get("Collection_Details", null)); 89 this.list = new JList(); 90 this.list_label = new JLabel(get("Collection_List", null)); 91 this.list_model = new DefaultListModel(); 92 this.ok_button = new JButton(get("General.OK", null)); 93 this.prompt = this; 94 this.setModal(true); 95 this.setSize(SIZE); 96 this.setTitle(get("Title", null)); 97 close_button.addActionListener(new CloseButtonListener()); 98 confirmation.addActionListener(new ConfirmationCheckBoxListener()); 99 confirmation.setEnabled(false); 100 confirmation.setSelected(false); 101 details.setFont(Gatherer.config.getFont("general.tooltip_font", false)); 102 details.setText(get("No_Collection", null)); 103 list.addListSelectionListener(new CollectionListListener()); 104 list.clearSelection(); 105 list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 106 list.setModel(list_model); 107 ok_button.addActionListener(new OKButtonListener()); 108 ok_button.setEnabled(false); 109 scanForCollections(); 110 } 111 /** Destructor. */ 112 public void destroy() { 113 close_button = null; 114 confirmation = null; 115 details = null; 116 details_label = null; 117 list_model.clear(); 118 list_model = null; 119 list = null; 120 ok_button = null; 121 prompt = null; 122 } 123 /** This method causes the modal prompt to be displayed. */ 124 public void display() { 125 // Central pane 126 JPanel list_pane = new JPanel(new BorderLayout()); 127 list_pane.add(list_label, BorderLayout.NORTH); 128 list_pane.add(new JScrollPane(list), BorderLayout.CENTER); 129 list_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); 130 131 JPanel details_pane = new JPanel(new BorderLayout()); 132 details_pane.add(details_label, BorderLayout.NORTH); 133 details_pane.add(new JScrollPane(details), BorderLayout.CENTER); 134 details_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); 135 136 JPanel central_pane = new JPanel(new GridLayout(2, 1)); 137 central_pane.add(list_pane); 138 central_pane.add(details_pane); 139 central_pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 140 141 // Lower pane 142 JPanel confirmation_pane = new JPanel(new BorderLayout()); 143 confirmation_pane.add(confirmation, BorderLayout.CENTER); 144 confirmation_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); 145 146 JPanel button_pane = new JPanel(new GridLayout(1, 2)); 147 button_pane.add(ok_button); 148 button_pane.add(close_button); 149 button_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); 150 151 JPanel lower_pane = new JPanel(new BorderLayout()); 152 lower_pane.add(confirmation_pane, BorderLayout.NORTH); 153 lower_pane.add(button_pane, BorderLayout.SOUTH); 154 lower_pane.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5)); 155 156 // Final. 157 JPanel content_pane = (JPanel)this.getContentPane(); 158 content_pane.setLayout(new BorderLayout()); 159 content_pane.add(central_pane, BorderLayout.CENTER); 160 content_pane.add(lower_pane, BorderLayout.SOUTH); 161 162 // Center and display. 163 Dimension screen_size = Gatherer.config.screen_size; 164 this.setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2); 165 this.show(); 166 } 167 /** Shows a delete complete prompt. 168 168 * @param success A <strong>boolean</strong> indicating if the collection was successfully deleted. 169 169 * @see org.greenstone.gatherer.collection.Collection 170 170 */ 171 172 173 174 175 176 177 178 179 180 181 171 public void resultPrompt(boolean success) { 172 args = new String[1]; 173 args[0] = collection.getName(); 174 if(success) { 175 JOptionPane.showMessageDialog(prompt,get("Successful_Delete", args),get("Successful_Title", null),JOptionPane.INFORMATION_MESSAGE); 176 } 177 else { 178 JOptionPane.showMessageDialog(prompt,get("Failed_Delete", args),get("Failed_Title", null),JOptionPane.WARNING_MESSAGE); 179 } 180 } 181 /** Retrieves a phrase from the <strong>Dictionary</strong> in <strong>Gatherer</strong>. 182 182 * @param key A <strong>String</strong> used to match against a specific phrase in the dictionary. 183 183 * @see org.greenstone.gatherer.Dictionary 184 184 * @see org.greenstone.gatherer.Gatherer 185 185 */ 186 187 188 189 190 191 192 186 private String get(String key, String args[]) { 187 if(key.indexOf(".") == -1) { 188 key = "DeleteCollectionPrompt." + key; 189 } 190 return Gatherer.dictionary.get(key, args); 191 } 192 /** Attempts to load the given collection. Currently uses simple 193 193 * serialization of the collection class. 194 194 * @param location The path to the serialized collection. 195 195 */ 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 196 public Collection loadCollection(File file) { 197 Collection col = null; 198 try { 199 FileInputStream fis = new FileInputStream(file); 200 BufferedInputStream bin = new BufferedInputStream(fis); 201 ObjectInputStream input = new ObjectInputStream(bin); 202 col = (Collection) input.readObject(); 203 input.close(); 204 input = null; 205 bin.close(); 206 bin = null; 207 fis.close(); 208 fis = null; 209 } 210 catch (Exception error) { 211 error.printStackTrace(); 212 } 213 return col; 214 } 215 /** Method to scan the collect directory retrieving and reloading each collection it finds, while building the list of known collections. 216 216 * @see org.greenstone.gatherer.Configuration 217 217 * @see org.greenstone.gatherer.Gatherer … … 219 219 * @see org.greenstone.gatherer.util.Utility 220 220 */ 221 222 223 224 225 221 private void scanForCollections() { 222 // Start at the collect dir. 223 String collect_directory_name = Utility.getCollectionDir(Gatherer.config.gsdl_path); 224 File collect_directory = new File(collect_directory_name); 225 if(collect_directory.exists()) { 226 226 // Now for each child directory see if it contains a .col file and 227 227 // if so try to load it.. 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 228 File collections[] = collect_directory.listFiles(); 229 ArrayTools.sort(collections); 230 for(int i = 0; collections != null && i < collections.length; i++) { 231 File children[] = collections[i].listFiles(); 232 for(int j = 0; children != null && j < children.length; j++) { 233 if(children[j].getAbsolutePath().endsWith(".col")) { 234 Collection col = loadCollection(children[j]); 235 // If we've actually loaded 236 if(col != null) { 237 list_model.addElement(col); 238 } 239 } 240 } 241 } 242 } 243 // Otherwise the collect directory doesn't actually exist, so there ain't much we can do. 244 } 245 /** A button listener implementation, which listens for actions on the close button and disposes of the dialog when detected. */ 246 private class CloseButtonListener 247 implements ActionListener { 248 /** Any implementation of ActionListener must include this method so we can be informed when the button is actioned. 249 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself. 250 250 */ 251 252 253 254 255 256 */ 257 258 259 260 251 public void actionPerformed(ActionEvent event) { 252 prompt.dispose(); 253 } 254 } 255 /** This private class listens for selection events in from the list and then displays the appropriate details for that collection. 256 */ 257 private class CollectionListListener 258 implements ListSelectionListener { 259 /** Any implementation of ListSelectionListener must include this method so we can be informed when the list selection changes. 260 * @param event A <strong>ListSelectionEvent</strong> containing all the relevant information garnered from the event itself. 261 261 */ 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 262 public void valueChanged(ListSelectionEvent event) { 263 if(!list.isSelectionEmpty()) { 264 confirmation.setEnabled(true); 265 collection = (Collection) list.getSelectedValue(); 266 args = new String[4]; 267 args[0] = collection.getTitle(); 268 args[1] = collection.getName(); 269 args[2] = collection.getEmail(); 270 args[3] = collection.getDescription(); 271 details.setText(get("Details", args)); 272 } 273 else { 274 confirmation.setEnabled(false); 275 details.setText(get("No_Collection", null)); 276 } 277 } 278 } 279 /** A check box listener so we can tell if the users selected confirm. */ 280 private class ConfirmationCheckBoxListener 281 implements ActionListener { 282 /** Any implementation of ActionListener must include this method so we can be informed when the button is actioned. 283 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself. 284 284 */ 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 285 public void actionPerformed(ActionEvent event) { 286 if(confirmation.isSelected()) { 287 ok_button.setEnabled(true); 288 } 289 else { 290 ok_button.setEnabled(false); 291 } 292 } 293 } 294 /** The OK button listener implementation. */ 295 private class OKButtonListener 296 implements ActionListener { 297 /** Any implementation of ActionListener must include this method so we can be informed when the button is actioned. 298 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself. 299 * @see org.greenstone.gatherer.Configuration 300 * @see org.greenstone.gatherer.Gatherer 301 * @see org.greenstone.gatherer.util.Utility 302 */ 303 public void actionPerformed(ActionEvent event) { 304 304 // Delete the selected collection. 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 305 File delete_me = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator); 306 if(Utility.delete(delete_me)) { 307 resultPrompt(true); 308 list_model.removeElement(collection); 309 details.setText(get("No_Collection", null)); 310 confirmation.setEnabled(false); 311 confirmation.setSelected(false); 312 ok_button.setEnabled(false); 313 collection = null; 314 } 315 else { 316 resultPrompt(false); 317 } 318 } 319 } 320 320 } 321 321 -
trunk/gli/src/org/greenstone/gatherer/collection/Job.java
r4293 r4366 50 50 */ 51 51 public class Job 52 52 implements ActionListener { 53 53 54 54 private boolean clobber; 55 55 private boolean debug; 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 56 private boolean higher_directories; 57 private boolean no_parents; 58 private boolean other_hosts; 59 private boolean page_requisites; 60 private boolean quiet; 61 62 private GProgressBar progress; 63 64 private GURL initial = null; 65 private GURL url = null; 66 67 private TreeModel model; 68 69 private int depth; 70 private int previous_state; 71 private int state; 72 73 private String current_url; 74 private String destination; 75 private String proxy_pass; 76 private String proxy_user; 77 78 private Vector encountered_urls; 79 private Vector failed_urls; 80 81 private WGet mummy; 82 83 public static int COMPLETE = 0; 84 public static int PAUSED = 1; 85 85 public static int RUNNING = 2; 86 86 public static int STOPPED = 3; 87 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 88 /** 89 */ 90 public Job(TreeModel model, boolean clobber, boolean debug, boolean no_parents, boolean other_hosts, boolean page_requisites, boolean quiet, GURL initial, int depth, String destination, String proxy_pass, String proxy_user, WGet mummy, boolean simple) { 91 this.model = model; 92 93 this.debug = debug; 94 this.clobber = clobber; 95 this.no_parents = no_parents; 96 this.other_hosts = other_hosts; 97 this.page_requisites = page_requisites; 98 this.quiet = quiet; 99 this.initial = initial; 100 this.depth = depth; 101 this.destination = destination; 102 this.proxy_pass = proxy_pass; 103 this.proxy_user = proxy_user; 104 this.mummy = mummy; 105 106 progress = new GProgressBar(this, initial.toString(), simple); 107 108 encountered_urls = new Vector(); 109 failed_urls = new Vector(); 110 111 previous_state = STOPPED; 112 state = STOPPED; 113 } 114 115 /** Depending on which button on the progress bar was pushed, 116 * this method will affect the state of the Job and perhaps make 117 * calls to wget.class if necessary. 118 * @param event The ActionEvent fired from within the GProgressBar 119 * which we must respond to. 120 */ 121 public void actionPerformed(ActionEvent event) { 122 // The action button is used to alternately start or stop the 123 // job. If the current state of the job is paused then this 124 // restart is logically equivelent to a resume. 125 if(event.getSource() == progress.action) { 126 previous_state = state; 127 if(state == RUNNING) { 128 state = PAUSED; 129 } 130 else { 131 state = RUNNING; 132 mummy.resumeThread(); 133 } 134 } 135 else if (event.getSource() == progress.cancel) { 136 state = STOPPED; // Should already be stopped. 137 mummy.deleteJob(this); 138 } 139 } 140 141 /** Called by the WGet native code to inform us of a new download starting. 142 * @param url The url that is being downloaded, as a String. 143 */ 144 public void addDownload(String raw_url) { 145 if(!encountered_urls.contains(raw_url)) { 146 encountered_urls.add(raw_url); 147 } 148 // Regardless create a new GURL 149 current_url = raw_url; 150 url = new GURL(raw_url); 151 progress.addDownload(raw_url); 152 } 153 154 /** Used to advise the Job of a newly parsed link. Its up to Job 155 * to decide if it already knows about this url, and if not to 156 * update its progress bar. 157 * @param url The url in question as a String. 158 * @param type Whether the link is an internal or external link. 159 * @return A boolean indicating if the url was added. 160 */ 161 public boolean addLink(String raw_url, int type) { 162 ///ystem.out.println("addLink("+url+", "+type+")"); 163 if(!encountered_urls.contains(raw_url)) { 164 164 // Add it to the urls we've seen. 165 165 encountered_urls.add(raw_url); 166 166 // Add it the to links for the current GURL. 167 167 168 168 // Add it to the progress file count. 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 169 progress.increaseFileCount(); 170 return true; 171 } 172 // Regardless add it to the children links of the current GURL 173 initial.addLink(raw_url); 174 175 // We've seen it before. Don't count it again. 176 return false; 177 } 178 179 public void callWGet() { 180 // Build parameter string 181 String command = "wget "; 182 183 // Parse arguments into array. 184 // Always: 185 // rewrite links to be local if possible - NOOOOOO, 186 // output a debug file and debug messages, 187 // run quietly. 188 //command = command + "-k "; 189 190 if(destination != null) { 191 command = command + "-P " + destination + " "; 192 } 193 194 if(depth < 0) { 195 195 // Infinite recursion 196 197 198 196 command = command + "-r "; 197 } 198 else if (depth == 0) { 199 199 // Just this page. 200 201 200 } 201 else if (depth > 0) { 202 202 // Recursion to the specified depth. 203 204 205 206 207 208 209 210 211 212 213 203 command = command + "-r -l" + depth + " "; 204 } 205 206 if(!clobber || previous_state == Job.PAUSED) { 207 command = command + "-nc -c "; 208 } 209 210 if(proxy_user != null) { 211 command = command + "--proxy-user=" + proxy_user 212 + " --proxy-passwd=" + proxy_pass + " "; 213 } 214 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 215 if(page_requisites) { 216 command = command + "-p "; 217 } 218 219 if(other_hosts) { 220 command = command + "-H "; 221 } 222 223 // Finally tell it the site to download. 224 command = command + initial.toString(); 225 226 if(previous_state == Job.COMPLETE) { 227 progress.mirrorBegun(true); 228 } 229 else { 230 progress.mirrorBegun(false); 231 } 232 233 // Run it 234 try { 235 Gatherer.println("Cmd: " + command); 236 Runtime rt = Runtime.getRuntime(); 237 Process prcs = rt.exec(command); 238 InputStreamReader isr = 239 new InputStreamReader( prcs.getErrorStream() ); 240 BufferedReader br = new BufferedReader( isr ); 241 241 // Capture the standard error stream and seach for two particular 242 242 // occurances. 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 243 String line; 244 boolean ignore_for_robots = false; 245 while ((line = br.readLine()) != null) { 246 Gatherer.println(line); 247 248 // The first magic special test is to see if we've just 249 // asked for the robots.txt file. If so we ignore 250 // the next add and then the next complete/error. 251 if(line.lastIndexOf("robots.txt;") != -1) { 252 Gatherer.println("***** Requesting robot.txt"); 253 ignore_for_robots = true; 254 } 255 // If line contains "=> `" display text as the 256 // currently downloading url. Unique to add download. 257 else if(line.lastIndexOf("=> `") != -1) { 258 if(!ignore_for_robots) { 259 // Add download 260 String new_url = 261 line.substring(line.indexOf("`") + 1, 262 line.lastIndexOf("'")); 263 // Remove the destination guff 264 if(destination != null) { 265 new_url = new_url.substring(destination.length()); 266 } 267 addDownload("http:/" + new_url); 268 } 269 } 270 // If line contains "saved [<size>]" set currently 271 // downloading url to "Download Complete". 272 else if(line.lastIndexOf(") - `") != -1) { 273 if(!ignore_for_robots) { 274 // Download complete 275 downloadComplete(); 276 } 277 else { 278 ignore_for_robots = false; 279 } 280 } 281 // The already there line begins "File `..." However this 282 // is only true in english, so instead I looked and there 283 // are few (if any at all) other messages than those above 284 // and not overwriting messages that use " `" so we'll 285 // look for that. Note this method is not guarenteed to be 286 // unique like the previous two. 287 else if(line.lastIndexOf(" `") != -1) { 288 // Not Overwriting 289 Gatherer.println("Already there."); 290 String new_url = 291 line.substring(line.indexOf("`") + 1, 292 line.lastIndexOf("'")); 293 // Remove the destination guff 294 if(destination != null) { 295 new_url = new_url.substring(destination.length()); 296 } 297 addDownload("http:/" + new_url); 298 downloadWarning(); 299 } 300 // Any other important message starts with the time in the form hh:mm:ss 301 else if(line.length() > 7) { 302 if(line.charAt(2) == ':' && line.charAt(5) == ':') { 303 if(!ignore_for_robots) { 304 Gatherer.println("Error."); 305 downloadFailed(); 306 } 307 else { 308 ignore_for_robots = false; 309 } 310 } 311 } 312 } 313 313 // Now display final message based on exit value 314 315 314 prcs.waitFor(); 315 } catch (Exception ioe) { 316 316 //message(Utility.ERROR, ioe.toString()); 317 318 319 320 321 322 323 324 325 326 } 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 317 Gatherer.printStackTrace(ioe); 318 } 319 // If we've got to here and the state isn't STOPPED then the 320 // job is complete. 321 if(state == Job.RUNNING) { 322 progress.mirrorComplete(); 323 previous_state = state; 324 state = Job.COMPLETE; 325 } 326 } 327 328 /** The most important part of the Job class, this method is 329 * responsible for calling the WGet native methods used to 330 * mirror the indicated url. By this stage all the variables 331 * necessary should be set and we need only build up the 332 * parameter string and make the call. 333 */ 334 public void callWGetNative() { 335 Vector args = new Vector(); 336 337 // Let the GProgressBar know we're starting, just in case 338 // the user hasn't told us to. If this is the second time the 339 // urls downloaded and the first attempt was successful (ie 340 // the previous job was complete), then we have the case where 341 // the user is forcing us to remirror. Reset all the values etc 342 // if this is the case then reset the variables. 343 // Note that this can cause the result line to look something 344 // like this. 345 // Downloaded 12 of 12 files (8 warnings, 0 errors). 346 // The warnings would be something like, 'File already downloaded' 347 // but the total number of files and the file successfully 348 // downloaded will be correct. 349 if(previous_state == Job.COMPLETE) { 350 progress.mirrorBegun(true); 351 } 352 else { 353 progress.mirrorBegun(false); 354 } 355 356 // Parse arguments into array. 357 args.add(Utility.BASE_DIR + "wget"); 358 //args.add("-k"); 359 args.add("-d"); 360 args.add("-o"); 361 args.add("debug.txt"); 362 362 363 364 365 366 367 368 363 if(destination != null) { 364 args.add("-P"); 365 args.add(destination); 366 } 367 368 if(depth < 0) { 369 369 // Infinite recursion 370 371 372 370 args.add("-r"); 371 } 372 else if (depth == 0) { 373 373 // Just this page. 374 375 374 } 375 else if (depth > 0) { 376 376 // Recursion to the specified depth. 377 378 379 380 381 382 383 384 385 386 387 388 389 390 377 args.add("-r"); 378 args.add("-l"); 379 args.add("" + depth + ""); // Hacky 380 } 381 382 if(!clobber || previous_state == PAUSED) { 383 args.add("-nc"); 384 args.add("-c"); 385 } 386 387 if(proxy_user != null) { 388 args.add("--proxy-user=" + proxy_user); 389 args.add("--proxy-passwd=" + proxy_pass); 390 } 391 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 392 if(page_requisites) { 393 args.add("-p"); 394 } 395 396 if(quiet) { 397 args.add("-q"); 398 } 399 400 if(other_hosts) { 401 args.add("-H"); 402 } 403 404 args.add(initial.toString()); 405 406 Gatherer.println("Calling wget "); 407 for(Enumeration e = args.elements(); e.hasMoreElements();) { 408 Gatherer.println(e.nextElement() + " "); 409 } 410 Gatherer.println(""); 411 412 // Run home to mummy. 413 int value = mummy.wget(args.size(), args.toArray(), debug); 414 415 // If we've got to here and the state isn't STOPPED then the job is complete. 416 if(state == RUNNING) { 417 progress.mirrorComplete(); 418 previous_state = state; 419 state = COMPLETE; 420 } 421 } 422 423 /** Called by the WGet native code when the current download is 424 * completed. In turn all download listeners are informed. 425 */ 426 public void downloadComplete() { 427 progress.downloadComplete(); 428 /* @todo 429 model.add(url.getURL(), destination); 430 */ 431 url = null; 432 current_url = null; 433 } 434 434 435 436 437 438 439 440 441 442 435 /** Called by the WGet native code when the requested download returns 436 * a status code other than 200. 437 */ 438 public void downloadFailed() { 439 ///ystem.out.println("downloadFailed("+current_url+")"); 440 failed_urls.add(current_url); // Its the current url thats failed. 441 progress.downloadFailed(); 442 } 443 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 /**466 467 468 public GProgressBar getProgressBar() {469 470 }471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 444 /** 445 */ 446 public void downloadWarning() { 447 progress.downloadWarning(); 448 } 449 450 /** 451 * @return A String representing the currently downloading url. 452 */ 453 public String getCurrent() { 454 return current_url; 455 } 456 457 /** 458 * @return A String representing the initial urls host (root node 459 * of tree that we are mirroring). 460 */ 461 public String getHost() { 462 return url.getHost(); 463 } 464 465 /** 466 * @return Returns the progress bar associated with this job. 467 */ 468 public GProgressBar getProgressBar() { 469 return progress; 470 } 471 472 /** Called to discover if the user wanted this thread to run or if 473 * it is paused. 474 * @return An int representing the current Job state. 475 */ 476 public int getState() { 477 return state; 478 } 479 480 /** Returns the current state of the stop flag for this job. 481 * @return A boolean representing whether the user has requested to 482 * stop. 483 */ 484 public boolean hasSignalledStop() { 485 if(state == Job.STOPPED || state == Job.PAUSED || 486 state == Job.COMPLETE) { 487 return true; 488 } 489 return false; 490 } 491 492 /** A convinence call. 493 * @return A String representing the url of the initial url (root node of the mirrored tree). 494 */ 495 public String toString() { 496 return initial.toString(); 497 } 498 499 /** Called by the WGet native code to signal the current progress of 500 * downloading. 501 * @param current A long representing the number of bytes that have 502 * been downloaded since the last update. 503 * @param expected A long representing the total number of bytes 504 * expected for this download. 505 */ 506 public void updateProgress(long current, long expected) { 507 progress.updateProgress(current, expected); 508 } 509 509 } 510 510 -
trunk/gli/src/org/greenstone/gatherer/collection/LoadCollectionBox.java
r4293 r4366 49 49 public class LoadCollectionBox { 50 50 51 52 53 51 private JFileChooser chooser = null; 52 public LoadCollectionBox() { 53 } 54 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 55 public String getFileName() { 56 String defaultPath = Utility.getCollectionDir(Gatherer.config.gsdl_path); 57 chooser = new JFileChooser(new File(defaultPath)); 58 chooser.setDialogTitle(Gatherer.dictionary.get("SaveCollectionBox.Title")); 59 ExtensionFileFilter filter1 = new ExtensionFileFilter(".col", Gatherer.dictionary.get("General.File_Description")); 60 chooser.setFileFilter(filter1); 61 chooser.setAcceptAllFileFilterUsed(false); 62 int return_val = chooser.showOpenDialog(null); 63 if(return_val == JFileChooser.APPROVE_OPTION) { 64 return chooser.getSelectedFile().getAbsolutePath(); 65 } 66 else { 67 return null; 68 } 69 } 70 70 } -
trunk/gli/src/org/greenstone/gatherer/collection/SaveCollectionBox.java
r4293 r4366 42 42 /** Provides a prompt allowing the user some choice in whether a collection saves. */ 43 43 public class SaveCollectionBox 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 44 extends JDialog 45 implements ActionListener{ 46 /** What option the user has choosen. */ 47 private int result = 0; 48 /** Button to cancel prompt, no save. */ 49 private JButton cancel = null; 50 /** Button for no save. */ 51 private JButton no = null; 52 /** Button to save. */ 53 private JButton yes = null; 54 /** A reference to ourselves so our inner classes can dispose of us. */ 55 private SaveCollectionBox myself = null; 56 /** Result value if the user has choosen cancel. */ 57 static final public int SAVE_CANCEL = 0; 58 /** Result value if the user has choosen no. */ 59 static final public int SAVE_NO = 1; 60 /** Result value if the user has choosen yes. */ 61 static final public int SAVE_YES = 2; 62 /** Construtor. */ 63 public SaveCollectionBox() { 64 super(Gatherer.g_man); 65 this.myself = this; 66 result = SAVE_CANCEL; 67 // Dialog setup 68 this.setModal(true); 69 this.setTitle(get("Title")); 70 this.setSize(360,100); 71 } 72 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured. In this case we see what button the users clicked, set the appropriate result then dispose of the dialog. */ 73 public void actionPerformed(ActionEvent event) { 74 if(event.getSource() == yes) { 75 result = SAVE_YES; 76 this.dispose(); 77 } else if(event.getSource() == no) { 78 result = SAVE_NO; 79 this.dispose(); 80 } else if(event.getSource() == cancel) { 81 result = SAVE_CANCEL; 82 this.dispose(); 83 } 84 } 85 /** Destructor. */ 86 public void destroy() { 87 cancel = null; 88 no.removeActionListener(this); 89 no = null; 90 yes.removeActionListener(this); 91 yes = null; 92 myself = null; 93 rootPane = null; 94 } 95 /** Displays the prompt by first building the controls, then waits for a user selection. 96 96 * @param name The name of the current collection as a <strong>String</strong>. 97 97 */ 98 99 100 101 98 public int getUserOption(String name) { 99 JPanel content_pane = (JPanel) this.getContentPane(); 100 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 101 content_pane.setLayout(new GridLayout(2,1)); 102 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 103 String args[] = new String[1]; 104 args[0] = name; 105 JLabel save_label = new JLabel(get("Label", args)); 106 content_pane.add(save_label); 107 JPanel button_pane = new JPanel(new GridLayout(1,3)); 108 content_pane.add(button_pane); 109 // We add both mnemonics and key listener so that the 'y' of yes is underlined, but pressing just [Y] (rather than [CTL]-[Y]) performs a systematic click. 110 yes = new JButton(get("General.Yes")); 111 yes.addActionListener(this); 112 KeyListenerImpl key_listener = new KeyListenerImpl(); 113 yes.addKeyListener(key_listener); 114 yes.setMnemonic(KeyEvent.VK_Y); 115 button_pane.add(yes); 116 no = new JButton(get("General.No")); 117 no.addActionListener(this); 118 no.addKeyListener(key_listener); 119 no.setMnemonic(KeyEvent.VK_N); 120 button_pane.add(no); 121 cancel = new JButton(get("General.Cancel")); 122 cancel.addActionListener(this); 123 cancel.addKeyListener(key_listener); 124 cancel.setMnemonic(KeyEvent.VK_C); 125 button_pane.add(cancel); 126 // Center on screen. 127 Dimension dlgSize = getSize(); 128 Dimension frmSize = Gatherer.g_man.getSize(); 129 Point loc = Gatherer.g_man.getLocation(); 130 setLocation((frmSize.width - dlgSize.width) / 2 + loc.x, (frmSize.height - dlgSize.height) / 2 + loc.y); 131 show(); 132 // Deallocate things we allocated here. 133 yes.removeKeyListener(key_listener); 134 no.removeKeyListener(key_listener); 135 cancel.removeKeyListener(key_listener); 136 key_listener = null; 137 content_pane = null; 138 args = null; 139 save_label = null; 140 button_pane = null; 141 dlgSize = null; 142 frmSize = null; 143 loc = null; 144 return result; 145 } 146 /** Method to retrieve a phrase from the dictionary based of a key. 147 147 * @param key A <strong>String</strong> used to find the correct phrase. 148 148 * @return A <strong>String</strong> containing the correct phrase with the correct formatting. 149 149 */ 150 151 152 153 150 private String get(String key) { 151 return get(key, null); 152 } 153 /** Method to retrieve a phrase from the dictionary based of a key and including arguments. 154 154 * @param key A <strong>String</strong> used to find the correct phrase. 155 155 * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase. 156 156 * @return A <strong>String</strong> containing the correct phrase with the correct formatting. 157 157 */ 158 159 160 161 162 163 164 165 166 167 168 158 private String get(String key, String args[]) { 159 if(key.indexOf('.') == -1) { 160 key = "SaveCollectionBox." + key; 161 } 162 return Gatherer.dictionary.get(key, args); 163 } 164 /** Listens for key presses when the focus is on one of the buttons. Note that the key pressed needn't be the one associated with the button in focus. */ 165 private class KeyListenerImpl 166 extends KeyAdapter { 167 /** Any extension of KeyAdapter can override this method so that we can be informed whenever a key is released (ie after a keyTyped event). In this case we map the key press to an appropriate click on one of the buttons (not necessarily the one the key release was detected on). 168 * @param event A <strong>KeyEvent</strong> containing details about the key release event. 169 169 */ 170 171 172 173 174 175 176 177 178 179 180 181 170 public void keyReleased(KeyEvent event) { 171 if(event.getKeyCode() == KeyEvent.VK_Y) { 172 yes.doClick(10); 173 } 174 else if(event.getKeyCode() == KeyEvent.VK_N) { 175 no.doClick(10); 176 } 177 else if(event.getKeyCode() == KeyEvent.VK_C) { 178 cancel.doClick(10); 179 } 180 } 181 } 182 182 } -
trunk/gli/src/org/greenstone/gatherer/collection/SaveCollectionTask.java
r4293 r4366 50 50 */ 51 51 public class SaveCollectionTask 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 52 extends Thread { 53 private boolean close_after = false; 54 /** Should we exit the Gatherer once this save is complete. */ 55 private boolean exit_after = false; 56 /** Do we run the import scripts once this save is complete. */ 57 private boolean import_after = false; 58 /** The current collection. */ 59 private Collection collection = null; 60 /** The filename of the collection we are saving. */ 61 private String name = null; 62 static final private int CLOSE_COLLECTION = 0; 63 static final private int COLLECTION_COPIED = 1; 64 static final private int COLLECTION_SAVED = 2; 65 static final private int COLLECTION_CFG_SAVED = 3; 66 static final private int COPY_COLLECTION = 4; 67 static final private int MAKE_COLLECTION = 5; 68 static final private int METADATA_SAVED = 6; 69 static final private int METADATA_XML_SAVED = 7; 70 static final private int OPEN_COLLECTION = 8; 71 static final private int RESTORE_COLLECTION = 9; 72 /** Constructor. 73 * @param name The filename of the collection we are saving as. 74 */ 75 public SaveCollectionTask(Collection collection) { 76 this.collection = collection; 77 } 78 /** Constructor. 79 * @param exit_after <i>true</i> to cause the Gatherer to exit once save is complete, <i>false</i> otherwise. 80 */ 81 public SaveCollectionTask(Collection collection, boolean close_after, boolean exit_after) { 82 this.close_after = close_after; 83 this.collection = collection; 84 this.exit_after = exit_after; 85 } 86 /** Constructor. 87 * @param name The filename of the collection we are saving as. 88 */ 89 public SaveCollectionTask(Collection collection, String name) { 90 this.collection = collection; 91 this.name = name; 92 } 93 /** <p>This method, when created in a forked process by start(), performs the actions necessary to save a collection. If this is a regular save it saves the state of the current collection, ensuring all files, metadata files, and configuration files are written to disk. If, instead, this is a "Save As" action then there as several more steps involved:</p> 94 * <p>1. Perform a regular collection save on what we will later refer to as the origin collection.</p> 95 * <p>2. Call CollectionManager.makeCollection() to create the collection structure to save into (copied collection).</p> 96 * <p>3. Copy files from the origin to the copied collections (except special collection files ending with ~).</p> 97 * <p>4. Restore origin collection by undoing file copy actions and removing the ~ from the end of collection files.</p> 98 * <p>5. Close the origin collection.</p> 99 * <p>6. Open the copied collection.</p> 100 * <p>Of course all of this takes a while, and depends on several other bits of code to work properly.</p>. 101 * @see org.greenstone.gatherer.collection.Collection 102 * @see org.greenstone.gatherer.collection.CollectionModel 103 * @see org.greenstone.gatherer.gui.GUIManager 104 * @see org.greenstone.gatherer.gui.GConfigPane 105 * @see org.greenstone.gatherer.msm.MetadataSetManager 106 * @see org.greenstone.gatherer.util.Utility 107 */ 108 public void run() { 109 // Change cursor to hourglass. 110 Gatherer.g_man.wait(true); 111 // Create progress monitor box. It will display itself as necessary. 112 ProgressMonitor spd = new ProgressMonitor(Gatherer.g_man, Gatherer.dictionary.get("SaveProgressDialog.Title", collection.getName()), null, 0, 100); 113 spd.setMillisToDecideToPopup(100); 114 spd.setMillisToPopup(100); 115 // 0. Force all remaining metadata.xml files to load. 116 // 1. Perform a regular collection save on what we will later refer to as the origin collection. 117 ///ystem.err.println("1. Save origin."); 118 String tmp_loc = Gatherer.c_man.getCollectionFilename(); 119 String args[] = new String[1]; 120 args[0] = collection.getName() + ".col"; 121 try { 122 122 // Block until all of the metadata files have been read in. 123 123 collection.gdm.waitUntilComplete(); 124 124 // Write out the metadata xml files. The destroy below is meant to do this, but never does. 125 125 collection.gdm.save(); 126 126 127 128 127 spd.setProgress(getValue(METADATA_XML_SAVED)); 128 File file = new File(tmp_loc); 129 129 // Create backup 130 131 132 133 134 135 136 130 if(file.exists()) { 131 File backup = new File(tmp_loc + "~"); 132 backup.deleteOnExit(); 133 if(!file.renameTo(backup)) { 134 Gatherer.println("Error in CollectionManager.load(): FileNotRenamedException"); 135 } 136 } 137 137 // Carry on. 138 139 138 collection.save(); 139 spd.setProgress(getValue(COLLECTION_SAVED)); 140 140 // Write out the collection configuration file. 141 142 141 Gatherer.g_man.config_pane.saveConfiguration(); 142 spd.setProgress(getValue(COLLECTION_CFG_SAVED)); 143 143 // Write out the metadata files. 144 145 144 Gatherer.c_man.msm.save(); 145 spd.setProgress(getValue(METADATA_SAVED)); 146 146 // Clean-up 147 147 spd.setProgress(100); 148 148 ///atherer.g_man.collectionChanged(Gatherer.c_man.ready()); 149 150 151 152 153 154 155 149 collection.setSaved(true); 150 } 151 catch (Exception error) { 152 Gatherer.printStackTrace(error); 153 } 154 // Now we check whether we've finished, or is this a Save As action, in which case we've got miles to go. 155 if(name != null) { 156 156 // 2. Call CollectionManager.makeCollection() to create the collection structure to save into (copied collection). 157 157 ///ystem.err.println("2. Make copy."); 158 159 158 Gatherer.c_man.createCollection(null, null, name, null, null, null); 159 spd.setProgress(getValue(MAKE_COLLECTION)); 160 160 // 3. Copy files from the origin to the copied collections (except special collection files ending with ~). 161 161 // As part of this we must rename origin.col to copy.col 162 162 ///ystem.err.println("3. Copy origin."); 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 163 ArrayList files = new ArrayList(); 164 File collection_file = new File(Gatherer.c_man.getCollectionFilename()); 165 File copied_dir = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path) + name); 166 files.add(collection_file.getParentFile()); 167 while(files.size() > 0) { 168 File file = (File) files.get(0); 169 files.remove(0); 170 if(file.isDirectory()) { 171 File children[] = file.listFiles(); 172 for(int i = 0; i < children.length; i++) { 173 files.add(children[i]); 174 } 175 children = null; 176 } 177 else { 178 // Rename origin.col file. 179 if(file.equals(collection_file)) { 180 File copied_file = new File(copied_dir, name + ".col"); 181 copy(collection_file, copied_file); 182 copied_file = null; 183 } 184 // Exclude *~ files from certain locations and lock.tmp file. 185 else if(!file.getName().endsWith("~") && !file.getName().equals(CollectionManager.LOCK_FILE)) { 186 StringTokenizer origin = new StringTokenizer(file.getAbsolutePath(), File.separator); 187 StringTokenizer destin = new StringTokenizer(copied_dir.getAbsolutePath(), File.separator); 188 while(destin.hasMoreTokens()) { 189 origin.nextToken(); 190 destin.nextToken(); 191 } 192 File copied_file = new File(copied_dir.getAbsolutePath()); 193 while(origin.hasMoreTokens()) { 194 copied_file = new File(copied_file, origin.nextToken()); 195 } 196 copy(file, copied_file); 197 copied_file = null; 198 origin = null; 199 destin = null; 200 } 201 } 202 file = null; 203 } 204 spd.setProgress(getValue(COPY_COLLECTION)); 205 205 // 4. Restore origin collection by undoing file copy actions and removing the ~ from the end of collection files. 206 206 ///ystem.err.println("4. Restore origin."); 207 207 Gatherer.c_man.undo.undoAll(); 208 208 ///ystem.err.println(" - UndoAll complete."); 209 209 // Recurse collection tree restoring *~ 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 210 files.clear(); // Should be empty anyway. 211 files.add(collection_file.getParentFile()); 212 while(files.size() > 0) { 213 File file = (File) files.get(0); 214 files.remove(0); 215 if(file.isDirectory()) { 216 File children[] = file.listFiles(); 217 for(int i = 0; i < children.length; i++) { 218 files.add(children[i]); 219 } 220 children = null; 221 } 222 else if(file.getName().endsWith("~")) { 223 String filename = file.getAbsolutePath(); 224 File original_file = new File(filename.substring(0, filename.length() - 1)); 225 ///ystem.err.println("Renaming " + filename); 226 if(!file.renameTo(original_file)) { 227 Gatherer.println("Error in SaveCollectionTask.run(): FileRenameException"); 228 } 229 } 230 } 231 231 ///ystem.err.println(" - Restore *~ complete."); 232 232 spd.setProgress(getValue(RESTORE_COLLECTION)); 233 233 // 5. Close the origin collection. 234 234 ///ystem.err.println("5. Close origin."); 235 236 237 235 collection.setSaved(true); 236 Gatherer.c_man.closeCollection(); 237 spd.setProgress(getValue(CLOSE_COLLECTION)); 238 238 // 6. Open the copied collection. 239 239 ///ystem.err.println("6. Open copy."); 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 240 Gatherer.c_man.loadCollection(copied_dir.getAbsolutePath() + File.separator + name + ".col"); 241 spd.setProgress(getValue(OPEN_COLLECTION)); 242 copied_dir = null; 243 } 244 spd.close(); 245 spd = null; 246 tmp_loc = null; 247 args = null; 248 // Reset undo queue. 249 if(Gatherer.c_man.ready()) { 250 Gatherer.c_man.undo.clear(); 251 } 252 Gatherer.g_man.wait(false); 253 254 // Now we are finished action any necessary action. 255 if(import_after) { 256 Gatherer.c_man.importCollection(); 257 } 258 if(close_after) { 259 Gatherer.c_man.closeCollection(); 260 } 261 ///ystem.err.println("Save Complete."); 262 if(exit_after) { 263 Gatherer.self.exit(); 264 } 265 } 266 267 public void setImportAfter(boolean state) { 268 import_after = true; 269 } 270 271 private void copy(File source, File destination) { 272 ///ystem.err.println("Copy: " + source.getAbsolutePath()); 273 ///ystem.err.println(" to: " + destination.getAbsolutePath()); 274 try { 275 destination.getParentFile().mkdirs(); 276 FileInputStream f_in = new FileInputStream(source); 277 FileOutputStream f_out = new FileOutputStream(destination); 278 byte data[] = new byte[Utility.BUFFER_SIZE]; 279 int data_size = 0; 280 while((data_size = f_in.read(data, 0, Utility.BUFFER_SIZE)) != -1) { 281 f_out.write(data, 0, data_size); 282 } 283 f_in.close(); 284 f_out.close(); 285 } 286 catch (Exception exception) { 287 Gatherer.printStackTrace(exception); 288 } 289 } 290 291 private int getValue(int reference) { 292 double multiplier; 293 if(name == null) { 294 multiplier = 1.0; 295 } 296 else { 297 multiplier = 0.25; 298 } 299 switch(reference) { 300 // Standard Save 301 case COLLECTION_SAVED: 302 return (int)((double)70 * multiplier); 303 case COLLECTION_CFG_SAVED: 304 case METADATA_SAVED: 305 case METADATA_XML_SAVED: 306 return (int)((double)10 * multiplier); 307 // Save As 308 case MAKE_COLLECTION: 309 return 5; 310 case COPY_COLLECTION: 311 return 30; 312 case RESTORE_COLLECTION: 313 return 30; 314 case CLOSE_COLLECTION: 315 return 10; 316 case OPEN_COLLECTION: 317 return 10; 318 } 319 return 0; 320 } 321 321 } 322 322
Note:
See TracChangeset
for help on using the changeset viewer.