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 }