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) 027 */ 028 029 package edu.uchsc.ccp.knowtator; 030 031 import java.awt.Component; 032 import java.io.PrintWriter; 033 import java.io.StringWriter; 034 import java.lang.reflect.Field; 035 import java.lang.reflect.Method; 036 import java.util.ArrayList; 037 import java.util.Collection; 038 import java.util.HashMap; 039 040 import javax.swing.JOptionPane; 041 042 import org.apache.log4j.Logger; 043 044 import edu.stanford.smi.protege.model.Instance; 045 import edu.stanford.smi.protege.model.KnowledgeBase; 046 import edu.stanford.smi.protege.model.Project; 047 import edu.stanford.smi.protege.model.SimpleInstance; 048 import edu.uchsc.ccp.knowtator.textsource.TextSource; 049 import edu.uchsc.ccp.knowtator.textsource.TextSourceAccessException; 050 import edu.uchsc.ccp.knowtator.textsource.TextSourceChangeEvent; 051 import edu.uchsc.ccp.knowtator.textsource.TextSourceChangeListener; 052 import edu.uchsc.ccp.knowtator.textsource.TextSourceCollection; 053 import edu.uchsc.ccp.knowtator.textsource.TextSourceCollectionChangeEvent; 054 import edu.uchsc.ccp.knowtator.textsource.TextSourceCollectionChangeListener; 055 056 /** 057 * This class helps one to find a "text source" instance in the knowledgebase 058 * given a TextSource object or vice versa. 059 * 060 * In order to make this as simple to code up as possible, I made some 061 * simplifying assumptions which result in less flexibility for the user. 062 * 063 * One is that all instances of "text source" share the same namespace - and 064 * there should be no overlap - even across different types of "text source" 065 * instances. 066 * 067 * A user must know where a to find a TextSource given its name if the code 068 * cannot find it in the TextSouceCollection that it has open. 069 * 070 * 071 */ 072 073 public class TextSourceUtil { 074 075 AnnotationUtil annotationUtil; 076 077 KnowtatorProjectUtil kpu; 078 079 KnowledgeBase kb; 080 081 Project project; 082 083 Class[] textSourceCollectionClasses; 084 085 String[] displayNames; 086 087 HashMap displayNames2TSC; 088 089 String[] clsNames; 090 091 HashMap clsNames2TSC; 092 093 TextSource currentTextSource; 094 095 java.util.List<TextSourceChangeListener> textSourceChangeListeners; 096 097 TextSourceCollection currentTextSourceCollection; 098 099 java.util.List<TextSourceCollectionChangeListener> textSourceCollectionChangeListeners; 100 101 Logger logger = Logger.getLogger(TextSourceUtil.class); 102 103 public TextSourceUtil(AnnotationUtil annotationUtil, KnowtatorProjectUtil kpu) { 104 this.annotationUtil = annotationUtil; 105 this.kpu = kpu; 106 this.kb = annotationUtil.kb; 107 this.project = kb.getProject(); 108 109 textSourceChangeListeners = new ArrayList<TextSourceChangeListener>(); 110 textSourceCollectionChangeListeners = new ArrayList<TextSourceCollectionChangeListener>(); 111 112 java.util.List<Class> classes = new ArrayList<Class>(); 113 114 Collection<Instance> tscImplementations = (Collection<Instance>) kb 115 .getInstances(kpu.getTscImplementationsCls()); 116 117 String[] textSourceCollectionClassNames = new String[tscImplementations.size()]; 118 119 int _tsc = 0; 120 for (Instance tscImplementation : tscImplementations) { 121 String className = (String) tscImplementation.getOwnSlotValue(kb.getSlot("knowtator_tsc_implementation")); 122 textSourceCollectionClassNames[_tsc++] = className; 123 } 124 125 Class textSourceCollectionClass = null; 126 try { 127 textSourceCollectionClass = Class.forName("edu.uchsc.ccp.knowtator.textsource.TextSourceCollection"); 128 } catch (ClassNotFoundException cnfe) { 129 cnfe.printStackTrace(); 130 } 131 132 for (int i = 0; i < textSourceCollectionClassNames.length; i++) { 133 try { 134 Class tscClass = Class.forName(textSourceCollectionClassNames[i]); 135 if (isSubclass(tscClass, textSourceCollectionClass)) { 136 classes.add(tscClass); 137 } else 138 System.err.println("WARNING: class " + textSourceCollectionClassNames[i] 139 + " is not a subclass of edu.uchsc.ccp.knowtator.textsource.TextSourceCollection"); 140 } catch (ClassNotFoundException cnfe) { 141 System.err.println("WARNING: class " + textSourceCollectionClassNames[i] + " not found in classpath"); 142 } 143 } 144 textSourceCollectionClasses = (Class[]) (classes.toArray(new Class[classes.size()])); 145 displayNames = new String[textSourceCollectionClasses.length]; 146 displayNames2TSC = new HashMap(textSourceCollectionClasses.length); 147 clsNames = new String[textSourceCollectionClasses.length]; 148 clsNames2TSC = new HashMap(textSourceCollectionClasses.length); 149 150 for (int i = 0; i < textSourceCollectionClasses.length; i++) { 151 try { 152 Field displayNameField = textSourceCollectionClasses[i].getField("DISPLAY_NAME"); 153 String displayName = (String) displayNameField.get(null); 154 displayNames[i] = displayName; 155 displayNames2TSC.put(displayName, textSourceCollectionClasses[i]); 156 157 Field clsNameField = textSourceCollectionClasses[i].getField("CLS_NAME"); 158 String clsName = (String) clsNameField.get(null); 159 clsNames[i] = clsName; 160 clsNames2TSC.put(clsName, textSourceCollectionClasses[i]); 161 162 Method createClsMethod = textSourceCollectionClasses[i].getMethod("createCls", 163 new Class[] { KnowledgeBase.class }); 164 createClsMethod.invoke(null, kb); 165 } catch (Exception exception) { 166 exception.printStackTrace(); 167 } 168 } 169 logger.debug("made it to here"); 170 171 } 172 173 public void init() { 174 TextSourceCollection tsc = ProjectSettings.getRecentTextSourceCollection(project); 175 if (tsc != null) { 176 int recentIndex = ProjectSettings.getRecentTextSourceCollectionIndex(project); 177 178 setCurrentTextSourceCollection(tsc); 179 180 TextSource recentTextSource = null; 181 try { 182 recentTextSource = tsc.get(recentIndex); 183 } catch (TextSourceAccessException tsae) { 184 try { 185 recentTextSource = tsc.get(0); 186 } catch (TextSourceAccessException e) { 187 } 188 } 189 if (recentTextSource != null) { 190 setCurrentTextSource(recentTextSource); 191 } 192 } 193 } 194 195 public TextSourceCollection selectTextSourceCollection(Component parent) { 196 Object selection = JOptionPane.showInputDialog(parent, "Please select a text source type.", 197 "Text source type selection", JOptionPane.PLAIN_MESSAGE, null, displayNames, displayNames[0]); 198 199 TextSourceCollection newTextSourceCollection; 200 201 try { 202 if (selection != null) { 203 Class textSourceCollectionClass = (Class) displayNames2TSC.get(selection); 204 Method selectionMethod = textSourceCollectionClass.getMethod("open", new Class[] { Project.class, 205 Component.class }); 206 newTextSourceCollection = (TextSourceCollection) selectionMethod.invoke(null, new Object[] { project, 207 parent }); 208 return newTextSourceCollection; 209 } 210 } catch (Exception exception) { 211 StringWriter stackTraceWriter = new StringWriter(); 212 exception.printStackTrace(new PrintWriter(stackTraceWriter)); 213 String stackTrace = stackTraceWriter.toString(); 214 JOptionPane.showMessageDialog(parent, "Error opening text source collection: Stack trace = " + stackTrace, 215 "Error opening text source collection", JOptionPane.ERROR_MESSAGE, null); 216 exception.printStackTrace(); 217 } 218 return null; 219 } 220 221 private static boolean isSubclass(Class subClass, Class superClass) { 222 Class cls = subClass.getSuperclass(); 223 if (cls == null) 224 return false; 225 else if (cls.equals(superClass)) { 226 return true; 227 } else { 228 return isSubclass(cls, superClass); 229 } 230 231 } 232 233 /** 234 * This method finds a "text source" instance in the knowledgebase for the 235 * given TextSouce object. The "search" is very simplistic - simply return 236 * the instance in the knowledgebase that has the name textSource.getName(). 237 * The namespace of your text sources - regardless of what kind they are - 238 * should not have conflicts/overlaps 239 * 240 * @param textSource 241 * @param create 242 * - if true: if there is not a "text source" instance for the 243 * TextSource object then create one. 244 * @return the "text source" instance for the given TextSource object. 245 */ 246 247 public SimpleInstance getTextSourceInstance(TextSource textSource, boolean create) { 248 SimpleInstance textSourceInstance = (SimpleInstance) kb.getInstance(textSource.getName()); 249 if (textSourceInstance == null && create) { 250 return (SimpleInstance) textSource.createTextSourceInstance(kb); 251 } 252 return textSourceInstance; 253 } 254 255 public TextSource getTextSource(Instance textSourceInstance) throws TextSourceAccessException { 256 TextSourceCollection tsc = getCurrentTextSourceCollection(); 257 String name = textSourceInstance.getName(); 258 return tsc.get(name); 259 } 260 261 public String getTextSourceAnnotationComment(Instance textSourceInstance) { 262 263 String annotationComment = (String) textSourceInstance.getOwnSlotValue(kpu.annotationCommentSlot); 264 if (annotationComment == null) { 265 return ""; 266 } 267 return annotationComment; 268 } 269 270 public String getTextSourceAnnotationComment(TextSource textSource) { 271 Instance textSourceInstance = getTextSourceInstance(textSource, false); 272 if (textSourceInstance != null) { 273 return getTextSourceAnnotationComment(textSourceInstance); 274 } 275 return ""; 276 } 277 278 public void setTextSourceAnnotationComment(Instance textSourceInstance, String comment) { 279 textSourceInstance.setOwnSlotValue(kpu.annotationCommentSlot, comment); 280 } 281 282 public void setTextSourceAnnotationComment(TextSource textSource, String comment) { 283 Instance textSourceInstance = getTextSourceInstance(textSource, true); 284 if (textSourceInstance != null) { 285 setTextSourceAnnotationComment(textSourceInstance, comment); 286 } 287 } 288 289 public void addTextSourceChangeListener(TextSourceChangeListener textSourceChangeListener) { 290 textSourceChangeListeners.add(textSourceChangeListener); 291 } 292 293 public void removeTextSourceChangeListener(TextSourceChangeListener textSourceChangeListener) { 294 textSourceChangeListeners.remove(textSourceChangeListener); 295 } 296 297 public TextSource getCurrentTextSource() { 298 return currentTextSource; 299 } 300 301 public void setCurrentTextSource(TextSource textSource) { 302 if (textSource != null) { 303 this.currentTextSource = textSource; 304 ProjectSettings.setRecentTextSourceCollectionIndex(project, currentTextSourceCollection 305 .getIndex(textSource)); 306 fireTextSourceChanged(textSource); 307 } 308 } 309 310 // invoke SwingWorker or something.... 311 void fireTextSourceChanged(TextSource textSource) { 312 TextSourceChangeEvent event = new TextSourceChangeEvent(textSource); 313 for (TextSourceChangeListener tscl : textSourceChangeListeners) { 314 tscl.textSourceChanged(event); 315 } 316 } 317 318 /** 319 * TextSourceCollection methods 320 */ 321 322 public void addTextSourceCollectionChangeListener( 323 TextSourceCollectionChangeListener textSourceCollectionChangeListener) { 324 textSourceCollectionChangeListeners.add(textSourceCollectionChangeListener); 325 } 326 327 public void removeTextSourceCollectionChangeListener( 328 TextSourceCollectionChangeListener textSourceCollectionChangeListener) { 329 textSourceCollectionChangeListeners.remove(textSourceCollectionChangeListener); 330 } 331 332 public TextSourceCollection getCurrentTextSourceCollection() { 333 return currentTextSourceCollection; 334 } 335 336 public void setCurrentTextSourceCollection(TextSourceCollection textSourceCollection) { 337 if (textSourceCollection != null) { 338 this.currentTextSourceCollection = textSourceCollection; 339 ProjectSettings.setRecentTextSourceCollection(project, textSourceCollection); 340 fireTextSourceCollectionChange(currentTextSourceCollection); 341 try { 342 setCurrentTextSource(textSourceCollection.get(0)); 343 } catch (TextSourceAccessException tsae) { 344 tsae.printStackTrace(); 345 } 346 } 347 } 348 349 // invoke SwingWorker or something.... 350 void fireTextSourceCollectionChange(TextSourceCollection textSourceCollection) { 351 TextSourceCollectionChangeEvent event = new TextSourceCollectionChangeEvent(textSourceCollection); 352 for (TextSourceCollectionChangeListener tsccl : textSourceCollectionChangeListeners) { 353 tsccl.textSourceCollectionChanged(event); 354 } 355 } 356 357 }