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 }