Changeset 23433 for main/trunk/gli
- Timestamp:
- 2010-12-09T22:27:33+13:00 (13 years ago)
- Location:
- main/trunk/gli
- Files:
-
- 1 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/gli/classes/dictionary.properties
r23143 r23433 652 652 General.Warning:Warning 653 653 General.Yes:Yes 654 General.MultipleFileNamesNotSupported.Message:Your locale seems to be in UTF-8. Non-UTF-8 filenames are not supported by your setup. 655 General.MultipleFileNamesNotSupported.Title:Filename Encoding Support 654 656 #**************************** 655 657 # -
main/trunk/gli/metadata/greenstone.mds
r23393 r23433 43 43 <Language code="en"> 44 44 <Attribute name="label">Filename Encoding</Attribute> 45 <Attribute name="definition">TODO</Attribute> 45 <Attribute name="definition">The encoding of the filename. If this is known, it can be manually set here.</Attribute> 46 <Attribute name="comment">If not manually specified, Greenstone will try to guess the encoding of the filename upon building, which may or may not be correct.</Attribute> 46 47 </Language> 47 48 </Element> -
main/trunk/gli/src/org/greenstone/gatherer/Gatherer.java
r23143 r23433 56 56 import org.greenstone.gatherer.gui.WarningDialog; 57 57 import org.greenstone.gatherer.gui.FedoraLogin; 58 import org.greenstone.gatherer.metadata.FilenameEncoding; 58 59 import org.greenstone.gatherer.remote.RemoteGreenstoneServer; 59 60 import org.greenstone.gatherer.util.JarTools; … … 471 472 } 472 473 474 // Check that the local can support multiple filename encodings 475 //System.err.println("#### Java identifies current Locale as (file.encoding): " 476 // + System.getProperty("file.encoding")); 477 if(System.getProperty("file.encoding").equals("UTF-8")){ 478 // If the locale is UTF-8, Java will interpret all filename bytes as UTF-8, 479 // which is a destructive process as it will convert characters not recognised 480 // by UTF-8 into the invalid character, rather than preserving the bytecodes. 481 // This has the effect that non-UTF8 encoded filenames on a system set to a 482 // UTF-8 locale are not 'seen' by Java (if they contain non-ASCII characters). 483 multipleFilenameEncodingsNotSupported(); 484 FilenameEncoding.MULTIPLE_FILENAME_ENCODINGS_SUPPORTED = false; 485 FilenameEncoding.URL_FILE_SEPARATOR = File.separator; 486 } else { 487 FilenameEncoding.MULTIPLE_FILENAME_ENCODINGS_SUPPORTED = true; 488 FilenameEncoding.URL_FILE_SEPARATOR = "/"; // URL file separator is always "/" 489 } 490 473 491 // Set the default font for all Swing components. 474 492 FontUIResource default_font = Configuration.getFont("general.font", true); … … 852 870 + File.separator + "cgi" + File.separator + "gsdl3site.cfg"; 853 871 } else { // cgi-bin/gsdlsite.cfg 854 return Configuration.gsdl_path + File.separator872 return Configuration.gsdl_path /* + File.separator */ 855 873 + "cgi-bin" + File.separator + "gsdlsite.cfg"; 856 874 } … … 1258 1276 } 1259 1277 1278 /** Prints a warning message about the OS not supporting multiple filename encodings. */ 1279 static private void multipleFilenameEncodingsNotSupported() { 1280 WarningDialog dialog = new WarningDialog("warning.NoEncodingSupport", 1281 Dictionary.get("General.MultipleFileNamesNotSupported.Title"), 1282 Dictionary.get("General.MultipleFileNamesNotSupported.Message"), null, false); 1283 dialog.display(); 1284 dialog.dispose(); 1285 dialog = null; 1286 } 1260 1287 1261 1288 /** Sets up the proxy connection by setting JVM Environment flags and creating a new Authenticator. -
main/trunk/gli/src/org/greenstone/gatherer/collection/CollectionManager.java
r23143 r23433 62 62 import org.greenstone.gatherer.gui.WarningDialog; 63 63 import org.greenstone.gatherer.metadata.DocXMLFileManager; 64 import org.greenstone.gatherer.metadata.FilenameEncoding; 64 65 import org.greenstone.gatherer.metadata.MetadataChangedListener; 65 66 import org.greenstone.gatherer.metadata.MetadataSet; … … 1552 1553 if (collection != null) { 1553 1554 collection.setMetadataChanged(true); 1555 1556 // we're only going to refresh the tree's already visible nodes (and reselect them) IFF 1557 // gs.FilenameEncoding meta was set on any files/folders and the filenames of the 1558 // affected CollectionTreeNodes need to be recalculated 1559 if(FilenameEncoding.isRefreshRequired()) { 1560 1561 // refreshes the relevant part of the tree 1562 TreePath[] paths = collection_tree.getSelectionPaths(); 1563 if(paths != null) { 1564 for(int i = 0; i < paths.length; i++) { 1565 collection_tree_model.refresh(paths[i]); 1566 collection_tree.setSelectionPath(paths[i]); 1567 } 1568 } 1569 // refreshed the tree, so turn off the requirement to refresh 1570 FilenameEncoding.setRefreshRequired(false); 1571 } 1554 1572 } 1555 1573 } -
main/trunk/gli/src/org/greenstone/gatherer/collection/CollectionTreeNode.java
r16838 r23433 32 32 import org.greenstone.gatherer.cdm.CollectionDesignManager; 33 33 import org.greenstone.gatherer.file.FileNode; 34 import org.greenstone.gatherer.metadata.FilenameEncoding; 34 35 import org.greenstone.gatherer.util.JarTools; 35 36 import java.util.Set; 36 37 import java.util.Iterator; 37 import java.nio.charset.Charset;38 38 39 39 … … 54 54 { 55 55 super(file); 56 // the super call will additionally call calcDisplayString() which will get any 57 // applicable the filename encoding and apply it to the file's name for display. 56 58 57 59 this.is_explodable = CollectionDesignManager.plugin_manager.isFileExplodable(file); … … 81 83 return is_srcreplaceable; 82 84 } 85 86 /** This method returns a string representation of the filenodes in the 87 * <i>Collection</i> Tree, that can then be displayed in the tree. If the 88 * filename encoding is specified as metadata with the file, then this 89 * method will apply that to the filename's bytes to get the displayName. 90 */ 91 protected String calcDisplayString() { 92 // metadata.xml files in collections don't get displayed anyway 93 if(file.getName().equals("metadata.xml")) { 94 return super.calcDisplayString(); 95 } 96 97 if(!FilenameEncoding.MULTIPLE_FILENAME_ENCODINGS_SUPPORTED) { 98 return super.calcDisplayString(); 99 } 100 101 // Else: try to encode the display string from the 102 // file_to_encoding map. If that fails, just use the locale 103 String displayName = null; 104 String urlEncodedPath = getURLEncodedFilePath(); 105 String encoding = FilenameEncoding.findFilenameEncoding(file, urlEncodedPath, false); 106 107 // if it isn't the same as the current encoding already applied, reapply 108 // it which will set the filenameEncoding again as well 109 if(!encoding.equals(getFilenameEncoding())) { 110 displayName = reencodeDisplayName(encoding); // may return null 111 } 112 113 if(displayName == null) { 114 if(FilenameEncoding.DEBUGGING) { 115 displayName = getURLEncodedFileName(); 116 } else { 117 displayName = super.calcDisplayString(); 118 } 119 } 120 121 return displayName; 122 } 123 124 /** Call this if the filename encoding has changed and needs to be 125 * recalculated and re-applied to the filename. This is only for display, 126 * so it only gets applied to the urlEncodedFileName (not urlEncodedFilePath). 127 * Note that the filenameEncoding may not be the same as the given encoding 128 * at the end of this method (in case it was a charset alias of the encoding). 129 * This method both sets and returns the displayFileName member variable. 130 * @return the reencoded display name, if the encoding was a recognised alias 131 * in which case the filenameEncoding will store the canonical name. */ 132 public String reencodeDisplayName(String encoding) { 133 if(!FilenameEncoding.MULTIPLE_FILENAME_ENCODINGS_SUPPORTED) { 134 return displayFileName; // may still be null 135 } 136 137 filenameEncoding = encoding; // clear previous value 138 139 if(filenameEncoding.equals("")) { 140 displayFileName = super.calcDisplayString(); // *FileNode* calcDisplayString 141 return displayFileName; 142 } 143 144 try{ 145 displayFileName = new String(file.getName().getBytes(), filenameEncoding); 146 } catch(Exception e) { 147 // IllegalCharsetName-, UnsupportedCharset- or UnsupportedEncoding-Exception 148 // Store the unsupported encoding, but display with filesystem (or URL) encoding 149 filenameEncoding = encoding; 150 151 if(FilenameEncoding.DEBUGGING) { 152 displayFileName = getURLEncodedFileName(); 153 } else { 154 displayFileName = super.calcDisplayString(); 155 } 156 } 157 return displayFileName; 158 } 159 160 /** Can call this upon refreshing a FileNode (this CollectionTreeNode). It makes 161 * sure the display names of the visible nodes in the CollectionTree aren't stale */ 162 public void refreshDescendantEncodings() { 163 // now recalculate encodings for all visible children 164 165 // Don't bother with the encoding stuff when multiple filename encodings 166 // are not supported because the system is UTF-8 (not Native-Latin-1) and 167 // Java interprets all filename bytes as UTF-8, which destructively 168 // converts unrecognised characters (for UTF-8) into the invalid character. 169 170 if(!FilenameEncoding.MULTIPLE_FILENAME_ENCODINGS_SUPPORTED 171 || child_nodes == null) 172 { 173 return; 174 } 175 176 // get and apply the filename encoding, if any 177 for(int i = 0; i < child_nodes.size(); i++) { 178 CollectionTreeNode child_node = (CollectionTreeNode) child_nodes.get(i); 179 String urlEncodedPath = child_node.getURLEncodedFilePath(); 180 181 String encoding = FilenameEncoding.findFilenameEncoding( 182 child_node.getFile(), urlEncodedPath, false); 183 184 // if current encoding is different from the existing one, re-apply encoding 185 if(!child_node.getFilenameEncoding().equals(encoding)) { 186 child_node.reencodeDisplayName(encoding); 187 } 188 } 189 } 190 191 // Unused at present 192 /** Call when the filename encoding of this folder level fileNode has changed 193 * and therefore the filename encodings of the descendant fileNodes have to be 194 * reset (their entries in the file_to_encoding hashmap cleared), so that we know 195 * to recalculate these later. Call when deleting, moving or renaming col nodes */ 196 public void resetDescendantEncodings() { 197 if(FilenameEncoding.MULTIPLE_FILENAME_ENCODINGS_SUPPORTED) { 198 resetDescendantEncodings(this.file, this.getURLEncodedFilePath()); 199 200 // for an actual file/folder delete, want to remove all corresponding 201 // entries from the hashtable without recalculating any encodings 202 // (files have been deleted, so no there will be no filenames to display). 203 // So don't do this here: refreshDescendantEncodings(); 204 // It's done near the end of FileNode.map(). 205 } 206 } 207 208 // Together with the above, unused at present 209 private static void resetDescendantEncodings(File f, String urlEncodedPath) 210 { 211 // remove this file f's urlencoded path name from the file_to_encoding Map 212 FilenameEncoding.map.remove(urlEncodedPath); 213 214 if(f.isDirectory()) { 215 File[] children = f.listFiles(); 216 for(int i = 0; i < children.length; i++) { 217 urlEncodedPath = FilenameEncoding.fileToURLEncoding(children[i]); 218 resetDescendantEncodings(children[i], urlEncodedPath); 219 // sets filenameEncoding var 220 } 221 } 222 } 223 83 224 } -
main/trunk/gli/src/org/greenstone/gatherer/file/FileNode.java
r16984 r23433 8 8 import javax.swing.tree.*; 9 9 import org.greenstone.gatherer.DebugStream; 10 import org.greenstone.gatherer.metadata.FilenameEncoding; 10 11 import org.greenstone.gatherer.util.ArrayTools; 11 12 … … 19 20 protected File file = null; 20 21 protected FileSystemModel model = null; 21 protected MutableTreeNode parent = null; 22 protected MutableTreeNode parent = null; 23 24 protected String urlEncodedFileName = ""; 25 protected String urlEncodedFilePath = ""; 26 protected String filenameEncoding = ""; 22 27 /** The string that is displayed as the filename. Attempts to be in the correct encoding. */ 23 28 protected String displayFileName = null; 24 29 25 30 26 31 public FileNode(File file) 27 32 { 28 this.file = file; 29 30 // Files cannot have children 31 if (file != null && !file.isDirectory()) { //file.isFile()) { 32 // Cache this result to prevent unceasing missing disk messages being thrown if the 33 // removable media was, um, removed after directory mapped 34 this.allows_children = false; 35 displayFileName = calcDisplayString(); 36 } 37 } 38 39 40 /** This method returns a string representation of the filenodes in the Collection 41 * Tree, that can then be displayed in the tree. 42 * We'll initially assume that the filenames are utf8 encoded and so convert the 43 * filename into utf8 for proper presentation in the Collection tree pane. 44 * If the filenames are not utf8, then the conversion would have introduced funny 45 * characters. Therefore, when converting to utf8, if the converted filename 46 * contains the special character '\ufffd', then we know the conversion did not work 47 * and we return the original string which may or may not be properly presented by 48 * default. 49 * See http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/CharsetDecoder.html 50 * which says "How a decoding error is handled depends upon the action requested for 51 * that type of error, which is described by an instance of the CodingErrorAction class. 52 * The possible error actions are to ignore the erroneous input, report the error to 53 * the invoker via the returned CoderResult object, or replace the erroneous input with 54 * the current value of the replacement string. The replacement has the initial value 55 * "\uFFFD"; its value may be changed via the replaceWith method." 56 * The following made me think that String(byte[], String charsetName) constructor may 57 * use the replacement value \uFFFD. 58 * http://www.experts-exchange.com/Programming/Programming_Languages/Java/Q_20512969.html 59 * mentions the following which made me think of this: 60 * convertedStr = convertedStr.replace('\ufffd', ' '); 61 */ 62 protected String calcDisplayString() { 63 String filename = file.getName(); 64 try{ 65 String utf8filename = new String(filename.getBytes(), "UTF8"); 66 if(utf8filename.indexOf('\ufffd') == -1) { 67 return utf8filename; 68 } else { // contains the character indicating that it's invalid utf8 69 // return the original string 70 return filename; 71 } 72 } catch(java.io.UnsupportedEncodingException e) { 73 return filename; 74 } 33 this.file = file; 34 35 if (file != null) { 36 // Files cannot have children 37 if(file.isFile()) { 38 // Cache this result to prevent unceasing missing disk messages being thrown if the 39 // removable media was, um, removed after directory mapped 40 this.allows_children = false; 41 } 42 filenameEncoding = ""; 43 urlEncodedFilePath = FilenameEncoding.calcURLEncodedFilePath(file); 44 urlEncodedFileName = FilenameEncoding.calcURLEncodedFileName(urlEncodedFilePath); 45 46 // work out the display string (extra special processing for CollectionTreeNodes) 47 displayFileName = calcDisplayString(); 48 } 49 } 50 51 public String getURLEncodedFileName() { return urlEncodedFileName; } 52 53 public String getURLEncodedFilePath() { return urlEncodedFilePath; } 54 55 public String getFilenameEncoding() { return filenameEncoding; } 56 57 58 /** This method returns a string representation of the filenodes in the tree, 59 * that can then be displayed in the tree. Overridden in subclass CollectionTreeNode. 60 * Turn FilenameEncoding.DEBUGGING on to see URLEncoded filenames. 61 */ 62 protected String calcDisplayString() { 63 if(FilenameEncoding.DEBUGGING) { 64 return getURLEncodedFileName(); 65 } else { 66 return file.getName(); 67 } 75 68 } 76 69 … … 314 307 } 315 308 } 309 310 // in case any filename encodings had gone stale, 311 // (recalculate these and) refresh the display name 312 refreshDescendantEncodings(); 313 316 314 } 317 315 … … 327 325 } 328 326 329 327 // overridden in subclass CollectionTreeNode to reset and reencode display strings 328 public void resetDescendantEncodings() {} 329 public void refreshDescendantEncodings() {} 330 331 330 332 public void setModel(FileSystemModel model) { 331 333 this.model = model; -
main/trunk/gli/src/org/greenstone/gatherer/gui/EnrichPane.java
r18593 r23433 44 44 import org.greenstone.gatherer.collection.CollectionTreeNode; 45 45 import org.greenstone.gatherer.gui.tree.DragTree; 46 import org.greenstone.gatherer.metadata.FilenameEncoding; 46 47 import org.greenstone.gatherer.metadata.MetadataElement; 47 48 import org.greenstone.gatherer.metadata.MetadataValue; … … 287 288 public void valueChanged(TreeSelectionEvent event) 288 289 { 290 if(FilenameEncoding.isRefreshRequired()) { 291 // The CollectionTree is in the process of being re-built to deal with filename-encodings, 292 // so don't mess up the table during that time. 293 // (CollectionTreeNode.refreshDescendantEncodings() doesn't cope well if this method 294 // responds on Tree selection changes while the tree is updating its encodings, resulting in lost 295 // and misplaced metadata values in the table and thereby in the metadata.xml files themselves). 296 return; 297 } 298 299 289 300 // If we haven't got focus then it must have been a selection in the Gather pane, so don't bother rebuilding 290 301 if (has_focus == false) { -
main/trunk/gli/src/org/greenstone/gatherer/gui/GUIManager.java
r23143 r23433 59 59 import org.greenstone.gatherer.gui.metaaudit.MetaAuditFrame; 60 60 import org.greenstone.gatherer.gui.tree.DragTree; 61 import org.greenstone.gatherer.metadata.FilenameEncoding; 61 62 import org.greenstone.gatherer.metadata.MetadataSet; 62 63 import org.greenstone.gatherer.metadata.MetadataXMLFileManager; … … 295 296 tab_pane.setSelectedComponent(gather_pane); 296 297 Gatherer.c_man.closeCollection(); 298 FilenameEncoding.closeCollection(); // clear filename-to-encodings map 297 299 } 298 300 -
main/trunk/gli/src/org/greenstone/gatherer/metadata/MetadataValueTableModel.java
r13398 r23433 139 139 140 140 MetadataValueTableEntry metadata_value_table_entry = (MetadataValueTableEntry) metadata_value_table_entries.get(row); 141 142 if(metadata_value_table_entry == null) { 143 System.err.println("\n@@@@@ MetadataValueTableModel.getValueAt(): metadata_value_table_entry is unexpectedly null!\n"); 144 return null; 145 } 146 141 147 if (col == 0 && metadata_value_table_entry.isInheritedMetadata()) { 142 148 return metadata_value_table_entry.getFolderMetadataInheritedFrom(); … … 213 219 { 214 220 MetadataValueTableEntry metadata_value_table_entry = getMetadataValueTableEntry(row); 215 221 if(metadata_value_table_entry == null) { 222 System.err.println("\n@@@@@ MetadataValueTableModel.setValueAt(): metadata_value_table_entry is unexpectedly null!\n"); 223 return; 224 } 225 216 226 // If nothing has changed no action is necessary 217 227 String old_metadata_value = metadata_value_table_entry.getFullValue(); … … 252 262 MetadataValueTreeNode metadata_value_tree_node = metadata_element.addMetadataValue((String) new_metadata_value); 253 263 MetadataValue metadata_value = new MetadataValue(metadata_element, metadata_value_tree_node); 254 metadata_value.setIsAccumulatingMetadata(true); 264 metadata_value.setIsAccumulatingMetadata(true); 255 265 (new AppendMetadataTask(metadata_value)).run(); 256 266 } -
main/trunk/gli/src/org/greenstone/gatherer/metadata/MetadataXMLFile.java
r23394 r23433 31 31 import java.util.*; 32 32 import org.greenstone.gatherer.DebugStream; 33 import org.greenstone.gatherer.collection.CollectionTreeNode; 33 34 import org.greenstone.gatherer.util.XMLTools; 34 35 import org.w3c.dom.*; … … 45 46 static final private String METADATA_ELEMENT = "Metadata"; 46 47 48 /** Special metadata field: the filename encoding is a unique sort of metadata in 49 * that it is not just information stored with a collection file, but also needs to 50 * be applied in real-time to the collection file (to its filename) for display. */ 51 static final public String FILENAME_ENCODING_METADATA = "gs.filenameEncoding"; 52 47 53 // To speed things up a bit we keep the last accessed metadata.xml file in memory 48 54 static private File loaded_file = null; … … 57 63 58 64 59 public void addMetadata( File file, ArrayList metadata_values)65 public void addMetadata(CollectionTreeNode file_node, ArrayList metadata_values) 60 66 { 61 67 // If this metadata.xml file isn't the one currently loaded, load it now … … 76 82 77 83 // Determine the file's path relative to the location of the metadata.xml file 78 String metadata_xml_file_directory_path = getParentFile().getAbsolutePath();79 String file_relative_path = file .getAbsolutePath().substring(metadata_xml_file_directory_path.length());80 if (file_relative_path.startsWith(File .separator)) {81 file_relative_path = file_relative_path.substring(File .separator.length());84 String metadata_xml_file_directory_path = FilenameEncoding.fileToURLEncoding(getParentFile()); 85 String file_relative_path = file_node.getURLEncodedFilePath().substring(metadata_xml_file_directory_path.length()); 86 if (file_relative_path.startsWith(FilenameEncoding.URL_FILE_SEPARATOR)) { 87 file_relative_path = file_relative_path.substring(FilenameEncoding.URL_FILE_SEPARATOR.length()); 82 88 } 83 89 … … 127 133 appropriate_fileset_element.appendChild(new_description_element); 128 134 135 // add the fileset element for .* at the top: especially important for 136 // non-accumulating (and override mode) meta. Other type fileset elements can be appended 129 137 if(file_path_regexp.equals(DIRECTORY_FILENAME)) { 130 loaded_file_document.getDocumentElement().insertBefore(appropriate_fileset_element, loaded_file_document.getDocumentElement().getFirstChild()); 138 loaded_file_document.getDocumentElement().insertBefore(appropriate_fileset_element, 139 loaded_file_document.getDocumentElement().getFirstChild()); 131 140 } else { 132 141 loaded_file_document.getDocumentElement().appendChild(appropriate_fileset_element); … … 147 156 metadata_value_string = metadata_value_string.replaceAll("\\]", "]"); 148 157 158 // the gs.filenameEncoding metadata is unique in that, when added, removed or 159 // changed, it must be applied on the file(name) whose metadata has been adjusted 160 if(metadata_element_name_full.equals(FILENAME_ENCODING_METADATA)) { 161 metadata_value_string = processFilenameEncoding(file_path_regexp, 162 file_node, metadata_value_string, false); 163 // true only if removing meta 164 } 165 149 166 // Check if this piece of metadata has already been assigned to this FileSet element 150 167 boolean metadata_already_assigned = false; … … 156 173 String current_metadata_element_name_full = current_metadata_element.getAttribute("name"); 157 174 if (current_metadata_element_name_full.equals(metadata_element_name_full)) { 158 // if the metadata must not accumulate, then edit t ehcurrent value175 // if the metadata must not accumulate, then edit the current value 159 176 if (!metadata_value.isAccumulatingMetadata()) { 160 177 XMLTools.setNodeText(current_metadata_element, metadata_value_string); … … 196 213 197 214 198 public ArrayList getMetadataAssignedToFile(File file )215 public ArrayList getMetadataAssignedToFile(File file, boolean fileEncodingOnly) 199 216 { 200 217 // If this metadata.xml file isn't the one currently loaded, load it now … … 214 231 } 215 232 216 // Determine the file's path relative to the location of the metadata.xml file 233 // Determine the file's path relative to the location of the metadata.xml file 234 String file_relative_path = FilenameEncoding.fileToURLEncoding(file); 217 235 File metadata_xml_file_directory = getParentFile(); 218 String file_relative_path = file.getAbsolutePath().substring(metadata_xml_file_directory.getAbsolutePath().length()); 219 if (file_relative_path.startsWith(File.separator)) { 220 file_relative_path = file_relative_path.substring(File.separator.length()); 236 String metadata_xml_file_directory_path = FilenameEncoding.fileToURLEncoding(metadata_xml_file_directory); 237 file_relative_path = file_relative_path.substring(metadata_xml_file_directory_path.length()); 238 239 if (file_relative_path.startsWith(FilenameEncoding.URL_FILE_SEPARATOR)) { 240 file_relative_path = file_relative_path.substring(FilenameEncoding.URL_FILE_SEPARATOR.length()); 221 241 } 222 242 … … 255 275 256 276 // This fileset specifies metadata for the folder the file is in 257 if (file_relative_path.startsWith(current_filename_element_value + File .separator)) {277 if (file_relative_path.startsWith(current_filename_element_value + FilenameEncoding.URL_FILE_SEPARATOR)) { 258 278 current_fileset_matches = true; 259 279 folder_metadata_inherited_from = new File(metadata_xml_file_directory, current_filename_element_value); … … 272 292 Element current_metadata_element = (Element) metadata_elements_nodelist.item(k); 273 293 String metadata_element_name_full = current_metadata_element.getAttribute("name"); 294 // if we're only looking for fileEncoding metadata and this isn't it, skip to the next 295 if(fileEncodingOnly && !metadata_element_name_full.equals(FILENAME_ENCODING_METADATA)) { 296 continue; 297 } 274 298 String metadata_set_namespace = MetadataTools.getMetadataSetNamespace(metadata_element_name_full); 275 299 … … 335 359 336 360 337 public void removeMetadata( File file, ArrayList metadata_values)361 public void removeMetadata(CollectionTreeNode file_node, ArrayList metadata_values) 338 362 { 339 363 // If this metadata.xml file isn't the one currently loaded, load it now … … 354 378 355 379 // Determine the file's path relative to the location of the metadata.xml file 356 String metadata_xml_file_directory_path = getParentFile().getAbsolutePath();357 String file_relative_path = file .getAbsolutePath().substring(metadata_xml_file_directory_path.length());358 if (file_relative_path.startsWith(File .separator)) {359 file_relative_path = file_relative_path.substring(File .separator.length());380 String metadata_xml_file_directory_path = FilenameEncoding.fileToURLEncoding(getParentFile()); 381 String file_relative_path = file_node.getURLEncodedFilePath().substring(metadata_xml_file_directory_path.length()); 382 if (file_relative_path.startsWith(FilenameEncoding.URL_FILE_SEPARATOR)) { 383 file_relative_path = file_relative_path.substring(FilenameEncoding.URL_FILE_SEPARATOR.length()); 360 384 } 361 385 … … 422 446 String current_metadata_value_string = XMLTools.getElementTextValue(current_metadata_element); 423 447 if (current_metadata_value_string.equals(metadata_value_string)) { 448 424 449 // Remove this Metadata element 425 450 current_metadata_element.getParentNode().removeChild(current_metadata_element); 426 451 452 // the gs.filenameEncoding metadata is unique in that, when added, removed or 453 // changed, it must be applied on the file(name) whose metadata has been adjusted 454 if(current_metadata_element_name_full.equals(FILENAME_ENCODING_METADATA)) { 455 456 // metadata_value_string will hereafter be the inherited gs.FilenameEncoding 457 // metadata (if any), now that the value at this level has been removed 458 metadata_value_string = processFilenameEncoding(file_path_regexp, 459 file_node, "", true); // true only if *removing* this meta 460 } 461 427 462 // If there are no Metadata elements left now, remove the (empty) FileSet element 428 463 if (metadata_elements_nodelist.getLength() == 0) { … … 441 476 442 477 443 public void replaceMetadata( File file, MetadataValue old_metadata_value, MetadataValue new_metadata_value)478 public void replaceMetadata(CollectionTreeNode file_node, MetadataValue old_metadata_value, MetadataValue new_metadata_value) 444 479 { 445 480 // If this metadata.xml file isn't the one currently loaded, load it now … … 460 495 461 496 // Determine the file's path relative to the location of the metadata.xml file 462 String metadata_xml_file_directory_path = getParentFile().getAbsolutePath();463 String file_relative_path = file .getAbsolutePath().substring(metadata_xml_file_directory_path.length());464 if (file_relative_path.startsWith(File .separator)) {465 file_relative_path = file_relative_path.substring(File .separator.length());497 String metadata_xml_file_directory_path = FilenameEncoding.fileToURLEncoding(getParentFile()); 498 String file_relative_path = file_node.getURLEncodedFilePath().substring(metadata_xml_file_directory_path.length()); 499 if (file_relative_path.startsWith(FilenameEncoding.URL_FILE_SEPARATOR)) { 500 file_relative_path = file_relative_path.substring(FilenameEncoding.URL_FILE_SEPARATOR.length()); 466 501 } 467 502 … … 541 576 // If the new metadata value already existed, remove the original value 542 577 if (new_metadata_value_already_exists) { 543 metadata_element_to_edit.getParentNode().removeChild(metadata_element_to_edit); 578 if(metadata_element_to_edit != null) { //????????? 579 metadata_element_to_edit.getParentNode().removeChild(metadata_element_to_edit); 580 } else { 581 System.err.println("ERROR MetadataXMLFile: metadata_element_to_edit is null"); 582 } 544 583 } 545 584 // Otherwise replace the old value with the new value 546 585 // Ensure metadata_element_to_edit isn't null (may occur when multiple files are selected) 547 586 else if (metadata_element_to_edit != null) { 587 588 // the gs.filenameEncoding metadata is unique in that, when added, removed or 589 // changed, it must be applied on the file(name) whose metadata has been adjusted 590 if(metadata_element_name_full.equals(FILENAME_ENCODING_METADATA)) { 591 new_metadata_value_string = processFilenameEncoding(file_path_regexp, file_node, new_metadata_value_string, false); 592 // true only if removing meta 593 } 548 594 XMLTools.setElementTextValue(metadata_element_to_edit, new_metadata_value_string); 549 595 } … … 649 695 } 650 696 } 697 698 /** 699 * The gs.filenameEncoding metadata is unique in that, when added, removed or 700 * replaced, it must be applied on the file(name) whose metadata has been 701 * adjusted. 702 * This method handles all that, given the regular expression or filepath name 703 * to match on (.* matches subdirectories), the affected fileNode, the new 704 * encoding value and whether a new encoding value has been added/an existing 705 * one has been replaced or whether the encoding metadata has been removed. 706 * The new adjusted value for the encoding metadata is returned. 707 * 708 * MetadataXMLFileManager maintains a hashmap of (URL-encoded filepaths, encoding) 709 * to allow fast access to previously assigned gs.filenameEncoding metadata (if 710 * any) for each file. This hashmap also needs to be updated, but this update 711 * is complicated by the fact that it concerns regular expressions that could 712 * affect multiple filenames. 713 */ 714 public String processFilenameEncoding(String file_path_regexp, CollectionTreeNode file_node, 715 String encoding_metadata_value, boolean removingMetadata) 716 { 717 if(!FilenameEncoding.MULTIPLE_FILENAME_ENCODINGS_SUPPORTED) { 718 return encoding_metadata_value; 719 } 720 721 // Work out this filenode's new encoding and apply it: 722 723 if(removingMetadata) { // encoding_metadata_value = "" 724 // gs.filenameEncoding metadata being removed, work out 725 // any inherited metadata to replace it with in the meta-table 726 encoding_metadata_value = FilenameEncoding.getInheritedFilenameEncoding( 727 file_node.getURLEncodedFilePath(), file_node.getFile()); 728 // should be canonical encoding already 729 } 730 else if(!encoding_metadata_value.equals("")) { 731 // if adding or replacing filename encoding, 732 // get the canonical encoding name for this alias 733 encoding_metadata_value = FilenameEncoding.canonicalEncodingName(encoding_metadata_value); 734 } 735 // Reencode the display of this filenode only as any affected 736 // childnodes will be reencoded on FileNode.refreshDescendantEncodings() 737 file_node.reencodeDisplayName(encoding_metadata_value); 738 739 740 // Whether removing or adding/replacing the file's gs.filename encoding meta, 741 // store this in the file-to-encoding map for fast access, since the map stores 742 // empty string values when no meta has been assigned at this file level. 743 // In the case of removingMetadata, the value stored will be the fallback value 744 745 String urlpath = file_node.getURLEncodedFilePath(); 746 if(removingMetadata) { 747 // remove it from the map instead of inserting "", so that when folders in the collectiontree 748 // are being deleted or shifted, the removemetada (and addmetadata) calls that get fired 749 // for each affected filenodes does not cause the undesirable effect of multiple "" to be 750 // entered into the filename-to-encoding map for filepaths that no longer exist . 751 FilenameEncoding.map.remove(urlpath); 752 } else { // for adding and replacing, put the encoding into the map (also replaces any existing encoding for it) 753 FilenameEncoding.map.put(urlpath, encoding_metadata_value); 754 } 755 756 // If new folder-level metadata (or metadata for a set of files fitting a pattern) has been 757 // assigned, the file_to_encodings map will be cleared for all descendant folders and files, 758 // so that these can be re-calculated upon refreshing the visible parts of the CollectionTree. 759 // Mark the state as requiring a refresh of the CollectionTree. 760 // This next step also serves to prevent the MetadataValueTableModel from trying to update 761 // itself while a refresh (involving re-encoding of filenames of visible nodes) is in progress. 762 FilenameEncoding.setRefreshRequired(true); 763 764 return encoding_metadata_value; 765 } 651 766 } -
main/trunk/gli/src/org/greenstone/gatherer/metadata/MetadataXMLFileManager.java
r23410 r23433 90 90 if (current_file_directory_path.equals(metadata_xml_file.getParentFile().getAbsolutePath())) { 91 91 applicable_metadata_xml_file_found = true; 92 metadata_xml_file.addMetadata( current_file, metadata_values);92 metadata_xml_file.addMetadata(file_nodes[i], metadata_values); 93 93 if (!modified_metadata_xml_files.contains(metadata_xml_file)) { 94 94 modified_metadata_xml_files.add(metadata_xml_file); … … 107 107 108 108 // ...and add the metadata 109 new_metadata_xml_file.addMetadata( current_file, metadata_values);109 new_metadata_xml_file.addMetadata(file_nodes[i], metadata_values); 110 110 if (!modified_metadata_xml_files.contains(new_metadata_xml_file)) { 111 111 modified_metadata_xml_files.add(new_metadata_xml_file); … … 160 160 161 161 // Get the metadata assigned to the specified file from the applicable metadata.xml files 162 ArrayList assigned_metadata = getMetadataAssignedToFile(file, applicable_metadata_xml_files );162 ArrayList assigned_metadata = getMetadataAssignedToFile(file, applicable_metadata_xml_files, false); 163 163 164 164 // Remove any folder-level metadata … … 173 173 174 174 175 /** Returns the metadata assigned to a file inside the collection, excluding folder-level/inherited metadata. */ 176 static public ArrayList getMetadataAssignedDirectlyToFile(File file) 177 { 178 return getMetadataAssignedDirectlyToFile(file, false); 179 } 180 175 181 /** Returns the metadata assigned to a file inside the collection, excluding folder-level/inherited metadata. */ 176 static public ArrayList getMetadataAssignedDirectlyToFile(File file) 177 { 178 // Get all the metadata assigned to the specified file... 179 ArrayList assigned_metadata = getMetadataAssignedToFile(file); 180 181 // ...then remove any folder-level metadata 182 for (int i = assigned_metadata.size() - 1; i >= 0; i--) { 183 if (((MetadataValue) assigned_metadata.get(i)).isInheritedMetadata()) { 184 assigned_metadata.remove(i); 185 } 186 } 187 188 return assigned_metadata; 189 } 190 182 static public ArrayList getMetadataAssignedDirectlyToFile(File file, boolean filenameEncodingMetaOnly) 183 { 184 185 // Get all the metadata assigned to the specified file... 186 ArrayList assigned_metadata = getMetadataAssignedToFile(file, filenameEncodingMetaOnly); 187 188 // ...then remove any folder-level metadata 189 for (int i = assigned_metadata.size() - 1; i >= 0; i--) { 190 if (((MetadataValue) assigned_metadata.get(i)).isInheritedMetadata()) { 191 assigned_metadata.remove(i); 192 } 193 } 194 195 return assigned_metadata; 196 /* 197 // Get all the metadata assigned to the specified file... 198 // Build up a list of applicable metadata.xml files - which in this case 199 // is exclusively the metadata file at this file/folder's own level. 200 ArrayList applicable_metadata_xml_files = new ArrayList(); 201 202 // Find the metadata.xml file (if any) that is at the same level as the file 203 String file_directory_path = (file.isDirectory() ? file : file.getParentFile()).getAbsolutePath() + File.separator; 204 for (int i = 0; i < metadata_xml_files.size(); i++) { 205 MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(i); 206 207 if (file_directory_path.equals(metadata_xml_file.getParentFile().getAbsolutePath() + File.separator)) { 208 //System.err.println("Found metadata_xml_file: " + metadata_xml_file); 209 applicable_metadata_xml_files.add(metadata_xml_file); 210 } 211 } 212 213 if(applicable_metadata_xml_files.size() == 0) { 214 return new ArrayList(0); 215 } 216 217 // Return the metadata assigned to the specified file from the applicable metadata.xml files 218 return getMetadataAssignedToFile(file, applicable_metadata_xml_files, filenameEncodingMetaOnly); 219 */ 220 } 221 191 222 192 223 /** Returns all the metadata assigned to a file inside the collection. */ 193 224 static public ArrayList getMetadataAssignedToFile(File file) 225 { 226 return getMetadataAssignedToFile(file, false); 227 } 228 229 /** Returns all the metadata assigned to a file inside the collection (or 230 * just gs.filenameEncoding if parameter filenameEncodingMetaOnly is true), 231 * including folder-level/inherited metadata. 232 */ 233 static public ArrayList getMetadataAssignedToFile(File file, boolean filenameEncodingMetaOnly) 194 234 { 195 235 // Build up a list of applicable metadata.xml files … … 207 247 } 208 248 209 // sort the metadataxml files in order starting from those in the249 // Sort the metadataxml files in order starting from those in the 210 250 // topmost folders down to the one in the lowest level folder. 211 251 Collections.sort(applicable_metadata_xml_files, metadataXMLFileComparator); 212 252 // Return the metadata assigned to the specified file from the applicable metadata.xml files 213 return getMetadataAssignedToFile(file, applicable_metadata_xml_files); 214 } 215 216 217 static private ArrayList getMetadataAssignedToFile(File file, ArrayList applicable_metadata_xml_files) 253 return getMetadataAssignedToFile(file, applicable_metadata_xml_files, filenameEncodingMetaOnly); 254 } 255 256 // package access method 257 static ArrayList getMetadataAssignedToFile(File file, ArrayList applicable_metadata_xml_files, 258 boolean filenameEncodingMetaOnly) 218 259 { 219 260 // Build up a list of metadata values assigned to this file … … 225 266 DebugStream.println("Applicable metadata.xml file: " + metadata_xml_file); 226 267 227 ArrayList metadata_values = metadata_xml_file.getMetadataAssignedToFile(file );268 ArrayList metadata_values = metadata_xml_file.getMetadataAssignedToFile(file, filenameEncodingMetaOnly); 228 269 for (int j = 0; j < metadata_values.size(); j++) { 229 270 MetadataValue metadata_value = (MetadataValue) metadata_values.get(j); … … 316 357 // This metadata.xml file is only potentially applicable if it is above or at the same level as the file 317 358 if (current_file_directory_path.startsWith(metadata_xml_file.getParentFile().getAbsolutePath())) { 318 metadata_xml_file.removeMetadata( current_file, metadata_values);359 metadata_xml_file.removeMetadata(file_nodes[i], metadata_values); 319 360 if (!modified_metadata_xml_files.contains(metadata_xml_file)) { 320 361 modified_metadata_xml_files.add(metadata_xml_file); … … 350 391 // This metadata.xml file is only applicable if it is at the same level as the file 351 392 if (current_file_directory_path.equals(metadata_xml_file.getParentFile().getAbsolutePath())) { 352 metadata_xml_file.replaceMetadata( current_file, old_metadata_value, new_metadata_value);393 metadata_xml_file.replaceMetadata(file_nodes[i], old_metadata_value, new_metadata_value); 353 394 if (!modified_metadata_xml_files.contains(metadata_xml_file)) { 354 395 modified_metadata_xml_files.add(metadata_xml_file); … … 399 440 400 441 401 402 * Comparator to order MetadataXMLFiles in ascending order from403 * those in a higher level folder to those in a lower level folder404 * It is based on the assumption that all MetadataXMLFiles sent to405 * it to compare will be linear descendants of one toplevel folder406 * E.g. /A/metadata.xml, /A/B/metadata.xml, /A/B/C/D/metadata.xml.407 * In other words, that each is a substring of one otheruntil we408 * get to the toplevel folder.409 410 411 412 public int compare(Object o1, Object o2) {413 414 return -1;415 416 return 1;417 418 419 420 421 422 423 424 // if 1 is a prefix2, then 1 < 2 in the ordering (1 comes before 2)425 426 return -1;427 428 return 1;429 430 // unlikely that the metadata.xml files will be the same431 // or that neither is a prefix of the other432 return filename1.compareTo(filename2); // sorts in ascending order433 434 435 436 437 438 439 return false;440 441 442 443 444 445 446 442 /** 443 * Comparator to order MetadataXMLFiles in ascending order from 444 * those in a higher level folder to those in a lower level folder 445 * It is based on the assumption that all MetadataXMLFiles sent to 446 * it to compare will be linear descendants of one toplevel folder 447 * E.g. /A/metadata.xml, /A/B/metadata.xml, /A/B/C/D/metadata.xml. 448 * In other words, that each is a substring of one of the others until we 449 * the toplevel folder is reached. 450 */ 451 private static class MetadataXMLFileComparator implements Comparator { 452 453 public int compare(Object o1, Object o2) { 454 if(!(o1 instanceof MetadataXMLFile)) { 455 return -1; 456 } else if (!(o2 instanceof MetadataXMLFile)) { 457 return 1; 458 } 459 460 // Both are MetadataXMLFiles objects. Remove the terminating 461 // "metadata.xml" from their filenames to get their containing folder 462 String filename1 = ((MetadataXMLFile)o1).getParentFile().getAbsolutePath(); 463 String filename2 = ((MetadataXMLFile)o2).getParentFile().getAbsolutePath(); 464 465 // if 1 is a prefix of 2, then 1 < 2 in the ordering (1 comes before 2) 466 if(filename2.startsWith(filename1)) { 467 return -1; 468 } else if(filename1.startsWith(filename2)) { 469 return 1; 470 } else { 471 // unlikely that the metadata.xml files will be the same 472 // or that neither is a prefix of the other 473 return filename1.compareTo(filename2); // sorts in ascending order 474 } 475 476 } 477 478 public boolean equals(Object obj) { 479 if(!(obj instanceof MetadataXMLFileComparator)) { 480 return false; 481 } 482 483 // else it is the same sort of comparator 484 return true; 485 } 486 487 } 447 488 448 489 } -
main/trunk/gli/src/org/greenstone/gatherer/util/SynchronizedTreeModelTools.java
r11084 r23433 31 31 import javax.swing.tree.*; 32 32 import org.greenstone.gatherer.DebugStream; 33 import org.greenstone.gatherer.metadata.FilenameEncoding; 34 import org.greenstone.gatherer.collection.CollectionTreeNode; 33 35 34 36 /** Due to the TreeModel objects not having any synchronization, certain assumptions, such as the model state remaining constant during a repaint, don't always hold - especially given that I'm changing the tree model on a different thread. In order to get around this I will use the latest swing paradigm wherein you flag a section of code to be executed by the AWT GUI Event queue, as soon as other gui tasks have finished. This way I shouldn't have tree redraws throwing NPEs because the array size of the children of a certain node has changed -while- the repaint call was made, i.e. repaint() calls getChildCount() = 13, removeNodeFromParent() called, repaint calls getChildAt(12) = ArrayIndexOutOfBoundsException. … … 104 106 final Runnable doRemoveNodeFromParent = new Runnable() { 105 107 public void run() { 106 model.removeNodeFromParent(target_node); 108 // If we're dealing with a collection tree node, it may have 109 // gs.FilenameEncoding assigned, so we remove its entry from the map. 110 // Needs to be done here because the tree is constantly changing 111 // when nodes are being removed, renamed and deleted, and this 112 // affects lookup queries sent to the map. 113 // Don't need to do a recursive reset on this coltreenode, because 114 // Delete/Move/Rename FileJobs were created for *each* node 115 if(target_node instanceof CollectionTreeNode) { 116 CollectionTreeNode colNode = (CollectionTreeNode)target_node; 117 FilenameEncoding.map.remove(colNode.getURLEncodedFilePath()); 118 } 119 120 model.removeNodeFromParent(target_node); 107 121 } 108 122 };
Note:
See TracChangeset
for help on using the changeset viewer.