001/** 002 * Copyright (c) 2007-2008, Regents of the University of Colorado 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions are met: 007 * 008 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 009 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 010 * Neither the name of the University of Colorado at Boulder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 011 * 012 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 013 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 014 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 015 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 016 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 017 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 018 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 019 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 020 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 021 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 022 * POSSIBILITY OF SUCH DAMAGE. 023 */ 024package org.cleartk.corpus.timeml; 025 026import java.util.ArrayList; 027import java.util.HashMap; 028import java.util.List; 029import java.util.Map; 030 031import org.apache.uima.cas.Feature; 032import org.apache.uima.cas.text.AnnotationFS; 033import org.apache.uima.jcas.JCas; 034import org.apache.uima.jcas.tcas.Annotation; 035import org.cleartk.timeml.type.Anchor; 036import org.cleartk.timeml.type.DocumentCreationTime; 037import org.cleartk.timeml.type.Event; 038import org.cleartk.timeml.type.TemporalLink; 039import org.cleartk.timeml.type.Time; 040import org.jdom2.Element; 041import org.xml.sax.Attributes; 042import org.xml.sax.helpers.AttributesImpl; 043 044/** 045 * <br> 046 * Copyright (c) 2007-2008, Regents of the University of Colorado <br> 047 * All rights reserved. 048 * 049 * 050 * @author Steven Bethard 051 * 052 */ 053public class TimeMlUtil { 054 055 private static final Map<String, String> elementNames; 056 057 private static final List<NamePair> eventAttributes; 058 059 private static final List<NamePair> timeAttributes; 060 061 private static final List<NamePair> tlinkAttributes; 062 063 private static final Map<String, List<NamePair>> timemlAttributeLists; 064 065 private static final Map<Class<?>, List<NamePair>> uimaAttributeLists; 066 067 static { 068 elementNames = new HashMap<String, String>(); 069 eventAttributes = new ArrayList<NamePair>(); 070 timeAttributes = new ArrayList<NamePair>(); 071 tlinkAttributes = new ArrayList<NamePair>(); 072 timemlAttributeLists = new HashMap<String, List<NamePair>>(); 073 uimaAttributeLists = new HashMap<Class<?>, List<NamePair>>(); 074 075 elementNames.put("Document", "TimeML"); 076 elementNames.put(Event.class.getName(), "EVENT"); 077 elementNames.put(Time.class.getName(), "TIMEX3"); 078 elementNames.put(DocumentCreationTime.class.getName(), "TIMEX3"); 079 elementNames.put(TemporalLink.class.getName(), "TLINK"); 080 081 eventAttributes.add(new NamePair("eid", "id")); 082 eventAttributes.add(new NamePair("eiid", "eventInstanceID")); 083 eventAttributes.add(new NamePair("class", "eventClass")); 084 for (String name : new String[] { 085 "stem", 086 "pos", 087 "tense", 088 "aspect", 089 "cardinality", 090 "polarity", 091 "modality", 092 "signalID" }) { 093 eventAttributes.add(new NamePair(name, name)); 094 } 095 096 timeAttributes.add(new NamePair("tid", "id")); 097 timeAttributes.add(new NamePair("type", "timeType")); 098 for (String name : new String[] { 099 "beginPoint", 100 "endPoint", 101 "quant", 102 "freq", 103 "functionInDocument", 104 "temporalFunction", 105 "value", 106 "valueFromFunction", 107 "mod" }) { 108 timeAttributes.add(new NamePair(name, name)); 109 } 110 111 tlinkAttributes.add(new NamePair("lid", "id")); 112 tlinkAttributes.add(new NamePair("relType", "relationType")); 113 tlinkAttributes.add(new NamePair("signalID", "signalID")); 114 115 timemlAttributeLists.put("EVENT", eventAttributes); 116 timemlAttributeLists.put("MAKEINSTANCE", eventAttributes); 117 timemlAttributeLists.put("TIMEX3", timeAttributes); 118 timemlAttributeLists.put("TLINK", tlinkAttributes); 119 120 uimaAttributeLists.put(Event.class, eventAttributes); 121 uimaAttributeLists.put(Time.class, timeAttributes); 122 uimaAttributeLists.put(TemporalLink.class, tlinkAttributes); 123 } 124 125 public static void copyAttributes(Element element, Annotation annotation, JCas jCas) { 126 for (NamePair names : timemlAttributeLists.get(element.getName().toUpperCase())) { 127 String featureValue = element.getAttributeValue(names.timemlName); 128 if (featureValue != null) { 129 String className = annotation.getClass().getName(); 130 String uimaName = String.format("%s:%s", className, names.uimaName); 131 Feature feature = jCas.getTypeSystem().getFeatureByFullName(uimaName); 132 annotation.setFeatureValueFromString(feature, featureValue); 133 } 134 } 135 } 136 137 public static void removeInconsistentAttributes(Element element, Annotation annotation, JCas jCas) { 138 for (NamePair names : timemlAttributeLists.get(element.getName().toUpperCase())) { 139 String newValue = element.getAttributeValue(names.timemlName); 140 String className = annotation.getClass().getName(); 141 String uimaName = String.format("%s:%s", className, names.uimaName); 142 Feature feature = jCas.getTypeSystem().getFeatureByFullName(uimaName); 143 String oldValue = annotation.getFeatureValueAsString(feature); 144 if (oldValue != null && !oldValue.equals(newValue)) { 145 annotation.setFeatureValueFromString(feature, null); 146 } 147 } 148 } 149 150 public static String toTimeMLElementName(AnnotationFS annotation) { 151 if (annotation instanceof Event) { 152 return "EVENT"; 153 } else if (annotation instanceof Time) { 154 return "TIMEX3"; 155 } else if (annotation instanceof TemporalLink) { 156 return "TLINK"; 157 } else { 158 return null; 159 } 160 } 161 162 public static Attributes toTimeMLAttributes(AnnotationFS annotation, String elementName) { 163 // add attributes that have a simple one-to-one mapping 164 AttributesImpl attributes = new AttributesImpl(); 165 for (NamePair names : timemlAttributeLists.get(elementName)) { 166 Feature feature = annotation.getType().getFeatureByBaseName(names.uimaName); 167 addAttribute(attributes, names.timemlName, annotation.getFeatureValueAsString(feature)); 168 } 169 // add un-mappable attributes 170 if (annotation instanceof TemporalLink) { 171 TemporalLink tlink = (TemporalLink) annotation; 172 Anchor source = tlink.getSource(); 173 Anchor target = tlink.getTarget(); 174 if (source instanceof Event) { 175 Event event = (Event) source; 176 addAttribute(attributes, "eventID", event.getId()); 177 addAttribute(attributes, "eventInstanceID", event.getEventInstanceID()); 178 } else if (source instanceof Time) { 179 addAttribute(attributes, "timeID", source.getId()); 180 } 181 if (target instanceof Event) { 182 Event event = (Event) target; 183 addAttribute(attributes, "relatedToEvent", event.getId()); 184 addAttribute(attributes, "relatedToEventInstance", event.getEventInstanceID()); 185 } else if (target instanceof Time) { 186 addAttribute(attributes, "relatedToTime", target.getId()); 187 } 188 } 189 return attributes; 190 } 191 192 public static Attributes toTempEval2007Attributes(AnnotationFS annotation, String elementName) { 193 // add attributes that have a simple one-to-one mapping 194 AttributesImpl attributes = new AttributesImpl(); 195 for (NamePair names : timemlAttributeLists.get(elementName)) { 196 if (!names.timemlName.equals("eiid")) { 197 Feature feature = annotation.getType().getFeatureByBaseName(names.uimaName); 198 addAttribute(attributes, names.timemlName, annotation.getFeatureValueAsString(feature)); 199 } 200 } 201 // add un-mappable attributes 202 if (annotation instanceof TemporalLink) { 203 TemporalLink tlink = (TemporalLink) annotation; 204 Anchor source = tlink.getSource(); 205 Anchor target = tlink.getTarget(); 206 if (source instanceof Event) { 207 Event event = (Event) source; 208 addAttribute(attributes, "eventID", event.getId()); 209 } else if (source instanceof Time) { 210 addAttribute(attributes, "timeID", source.getId()); 211 } 212 if (target instanceof Event) { 213 Event event = (Event) target; 214 addAttribute(attributes, "relatedToEvent", event.getId()); 215 } else if (target instanceof Time) { 216 addAttribute(attributes, "relatedToTime", target.getId()); 217 } 218 } 219 return attributes; 220 } 221 222 private static void addAttribute(AttributesImpl attributes, String name, String value) { 223 if (value != null) { 224 attributes.addAttribute("", name, name, "CDATA", value); 225 } 226 } 227 228 private static class NamePair { 229 public String timemlName; 230 231 public String uimaName; 232 233 public NamePair(String timemlName, String uimaName) { 234 this.timemlName = timemlName; 235 this.uimaName = uimaName; 236 } 237 } 238}