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 package edu.uchsc.ccp.knowtator.wizards; 029 030 import java.awt.BorderLayout; 031 import java.awt.Dimension; 032 import java.awt.GridBagConstraints; 033 import java.awt.GridBagLayout; 034 import java.awt.Insets; 035 import java.awt.Point; 036 import java.awt.event.ActionEvent; 037 import java.awt.event.ActionListener; 038 import java.util.Collection; 039 import java.util.HashSet; 040 import java.util.Set; 041 import java.util.TreeSet; 042 043 import javax.swing.JButton; 044 import javax.swing.JFrame; 045 import javax.swing.JLabel; 046 import javax.swing.JList; 047 import javax.swing.JOptionPane; 048 import javax.swing.JScrollPane; 049 import javax.swing.JTextArea; 050 import javax.swing.JTextField; 051 import javax.swing.event.CaretEvent; 052 import javax.swing.event.CaretListener; 053 054 import edu.stanford.smi.protege.model.SimpleInstance; 055 import edu.stanford.smi.protege.ui.DisplayUtilities; 056 import edu.stanford.smi.protege.ui.FrameRenderer; 057 import edu.stanford.smi.protege.util.CollectionUtilities; 058 import edu.uchsc.ccp.knowtator.FilterUtil; 059 import edu.uchsc.ccp.knowtator.KnowtatorManager; 060 061 public class CreateConsensusSetWizard implements ActionListener { 062 063 public static final String WELCOME_MESSAGE = "This wizard allows you to create a consensus set from existing, merged annotations. " 064 + "Typically, text sources will be individually annotated in separate projects and then " 065 + "merged together into a single project at which point consensus mode is used. " 066 + "This action will not delete or modify existing annotations. A consensus set " 067 + "consists of annotations that have been copied from the set of annotations " 068 + "defined by the filter that you will choose in this wizard. Consensus mode will then act on these " 069 + "copied annotations. For more information about " 070 + "how consensus mode works please consult the online documentation. http://knowtator.sourceforge.net//consensus.shtml"; 071 072 public static final String FILTER_INSTRUCTIONS = "Please select a filter that describes the set of annotations that you want to create a consensus " 073 + "set for. The selected filter must have either two annotators or two annotation sets specified. If you " 074 + "have not yet defined an appropriate filter, then please exit out of this wizard and create one. Please see" 075 + "http://knowtator.sourceforge.net//filters.shtml for information about filters."; 076 077 public static final String NAME_INSTRUCTIONS = "Please enter a descriptive name for your consensus set. If you plan to have " 078 + "only one consensus set in your annotation project, then selecting " + "the default name should be fine."; 079 080 public static final String TEXT_SOURCES_INSTRUCTIONS = "Please select the text sources that you want included in the consensus set creation."; 081 082 public static final String TO_WELCOME_FRAME = "TO_WELCOME_FRAME"; 083 084 public static final String TO_NAME_FRAME = "TO_NAME_FRAME"; 085 086 public static final String TO_FILTER_FRAME = "TO_FILTER_FRAME"; 087 088 public static final String TO_TEXTSOURCES_FRAME = "TO_TEXTSOURCES_FRAME"; 089 090 public static final String CREATE_BUTTON_CLICKED = "CREATE_BUTTON_CLICKED"; 091 092 SimpleInstance filter; 093 094 String consensusSetName = "consensus set"; 095 096 Set<SimpleInstance> textSources; 097 098 boolean createClicked = false; 099 100 WizardFrame welcomeFrame; 101 102 JTextArea welcomeMessageTextArea; 103 104 WizardFrame nameFrame; 105 106 JTextArea nameInstructionsTextArea; 107 108 JLabel nameLabel; 109 110 JTextField nameTextField; 111 112 WizardFrame filterFrame; 113 114 JTextArea filterInstructionsTextArea; 115 116 JLabel filterLabel; 117 118 JTextField filterTextField; 119 120 JButton filterButton; 121 122 WizardFrame textSourcesFrame; 123 124 JTextArea textSourcesInstructionsTextArea; 125 126 JLabel textSourcesLabel; 127 128 JList textSourcesList; 129 130 JButton textSourcesRemoveButton; 131 132 JButton textSourcesAddButton; 133 134 WizardFrame visibleFrame; // one of the above frames 135 136 JFrame parent; 137 138 Dimension wizardSize; 139 140 Point wizardLocation; 141 142 KnowtatorManager manager; 143 144 public CreateConsensusSetWizard(JFrame parent, KnowtatorManager manager) { 145 this.parent = parent; 146 this.manager = manager; 147 148 textSources = new TreeSet<SimpleInstance>(); 149 150 createWelcomeFrame(); 151 createConsensusNameFrame(); 152 createFilterFrame(); 153 createTextSourcesFrame(); 154 } 155 156 private void createWelcomeFrame() { 157 welcomeFrame = new WizardFrame(parent, "consensus set creation wizard", new Dimension(500, 400)); 158 welcomeFrame.setAlwaysOnTop(false); 159 welcomeFrame.previousButton.setEnabled(false); 160 welcomeFrame.nextButton.setActionCommand(TO_NAME_FRAME); 161 welcomeFrame.nextButton.addActionListener(this); 162 welcomeFrame.cancelButton.addActionListener(this); 163 welcomeFrame.contentPane.setLayout(new BorderLayout()); 164 welcomeFrame.setLocation(WizardUtil.getCentralDialogLocation(parent, welcomeFrame)); 165 166 welcomeMessageTextArea = new JTextArea(); 167 welcomeMessageTextArea.setEditable(false); 168 welcomeMessageTextArea.setText(WELCOME_MESSAGE); 169 welcomeMessageTextArea.setLineWrap(true); 170 welcomeMessageTextArea.setWrapStyleWord(true); 171 welcomeFrame.contentPane.add(welcomeMessageTextArea, BorderLayout.CENTER); 172 } 173 174 private void createConsensusNameFrame() { 175 nameFrame = new WizardFrame(parent, "enter a name"); 176 nameFrame.setAlwaysOnTop(false); 177 nameFrame.previousButton.setActionCommand(TO_WELCOME_FRAME); 178 nameFrame.previousButton.addActionListener(this); 179 nameFrame.nextButton.setActionCommand(TO_FILTER_FRAME); 180 nameFrame.nextButton.addActionListener(this); 181 nameFrame.cancelButton.addActionListener(this); 182 183 nameInstructionsTextArea = new JTextArea(); 184 nameInstructionsTextArea.setEditable(false); 185 nameInstructionsTextArea.setText(NAME_INSTRUCTIONS); 186 nameInstructionsTextArea.setLineWrap(true); 187 nameInstructionsTextArea.setWrapStyleWord(true); 188 189 nameLabel = new JLabel("consensus set name "); 190 191 nameTextField = new JTextField(consensusSetName); 192 nameTextField.addCaretListener(new CaretListener() { 193 public void caretUpdate(CaretEvent e) { 194 String name = nameTextField.getText(); 195 if (name == null || name.trim().equals("")) { 196 nameFrame.nextButton.setEnabled(false); 197 } else 198 nameFrame.nextButton.setEnabled(true); 199 consensusSetName = name; 200 } 201 }); 202 203 nameFrame.contentPane.setLayout(new GridBagLayout()); 204 nameFrame.contentPane.add(nameInstructionsTextArea, new GridBagConstraints(0, 0, 2, 1, 1.0d, 1.0d, 205 GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 2, 2)); 206 nameFrame.contentPane.add(nameLabel, new GridBagConstraints(0, 1, 1, 1, 0d, 0d, GridBagConstraints.EAST, 207 GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 2, 2)); 208 nameFrame.contentPane.add(nameTextField, new GridBagConstraints(1, 1, 1, 1, 1.0d, 0d, GridBagConstraints.WEST, 209 GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 2, 2)); 210 } 211 212 private void createFilterFrame() { 213 filterFrame = new WizardFrame(parent, "select annotation filter"); 214 filterFrame.setAlwaysOnTop(false); 215 filterFrame.previousButton.setActionCommand(TO_NAME_FRAME); 216 filterFrame.previousButton.addActionListener(this); 217 filterFrame.nextButton.setActionCommand(TO_TEXTSOURCES_FRAME); 218 filterFrame.nextButton.addActionListener(this); 219 filterFrame.nextButton.setEnabled(false); 220 filterFrame.cancelButton.addActionListener(this); 221 222 filterInstructionsTextArea = new JTextArea(); 223 filterInstructionsTextArea.setEditable(false); 224 filterInstructionsTextArea.setText(FILTER_INSTRUCTIONS); 225 filterInstructionsTextArea.setLineWrap(true); 226 filterInstructionsTextArea.setWrapStyleWord(true); 227 228 filterLabel = new JLabel("selected filter"); 229 filterTextField = new JTextField(); 230 filterTextField.setEditable(false); 231 filterButton = new JButton("select filter"); 232 filterButton.addActionListener(this); 233 234 filterFrame.contentPane.setLayout(new GridBagLayout()); 235 filterFrame.contentPane.add(filterInstructionsTextArea, new GridBagConstraints(0, 0, 3, 1, 1.0d, 1.0d, 236 GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 2, 2)); 237 filterFrame.contentPane.add(filterLabel, new GridBagConstraints(0, 1, 1, 1, 0d, 0d, GridBagConstraints.EAST, 238 GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 2, 2)); 239 filterFrame.contentPane.add(filterTextField, new GridBagConstraints(1, 1, 1, 1, 1.0d, 0d, 240 GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 2, 2)); 241 filterFrame.contentPane.add(filterButton, new GridBagConstraints(2, 1, 1, 1, 0d, 0d, GridBagConstraints.WEST, 242 GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 2, 2)); 243 } 244 245 private void createTextSourcesFrame() { 246 textSourcesFrame = new WizardFrame(parent, "select text sources"); 247 textSourcesFrame.setAlwaysOnTop(false); 248 textSourcesFrame.previousButton.setActionCommand(TO_FILTER_FRAME); 249 textSourcesFrame.previousButton.addActionListener(this); 250 textSourcesFrame.nextButton.setText("create"); 251 textSourcesFrame.nextButton.setActionCommand(CREATE_BUTTON_CLICKED); 252 textSourcesFrame.nextButton.addActionListener(this); 253 textSourcesFrame.nextButton.setEnabled(false); 254 textSourcesFrame.cancelButton.addActionListener(this); 255 256 textSourcesInstructionsTextArea = new JTextArea(); 257 textSourcesInstructionsTextArea.setEditable(false); 258 textSourcesInstructionsTextArea.setText(TEXT_SOURCES_INSTRUCTIONS); 259 textSourcesInstructionsTextArea.setLineWrap(true); 260 textSourcesInstructionsTextArea.setWrapStyleWord(true); 261 262 textSourcesLabel = new JLabel("Selected text sources"); 263 264 textSourcesList = new JList(); 265 textSourcesList.setCellRenderer(new FrameRenderer()); 266 JScrollPane scrollPane = new JScrollPane(textSourcesList); 267 268 textSourcesAddButton = new JButton("Add"); 269 textSourcesAddButton.addActionListener(this); 270 textSourcesRemoveButton = new JButton("Remove"); 271 textSourcesRemoveButton.addActionListener(this); 272 273 textSourcesFrame.contentPane.setLayout(new GridBagLayout()); 274 textSourcesFrame.contentPane.add(textSourcesInstructionsTextArea, new GridBagConstraints(0, 0, 2, 1, 0d, 0d, 275 GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 2, 2)); 276 textSourcesFrame.contentPane.add(textSourcesLabel, new GridBagConstraints(0, 1, 2, 1, 0d, 0d, 277 GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 2, 2)); 278 textSourcesFrame.contentPane.add(scrollPane, new GridBagConstraints(0, 2, 2, 1, 1.0d, 1.0d, 279 GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 2, 2)); 280 textSourcesFrame.contentPane.add(textSourcesAddButton, new GridBagConstraints(0, 3, 1, 1, 0d, 0d, 281 GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 2, 2)); 282 textSourcesFrame.contentPane.add(textSourcesRemoveButton, new GridBagConstraints(1, 3, 1, 1, 0d, 0d, 283 GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 2, 2)); 284 } 285 286 private void chooseFilter() { 287 SimpleInstance chosenFilter = (SimpleInstance) DisplayUtilities.pickInstance(filterFrame, CollectionUtilities 288 .createCollection(manager.getKnowtatorProjectUtil().getFilterCls()), "Select annotation filter"); 289 290 if (chosenFilter == null) 291 return; 292 Set<SimpleInstance> annotators = new HashSet<SimpleInstance>(FilterUtil.getAnnotators(chosenFilter)); 293 Set<SimpleInstance> sets = FilterUtil.getSets(chosenFilter); 294 if (annotators.size() < 2 && sets.size() < 2) { 295 JOptionPane.showMessageDialog(filterFrame, 296 "The selected filter must have either two annotators or two annotation sets specified.", 297 "Incomplete annotation filter", JOptionPane.ERROR_MESSAGE); 298 return; 299 } 300 301 filter = chosenFilter; 302 filterFrame.nextButton.setEnabled(true); 303 filterTextField.setText(filter.getBrowserText()); 304 } 305 306 private void addTextSources(Collection addedTextSources) { 307 if (addedTextSources != null && addedTextSources.size() > 0) { 308 for (Object addedTextSource : addedTextSources) { 309 textSources.add((SimpleInstance) addedTextSource); 310 } 311 textSourcesList.setListData(textSources.toArray()); 312 } 313 if (textSources.size() > 0) 314 textSourcesFrame.nextButton.setEnabled(true); 315 } 316 317 private void chooseTextSources() { 318 Collection textSources = DisplayUtilities.pickInstances(textSourcesFrame, manager.getKnowledgeBase(), 319 CollectionUtilities.createCollection(manager.getKnowtatorProjectUtil().getTextSourceCls()), 320 "select text sources"); 321 addTextSources(textSources); 322 } 323 324 private void removeTextSources() { 325 Object[] selectedValues = textSourcesList.getSelectedValues(); 326 for (Object selectedValue : selectedValues) { 327 textSources.remove(selectedValue); 328 } 329 textSourcesList.setListData(textSources.toArray()); 330 if (textSources.size() == 0) 331 textSourcesFrame.nextButton.setEnabled(false); 332 } 333 334 public void actionPerformed(ActionEvent actionEvent) { 335 String command = actionEvent.getActionCommand(); 336 Object source = actionEvent.getSource(); 337 if (command.equals(TO_WELCOME_FRAME)) { 338 showFrame(welcomeFrame); 339 } else if (command.equals(TO_NAME_FRAME)) { 340 showFrame(nameFrame); 341 } else if (command.equals(TO_FILTER_FRAME)) { 342 showFrame(filterFrame); 343 } else if (command.equals(TO_TEXTSOURCES_FRAME)) { 344 showFrame(textSourcesFrame); 345 } else if (command.equals("CANCEL")) { 346 setVisible(false); 347 } else if (source == filterButton) { 348 chooseFilter(); 349 } else if (source == textSourcesAddButton) { 350 chooseTextSources(); 351 } else if (source == textSourcesRemoveButton) { 352 removeTextSources(); 353 } else if (command.equals(CREATE_BUTTON_CLICKED)) { 354 createClicked = true; 355 setVisible(false); 356 } 357 } 358 359 public void setVisible(boolean visible) { 360 if (visible) { 361 createClicked = false; 362 showFrame(welcomeFrame); 363 } else { 364 welcomeFrame.setVisible(false); 365 nameFrame.setVisible(false); 366 filterFrame.setVisible(false); 367 textSourcesFrame.setVisible(false); 368 } 369 } 370 371 public void showFrame(WizardFrame wizardFrame) { 372 if (visibleFrame != null) { 373 wizardSize = visibleFrame.getSize(); 374 wizardLocation = visibleFrame.getLocation(); 375 wizardFrame.setSize(wizardSize); 376 wizardFrame.setLocation(wizardLocation); 377 } 378 visibleFrame = wizardFrame; 379 setVisible(false); 380 visibleFrame.setVisible(true); 381 } 382 383 public boolean createConsensusSet() { 384 return createClicked; 385 } 386 387 public SimpleInstance getFilter() { 388 return filter; 389 } 390 391 public Set<SimpleInstance> getTextSources() { 392 return textSources; 393 } 394 395 public String getConsensusSetName() { 396 return consensusSetName; 397 } 398 }