package info.ephyra.answerselection.definitional; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Properties; /** * A <code>Dossier</code> specifies different properties of a target (such as a * person or an event). These properties depend on the target type. For * instance, a person has a property 'nationality', whereas an event has a * property 'date'. * * @author Guido Sautter * @version 2008-02-10 */ public class Dossier { protected String target; protected String targetType; private String[] propertyNames = new String[0]; private Properties properties = new Properties(); /** * @param target the target String * @param targetType the type of the target */ public Dossier(String target, String targetType) { this.target = target; this.targetType = targetType; this.propertyNames = getPropertiesForTargetType(this.targetType); } /** * @return the target. */ public String getTarget() { return this.target; } /** * @return the targetType. */ public String getTargetType() { return this.targetType; } /** set a property of the target to a given value * @param property the name of the property * @param value the value of the property */ public void setProperty(String property, String value) { this.properties.setProperty(property, value); } /** retrieve the value of a property * @param property the name of the property * @return the value associated with the specified property, or null, if there is no such value */ public String getProperty(String property) { return this.properties.getProperty(property); } /** check if this dossier already contains a value for some property * @param property the name of the property to check * @return true iff this dossier has a value associated with the specified property */ public boolean isPropertySet(String property) { return this.properties.containsKey(property); } /** @return the names of the properties contained in this dossier (regardless if they already have a value associated with them or not) */ public String[] getPropertyNames() { return this.propertyNames; } /** @return the names of the properties in this dossier that do not yet have a value associated with them */ public String[] getMissingPropertyNames() { ArrayList<String> list = new ArrayList<String>(); for (int n = 0; n < this.propertyNames.length; n++) if (!this.properties.containsKey(this.propertyNames[n])) list.add(this.propertyNames[n]); return list.toArray(new String[list.size()]); } /** retrieve the names of the properties interesting for some given type of target * @param targetType the target type * @return an array containing the names of the properties interesting for a target of the specified type */ protected static String[] getPropertiesForTargetType(String targetType) { String[] props = targetTypeProperties.get(targetType); return (props == null) ? new String[0] : props; } /** determine the type of a target, using properties as evidence * @param givenProperties the names of the properties already known * @return the type of target that is most likely to ahe the specified properties */ public static String getTargetType(String[] givenProperties) { // determine type making use of the properties already known String[] types = targetTypes.toArray(new String[targetTypes.size()]); String[][] typeProps = new String[types.length][]; for (int t = 0; t < types.length; t++) typeProps[t] = getPropertiesForTargetType(types[t]); int[] scores = new int[types.length]; for (int i = 0; i < scores.length; i++) scores[i] = 0; HashSet<String> propSet = new HashSet<String>(); for (int p = 0; p < givenProperties.length; p++) propSet.add(givenProperties[p].toLowerCase()); for (int t = 0; t < types.length; t++) for (int p = 0; p < typeProps[t].length; p++) if (propSet.contains(typeProps[t][p].toLowerCase())) scores[t]++; int max = 0; int typeIndex = 0; for (int t = 0; t < types.length; t++) { if (scores[t] > max) { max = scores[t]; typeIndex = t; } } // FACTOID questions could probably not be interpreted (no properties given), often happens with somewhat wired questions on events if (max == 0) return EVENT; // return type most likely to have given properties return types[typeIndex]; } /** produce a dossier * @param target the target string * @param targetType the target type (if set to null, the target type will be determined automatically from the given properties) * @param givenProperties the properties of the target that are properties already known * @param givenValues the values associated with the known properties * @return dossier */ public static Dossier getDossier(String target, String targetType, String[] givenProperties, String[] givenValues) { String type = ((targetType == null) ? getTargetType(givenProperties) : targetType); Dossier dossier = new Dossier(target, type); for (int p = 0; p < givenProperties.length; p++) dossier.setProperty(givenProperties[p], givenValues[p]); return dossier; } /** register an additional type of target (hard coded are PERSON, ORGANIZATION, EVENT, ENTERTAINMENT and THING) * @param targetType the name for the new target type * @param properties the properties that are of interes with regard to the new target type */ public static void addTargetType(String targetType, String[] properties) { if (targetTypeProperties.containsKey(targetType)) { HashSet<String> propSet = new HashSet<String>(); String[] props = targetTypeProperties.get(targetType); for (int p = 0; p < props.length; p++) propSet.add(props[p]); for (int p = 0; p < properties.length; p++) propSet.add(properties[p]); props = propSet.toArray(new String[propSet.size()]); targetTypeProperties.put(targetType, props); } else { targetTypes.add(targetType); targetTypeProperties.put(targetType, properties); } } /** add a property to some existing target type * @param targetType the target type * @param property the new property to be associated with the specified target type */ public static void addTargetTypeProperty(String targetType, String property) { String[] props = targetTypeProperties.get(targetType); if (props != null) { HashSet<String> propSet = new HashSet<String>(); for (int p = 0; p < props.length; p++) propSet.add(props[p]); propSet.add(property); props = propSet.toArray(new String[propSet.size()]); targetTypeProperties.put(targetType, props); } } private static ArrayList<String> targetTypes = new ArrayList<String>(); private static HashMap<String, String[]> targetTypeProperties = new HashMap<String, String[]>(); public static final String PERSON = "PERSON"; public static final String ORGANIZATION = "ORGANIZATION"; public static final String EVENT = "EVENT"; public static final String THING = "THING"; public static final String ENTERTAINMENT = "ENTERTAINMENT"; private static final String[] PERSON_PROPERTIES = { "AGE", "ANCESTOR", "CAUSEOFDEATH", "DATEOFBIRTH", "DATEOFDEATH", "DATEOFLIVING", "DATEOFMARRIAGE", "FOOD", "HABITAT", "HEIGHT", "IDENTITY", "INCOME", "KILLER", "LANGUAGE", "LIFESPAN", "NAME", "NATIONALITY", "PLACEOFBIRTH", "PLACEOFDEATH", "PLACEOFLIVING", "PROFESSION", "SIZE", "SPECIALTY" }; private static final String[] ORGANIZATION_PROPERTIES = { "ABBREVIATION", // "ACTOR", "AGE", "DATEOFFOUNDATION", "DATEOFSTARTOFOPERATION", "FOUNDER", "FUNCTION", "HABITAT", "INCOME", "LANGUAGE", "LEADER", "LONGFORM", "NAME", "NATIONALITY", "OWNER", "PLACEOFORIGIN", "SPECIALTY", "SYNONYM", "VALUE" }; private static final String[] EVENT_PROPERTIES = { // "ABBREVIATION", "ACTOR", // "AGE", "CAUSE", "CONSEQUENCE", "DATE", // "DATEOFCREATION", // "DATEOFEND", // "DATEOFSTART", // "DURATION", // "HABITAT", // "LANGUAGE", // "NAME", "PLACE", // "SYNONYM", // "VALUE", // "WINNER" }; private static final String[] THING_PROPERTIES = { "ABBREVIATION", "AGE", "AUTHOR", "BUILDER", "CAPITAL", "DATEOFCREATION", "DATEOFINVENTION", "DATEOFSTARTOFOPERATION", "DEFINITION", "DISCOVERER", "DISCOVERY", "DISTANCE", "EXAMPLE", "FOOD", "FUNCTION", "HEIGHT", "INSTRUMENT", "INVENTOR", "MEDICINE", "NAME", "OWNER", "PLACEOFOCCURRENCE", "PLACEOFORIGIN", "POPULATION", "PROVIDER", "RESOURCE", "SIZE", "SPECIES", "SPEED", "SYMPTOM", "SYNONYM", "TEMPERATURE", "VALUE", "WIDTH" }; private static final String[] ENTERTAINMENT_PROPERTIES = { "ACTOR", "AGE", "AUTHOR", "DATEOFCREATION", "DATEOFEND", "DATEOFSTART", "DURATION", "EXAMPLE", "INSTRUMENT", "LANGUAGE", "MOVIE", "NAME", "OWNER", "PLACE", "PLACEOFORIGIN", "SYNONYM", "VALUE" }; static { targetTypes.add(PERSON); targetTypeProperties.put(PERSON, PERSON_PROPERTIES); targetTypes.add(ORGANIZATION); targetTypeProperties.put(ORGANIZATION, ORGANIZATION_PROPERTIES); targetTypes.add(EVENT); targetTypeProperties.put(EVENT, EVENT_PROPERTIES); targetTypes.add(THING); targetTypeProperties.put(THING, THING_PROPERTIES); targetTypes.add(ENTERTAINMENT); targetTypeProperties.put(ENTERTAINMENT, ENTERTAINMENT_PROPERTIES); } }