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.util.ArrayList;
032 import java.util.Collection;
033
034 import javax.swing.Action;
035 import javax.swing.JOptionPane;
036
037 import org.apache.log4j.Logger;
038
039 import edu.stanford.smi.protege.model.Cls;
040 import edu.stanford.smi.protege.model.Facet;
041 import edu.stanford.smi.protege.model.KnowledgeBase;
042 import edu.stanford.smi.protege.model.SimpleInstance;
043 import edu.stanford.smi.protege.model.Slot;
044 import edu.stanford.smi.protege.model.ValueType;
045 import edu.stanford.smi.protege.resource.ResourceKey;
046 import edu.stanford.smi.protege.util.AddAction;
047 import edu.stanford.smi.protege.util.AllowableAction;
048 import edu.stanford.smi.protege.util.CollectionUtilities;
049 import edu.stanford.smi.protege.util.RemoveAction;
050 import edu.stanford.smi.protege.widget.AbstractListWidget;
051 import edu.stanford.smi.protege.widget.ClsWidget;
052 import edu.stanford.smi.protege.widget.SlotWidget;
053
054 public class SlotMentionValueWidget extends AbstractListWidget {
055 static final long serialVersionUID = 0;
056
057 KnowtatorManager manager;
058
059 MentionUtil mentionUtil;
060
061 AnnotationUtil annotationUtil;
062
063 KnowtatorProjectUtil kpu;
064
065 private AllowableAction _addValueAction;
066
067 private AllowableAction _removeValueAction;
068
069 Logger logger = Logger.getLogger(SlotMentionValueWidget.class);
070
071 public void initialize() {
072 super.initialize();
073 addButton(getAddValueAction());
074 addButton(getRemoveValueAction());
075 manager = (KnowtatorManager) getKnowledgeBase().getClientInformation(Knowtator.KNOWTATOR_MANAGER);
076 mentionUtil = manager.getMentionUtil();
077 annotationUtil = manager.getAnnotationUtil();
078 kpu = manager.getKnowtatorProjectUtil();
079 }
080
081 public void setValues(Collection values) {
082 super.setValues(values);
083 SimpleInstance slotMention = (SimpleInstance) getInstance();
084 Slot mentionSlot = mentionUtil.getSlotMentionSlot(slotMention);
085
086 String slotLabel = null;
087 try {
088 SimpleInstance mentionedByMention = mentionUtil.getMentionedBy(slotMention);
089 Cls mentionCls = mentionUtil.getMentionCls(mentionedByMention);
090 ClsWidget clsWidget = getProject().getDesignTimeClsWidget(mentionCls);
091 SlotWidget slotWidget = clsWidget.getSlotWidget(mentionSlot);
092 slotLabel = slotWidget.getLabel();
093 } catch (Exception e) {
094 logger.debug("", e);
095 }
096
097 if (slotLabel != null)
098 getLabeledComponent().setHeaderLabel(slotLabel);
099 else
100 getLabeledComponent().setHeaderLabel(mentionSlot.getBrowserText());
101
102 }
103
104 protected Action getAddValueAction() {
105 _addValueAction = new AddAction(ResourceKey.VALUE_ADD) {
106 static final long serialVersionUID = 0;
107
108 public void onAdd() {
109 handleAddAction();
110 }
111 };
112 return _addValueAction;
113 }
114
115 String requestSymbolValue(Cls mentionCls, Slot mentionSlot) {
116 Object defaultValue = getDefaultValue(mentionCls, mentionSlot);
117
118 java.util.List values = new ArrayList();
119 values.addAll(mentionCls.getTemplateSlotAllowedValues(mentionSlot));
120 if (values.size() > 0) {
121 if (defaultValue == null)
122 defaultValue = values.get(0);
123
124 Object selection = JOptionPane.showInputDialog(this, "Select symbol", "Symbol selection",
125 JOptionPane.PLAIN_MESSAGE, null, values.toArray(), defaultValue);
126 if (selection != null)
127 return selection.toString();
128 }
129 return null;
130 }
131
132 Boolean requestBooleanValue(Cls mentionCls, Slot mentionSlot) {
133 Object defaultValue = getDefaultValue(mentionCls, mentionSlot);
134 if (defaultValue == null)
135 defaultValue = Boolean.TRUE;
136
137 java.util.List values = new ArrayList();
138 values.add(Boolean.TRUE);
139 values.add(Boolean.FALSE);
140 Object selection = JOptionPane.showInputDialog(this, "Select true or false", "Boolean selection",
141 JOptionPane.PLAIN_MESSAGE, null, values.toArray(), defaultValue);
142 if (selection != null) {
143 return (Boolean) selection;
144 }
145 return null;
146 }
147
148 String requestStringValue(Cls mentionCls, Slot mentionSlot) {
149 Object defaultValue = getDefaultValue(mentionCls, mentionSlot);
150 if (defaultValue == null)
151 defaultValue = "";
152
153 String stringValue = JOptionPane.showInputDialog(this, "Enter string value", defaultValue);
154 if (stringValue != null && stringValue.trim().length() > 0) {
155 return stringValue;
156 }
157 return null;
158 }
159
160 Integer requestIntegerValue(Cls mentionCls, Slot mentionSlot) {
161 Object defaultValue = getDefaultValue(mentionCls, mentionSlot);
162
163 String intValue = null;
164 if (defaultValue == null)
165 intValue = JOptionPane.showInputDialog(this, "Enter an integer value");
166 else
167 intValue = JOptionPane.showInputDialog(this, "Enter an integer value", defaultValue);
168
169 if (intValue == null || intValue.trim().equals(""))
170 return null;
171
172 String invalidErrorMessage = getInvalidIntegerDescription(intValue, mentionCls, mentionSlot);
173 if (invalidErrorMessage != null) {
174 JOptionPane
175 .showMessageDialog(this, invalidErrorMessage, "Invalid integer value", JOptionPane.ERROR_MESSAGE);
176 return null;
177 } else
178 return new Integer(intValue);
179 }
180
181 Float requestFloatValue(Cls mentionCls, Slot mentionSlot) {
182 Object defaultValue = getDefaultValue(mentionCls, mentionSlot);
183
184 String floatValue = null;
185 if (defaultValue == null)
186 floatValue = JOptionPane.showInputDialog(this, "Enter a number");
187 else
188 floatValue = JOptionPane.showInputDialog(this, "Enter a number", defaultValue);
189
190 if (floatValue == null || floatValue.trim().equals(""))
191 return null;
192
193 String invalidErrorMessage = getInvalidFloatDescription(floatValue, mentionCls, mentionSlot);
194 if (invalidErrorMessage != null) {
195 JOptionPane.showMessageDialog(this, invalidErrorMessage, "Invalid number", JOptionPane.ERROR_MESSAGE);
196 return null;
197 } else
198 return new Float(floatValue);
199 }
200
201 Object getDefaultValue(Cls mentionCls, Slot mentionSlot) {
202 Collection defaultValues = mentionCls.getTemplateSlotValues(mentionSlot);
203 if (defaultValues == null || defaultValues.size() == 0) {
204 defaultValues = mentionCls.getTemplateSlotDefaultValues(mentionSlot);
205 }
206 if (defaultValues != null && defaultValues.size() > 0)
207 return CollectionUtilities.getFirstItem(defaultValues);
208 return null;
209 }
210
211 private void showSlotMissingMessage() {
212 JOptionPane.showMessageDialog(this, "There is not a slot specified for this slot value.\n"
213 + "This is most likely a result of deleting a slot \n"
214 + "from the annotation schema after this annotation \n"
215 + "was created. Please remove this slot value, select\n"
216 + "another annotation, and re-select this annotation.", "Slot missing", JOptionPane.WARNING_MESSAGE);
217 }
218
219 private void showTypeMissingMessage(SimpleInstance mention) {
220 if (mentionUtil.isClassMention(mention))
221 JOptionPane.showMessageDialog(this, "There is no class assigned to this annotation.\n"
222 + "You may not add a value to this slot until a \n" + "class is assigned.", "No class assigned",
223 JOptionPane.WARNING_MESSAGE);
224 else if (mentionUtil.isInstanceMention(mention))
225 JOptionPane.showMessageDialog(this, "There is no instance assigned to this annotation.\n"
226 + "You may not add a value to this slot until an \n" + "instance is assigned.",
227 "No instance assigned", JOptionPane.WARNING_MESSAGE);
228
229 }
230
231 protected void handleAddAction() {
232 SimpleInstance slotMention = (SimpleInstance) getInstance();
233 Slot mentionSlot = mentionUtil.getSlotMentionSlot(slotMention);
234 if (mentionSlot == null) {
235 showSlotMissingMessage();
236 return;
237 }
238
239 SimpleInstance mentionedByMention = mentionUtil.getMentionedBy(slotMention);
240 Cls mentionCls = mentionUtil.getMentionCls(mentionedByMention);
241 if (mentionCls == null) {
242 showTypeMissingMessage(mentionedByMention);
243 return;
244 }
245
246 Object value = null;
247 ValueType type = mentionCls.getTemplateSlotValueType(mentionSlot);
248
249 if (type == ValueType.SYMBOL) {
250 value = requestSymbolValue(mentionCls, mentionSlot);
251 } else if (type == ValueType.BOOLEAN) {
252 value = requestBooleanValue(mentionCls, mentionSlot);
253 } else if (type == ValueType.STRING) {
254 value = requestStringValue(mentionCls, mentionSlot);
255 } else if (type == ValueType.INTEGER) {
256 value = requestIntegerValue(mentionCls, mentionSlot);
257 } else if (type == ValueType.FLOAT) {
258 value = requestFloatValue(mentionCls, mentionSlot);
259 } else if (type == ValueType.CLS || type == ValueType.INSTANCE) {
260 JOptionPane.showMessageDialog(this, "It appears that the value type constraint\n"
261 + "has changed since the slot values for this\n" + "slot were entered.\n"
262 + "Please remove the slot values for this slot,\n"
263 + "select a different annotation, and re-select\n " + "the currently selected annotation.",
264 "value type constraint inconsistency", JOptionPane.WARNING_MESSAGE);
265 } else {
266 JOptionPane.showMessageDialog(this, "this type is not handled yet!");
267 }
268 if (value != null)
269 addItem(value);
270
271 /**
272 * "enforces" maximum cardinality constraint. Assumes that the values
273 * will be ordered as they appear in the widget (oldest to newest
274 * additions)
275 */
276 int maxCardinality = mentionCls.getTemplateSlotMaximumCardinality(mentionSlot);
277 if (maxCardinality > 0) {
278 ArrayList values = new ArrayList(getValues());
279 removeAllItems();
280 for (int i = values.size() - 1, j = 0; i >= 0 && j < maxCardinality; i--) {
281 addItem(values.get(i));
282 j++;
283 }
284 }
285
286 // now we need to check if the values are valid (and in setValues)
287 // if the values are not valid we can call
288 // AbstractSlotWidget.setInvalidValueBorder
289 // if they are fine, then call AbstractSlotWidget.setNormalBorder
290 }
291
292 /**
293 * The code for this method was copied from
294 * edu.stanford.smi.protege.widget.IntegerFieldWidget and modified slightly
295 */
296
297 protected String getInvalidIntegerDescription(String text, Cls mentionCls, Slot mentionSlot) {
298 String result = null;
299 try {
300 int i = new Integer(text).intValue();
301 Number min = mentionCls.getTemplateSlotMinimumValue(mentionSlot);
302 if (min != null && i < min.intValue()) {
303 result = "The minimum value is " + min;
304 }
305 Number max = mentionCls.getTemplateSlotMaximumValue(mentionSlot);
306 if (max != null && i > max.intValue()) {
307 result = "The maximum value is " + max;
308 }
309 } catch (NumberFormatException e) {
310 result = "The value must be an integer";
311 }
312 return result;
313 }
314
315 /**
316 * The code for this method was copied from
317 * edu.stanford.smi.protege.widget.FloatFieldWidget and modified slightly
318 */
319
320 protected String getInvalidFloatDescription(String text, Cls mentionCls, Slot mentionSlot) {
321 String result = null;
322 try {
323 float f = Float.parseFloat(text);
324 Number min = mentionCls.getTemplateSlotMinimumValue(mentionSlot);
325 if (min != null && f < min.floatValue()) {
326 result = "The minimum value is " + min;
327 }
328 Number max = mentionCls.getTemplateSlotMaximumValue(mentionSlot);
329 if (max != null && f > max.floatValue()) {
330 result = "The maximum value is " + max;
331 }
332 } catch (NumberFormatException e) {
333 result = "The value must be a number";
334 }
335 return result;
336 }
337
338 protected Action getRemoveValueAction() {
339 _removeValueAction = new RemoveAction(ResourceKey.VALUE_REMOVE, this) {
340 public void onRemove(Collection values) {
341 handleRemoveAction(values);
342 }
343 };
344 return _removeValueAction;
345 }
346
347 protected void handleRemoveAction(Collection values) {
348 removeItems(values);
349 }
350
351 public static boolean isSuitable(Cls cls, Slot slot, Facet facet) {
352 KnowledgeBase kb = slot.getKnowledgeBase();
353 Cls complexSlotMentionCls = kb.getCls(KnowtatorProjectUtil.COMPLEX_SLOT_MENTION_CLS_NAME);
354 Slot mentionSlotValueSlot = kb.getSlot(KnowtatorProjectUtil.MENTION_SLOT_VALUE_SLOT_NAME);
355 if (!cls.equals(complexSlotMentionCls) && mentionSlotValueSlot.equals(slot))
356 return true;
357 return false;
358 }
359
360 public void setEditable(boolean b) {
361 setAllowed(_addValueAction, b);
362 }
363
364 }