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 }