001 /* 002 * The contents of this file are subject to the Mozilla Public 003 * License Version 1.1 (the "License"); you may not use this file 004 * except in compliance with the License. You may obtain a copy of 005 * the License at http://www.mozilla.org/MPL/ 006 * 007 * Software distributed under the License is distributed on an "AS 008 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 009 * implied. See the License for the specific language governing 010 * rights and limitations under the License. 011 * 012 * The Original Code is Knowtator. 013 * 014 * The Initial Developer of the Original Code is University of Colorado. 015 * Copyright (C) 2005 - 2008. All Rights Reserved. 016 * 017 * Knowtator was developed by the Center for Computational Pharmacology 018 * (http://compbio.uchcs.edu) at the University of Colorado Health 019 * Sciences Center School of Medicine with support from the National 020 * Library of Medicine. 021 * 022 * Current information about Knowtator can be obtained at 023 * http://knowtator.sourceforge.net/ 024 * 025 * Contributor(s): 026 * Philip V. Ogren <philip@ogren.info> (Original Author) - pvo 027 * Angus Roberts - ar 028 */ 029 030 /** 031 * Changes 032 * 2/8/2007 ar updated getRecentDirectory see note at method 033 * 2/8/2007 ar updated save() see note at method 034 * 035 */ 036 package edu.uchsc.ccp.knowtator.textsource.files; 037 038 import java.awt.Component; 039 import java.io.File; 040 import java.io.IOException; 041 import java.nio.charset.Charset; 042 import java.nio.charset.IllegalCharsetNameException; 043 import java.util.ArrayList; 044 import java.util.Collections; 045 import java.util.Comparator; 046 import java.util.HashMap; 047 import java.util.List; 048 import java.util.Map; 049 import java.util.regex.Matcher; 050 import java.util.regex.Pattern; 051 052 import javax.swing.JFileChooser; 053 import javax.swing.JOptionPane; 054 055 import edu.stanford.smi.protege.model.Cls; 056 import edu.stanford.smi.protege.model.KnowledgeBase; 057 import edu.stanford.smi.protege.model.Project; 058 import edu.uchsc.ccp.knowtator.KnowtatorProjectUtil; 059 import edu.uchsc.ccp.knowtator.textsource.TextSource; 060 import edu.uchsc.ccp.knowtator.textsource.TextSourceAccessException; 061 import edu.uchsc.ccp.knowtator.textsource.TextSourceCollection; 062 import edu.uchsc.ccp.knowtator.textsource.TextSourceIterator; 063 064 public class FileTextSourceCollection extends TextSourceCollection { 065 public static final String DISPLAY_NAME = "Local Files"; 066 067 public static String CLS_NAME = "file text source"; 068 069 public static final String PROJECT_SETTING_RECENT_DIRECTORY = new String( 070 "FileTextSourceCollection_RECENT_DIRECTORY"); 071 072 public static final String PROJECT_SETTING_RECENT_CHARSET = new String("FileTextSourceCollection_RECENT_CHARSET"); 073 074 File directory; 075 076 Charset charset; 077 078 String rootPath; 079 080 String name; 081 082 Map<String, TextSource> namesToTextSource; 083 084 Map<TextSource, Integer> textSourceToIndex; 085 086 List<TextSource> textSources; 087 088 List<String> textSourceNames; 089 090 public FileTextSourceCollection(String directoryName, Charset charset) throws IOException { 091 this(new File(directoryName), charset); 092 } 093 094 public FileTextSourceCollection(File directory, Charset charset) throws IOException { 095 this.directory = directory; 096 this.charset = charset; 097 name = directory.getName(); 098 rootPath = directory.getPath(); 099 100 List<File> files = new ArrayList<File>(); 101 collectFiles(directory, files); 102 103 Collections.sort(files, new Comparator<File>() { 104 public int compare(File file1, File file2) { 105 return String.CASE_INSENSITIVE_ORDER.compare(file1.getName(), file2.getName()); 106 } 107 }); 108 109 namesToTextSource = new HashMap<String, TextSource>(); 110 textSourceToIndex = new HashMap<TextSource, Integer>(); 111 textSources = new ArrayList<TextSource>(files.size()); 112 textSourceNames = new ArrayList<String>(files.size()); 113 114 for (File file : files) { 115 TextSource textSource = new FileTextSource(file, rootPath, charset); 116 String textSourceName = textSource.getName(); 117 namesToTextSource.put(textSourceName, textSource); 118 textSources.add(textSource); 119 textSourceNames.add(textSourceName); 120 textSourceToIndex.put(textSource, textSources.size() - 1); 121 } 122 Collections.sort(textSourceNames); 123 } 124 125 /** 126 * This method allows a text source to be added to this TextSourceCollection 127 * on the fly. 128 * 129 * @param fileToAdd 130 * the file to add to this FileTextSourceCollection 131 */ 132 public void addTextSourceToCollection(File fileToAdd) { 133 TextSource textSource = new FileTextSource(fileToAdd, rootPath, charset); 134 String textSourceName = textSource.getName(); 135 namesToTextSource.put(textSourceName, textSource); 136 textSources.add(textSource); 137 textSourceNames.add(textSourceName); 138 textSourceToIndex.put(textSource, textSources.size() - 1); 139 Collections.sort(textSourceNames); 140 } 141 142 public File getDirectory() { 143 return directory; 144 } 145 146 private void collectFiles(File file, List<File> files) throws IOException { 147 if (file.isDirectory()) { 148 if (!file.getName().equals(".svn") && !file.getName().equals("CVS")) { 149 File[] dirFiles = file.listFiles(); 150 for (int i = 0; i < dirFiles.length; i++) { 151 collectFiles(dirFiles[i], files); 152 } 153 } 154 } else { 155 files.add(file); 156 } 157 } 158 159 public int size() { 160 return textSources.size(); 161 } 162 163 public TextSource get(int index) throws TextSourceAccessException { 164 TextSource textSource = textSources.get(index); 165 if (textSource != null) 166 return textSource; 167 throw new TextSourceAccessException("There is no text source at index=" + index 168 + " for text source collection = " + getName()); 169 } 170 171 public TextSource get(String textSourceName) throws TextSourceAccessException { 172 TextSource textSource = namesToTextSource.get(textSourceName); 173 if (textSource != null) 174 return textSource; 175 throw new TextSourceAccessException("There is no text source for name='" + textSourceName 176 + "' for text source collection = " + getName()); 177 } 178 179 public int getIndex(TextSource textSource) { 180 Integer index = textSourceToIndex.get(textSource); 181 if (index != null) { 182 return index.intValue(); 183 } 184 return -1; 185 } 186 187 public String getName() { 188 return name; 189 } 190 191 public TextSource select(Component parent) { 192 Object selection = JOptionPane.showInputDialog(parent, "Select text source", "Select text source", 193 JOptionPane.INFORMATION_MESSAGE, null, textSourceNames.toArray(), textSourceNames.toArray()[0]); 194 try { 195 if (selection != null) 196 return get((String) selection); 197 } catch (TextSourceAccessException tsae) { 198 return null; 199 } 200 return null; 201 } 202 203 public TextSource find(Component parent) { 204 String searchString = JOptionPane.showInputDialog(parent, "Enter a regular expression for the name of a text source", "Find a text source", 205 JOptionPane.PLAIN_MESSAGE); 206 Pattern pattern = Pattern.compile(searchString); 207 Matcher matcher; 208 try { 209 210 for (String textSourceName : textSourceNames) { 211 matcher = pattern.matcher(textSourceName); 212 if (matcher.find()) 213 return get(textSourceName); 214 215 } 216 } catch (TextSourceAccessException tsae) { 217 tsae.printStackTrace(); 218 } 219 220 JOptionPane.showMessageDialog(parent, "No text source found with a name matching the search string you provided."); 221 return null; 222 } 223 224 /** 225 * contribution from Angus Roberts saves a relative path if the directory is 226 * under the protege project directory 227 */ 228 public void save(Project project) { 229 // If the directory is contained in the project, save relative to the 230 // project. 231 // Otherwise, save the directory as given 232 String directoryPath = directory.getAbsolutePath(); 233 String annotationProjectPath = new File(project.getProjectDirectoryURI().getPath()).getPath(); 234 235 if (directoryPath.startsWith(annotationProjectPath)) { 236 directoryPath = directoryPath.substring(annotationProjectPath.length() + 1); 237 project.setClientInformation(PROJECT_SETTING_RECENT_DIRECTORY, directoryPath); 238 } else { 239 project.setClientInformation(PROJECT_SETTING_RECENT_DIRECTORY, directory.getPath()); 240 } 241 project.setClientInformation(PROJECT_SETTING_RECENT_CHARSET, charset.name()); 242 } 243 244 public static TextSourceCollection open(Project project) { 245 File recentDirectory = getRecentDirectory(project); 246 Charset charset = getRecentCharset(project); 247 if (recentDirectory != null && charset != null) { 248 try { 249 TextSourceCollection tsc = new FileTextSourceCollection(recentDirectory, charset); 250 return tsc; 251 } catch (IOException ioe) { 252 ioe.printStackTrace(); 253 } 254 } 255 return null; 256 } 257 258 /** 259 * updated by Angus Roberts to look for the directory relative to the 260 * protege project directory 261 * 262 * @param project 263 * @return 264 */ 265 private static File getRecentDirectory(Project project) { 266 String recentPath = (String) project.getClientInformation(PROJECT_SETTING_RECENT_DIRECTORY); 267 268 if (recentPath == null) 269 return null; 270 271 File recentDirectory = new File(recentPath); 272 // if the path is not absolute, and If the directory can be found 273 // below the protege project, restore from here. 274 if (!recentDirectory.isAbsolute()) { 275 String annotationProjectPath = new File(project.getProjectDirectoryURI()).getPath(); 276 String absoluteRecentPath = annotationProjectPath + File.separator + recentPath; 277 recentDirectory = new File(absoluteRecentPath); 278 if (recentDirectory.exists() && recentDirectory.isDirectory()) { 279 return recentDirectory; 280 } else { 281 recentDirectory = new File(recentPath); 282 } 283 } 284 285 if (recentDirectory.exists() && recentDirectory.isDirectory()) { 286 return recentDirectory; 287 } 288 return null; 289 } 290 291 private static Charset getRecentCharset(Project project) { 292 String charsetName = (String) project.getClientInformation(PROJECT_SETTING_RECENT_CHARSET); 293 if (charsetName == null) 294 return null; 295 try { 296 Charset charset = Charset.forName(charsetName); 297 return charset; 298 } catch (IllegalCharsetNameException icne) { 299 return null; 300 } 301 } 302 303 public static TextSourceCollection open(Project project, Component parent) { 304 JFileChooser chooser = new JFileChooser(); 305 File homeDirectory = chooser.getCurrentDirectory(); 306 File recentDirectory = getRecentDirectory(project); 307 if (recentDirectory != null) { 308 chooser.setCurrentDirectory(recentDirectory); 309 } 310 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 311 int returnVal = chooser.showOpenDialog(parent); 312 if (returnVal == JFileChooser.APPROVE_OPTION) { 313 File file = chooser.getSelectedFile(); 314 if (file.equals(homeDirectory)) { 315 JOptionPane 316 .showMessageDialog( 317 parent, 318 "Choosing your home directory is not allowed. Please select a directory that contains only text files that you want to annotate.", 319 "", JOptionPane.ERROR_MESSAGE); 320 return null; 321 } 322 try { 323 FileTextSourceCollection tsc = new FileTextSourceCollection(file, Charset.forName("UTF-8")); 324 return tsc; 325 } catch (IOException ioe) { 326 ioe.printStackTrace(); 327 JOptionPane.showMessageDialog(parent, "Unable to open directory as a text source collection", "", 328 JOptionPane.ERROR_MESSAGE); 329 } 330 } 331 return null; 332 } 333 334 public static void createCls(KnowledgeBase kb) { 335 if (kb.getCls(CLS_NAME) == null) { 336 Cls textSourceParent = kb.getCls(KnowtatorProjectUtil.TEXT_SOURCE_CLS_NAME); 337 List<Cls> parents = new ArrayList<Cls>(); 338 parents.add(textSourceParent); 339 kb.createCls(CLS_NAME, parents); 340 } 341 return; 342 } 343 344 public TextSourceIterator iterator() { 345 return new FileTextSourceIterator(); 346 } 347 348 class FileTextSourceIterator implements TextSourceIterator { 349 int tsIndex = -1; 350 351 public TextSource next() throws TextSourceAccessException { 352 try { 353 return textSources.get(++tsIndex); 354 } catch (IndexOutOfBoundsException ioobe) { 355 throw new TextSourceAccessException(ioobe); 356 } 357 } 358 359 public boolean hasNext() { 360 return (tsIndex + 1) < textSources.size(); 361 } 362 } 363 } 364 365 // String[] selectionValues = new String[] {"US-ASCII", 366 // "ISO-8859-1", 367 // "UTF-8", 368 // "UTF-16BE", 369 // "UTF-16LE", 370 // "UTF-16"}; 371 // 372 // String selectionValue = (String) JOptionPane.showInputDialog(parent,"Select 373 // file encoding","File encoding selection",JOptionPane.PLAIN_MESSAGE, null, 374 // selectionValues, selectionValues[0]); 375 // if(selectionValue == null) return null; 376 // Charset charset = null; 377 // try 378 // { 379 // charset = Charset.forName(selectionValue); 380 // } 381 // catch(IllegalCharsetNameException icne) 382 // { 383 // JOptionPane.showMessageDialog(parent,"Invalid charset.", "Invalid charset 384 // error",JOptionPane.ERROR_MESSAGE); 385 // return null; 386 // } 387