package edu.berkeley.nlp.io; import edu.berkeley.nlp.util.IntPair; import edu.berkeley.nlp.util.MapFactory; import java.io.Serializable; import java.util.Collection; import java.util.Map; /** * An abstract class for Label objects which store attributes in a Map. Also * implements HasWord, HasTag, HasCategory, and HasContext by storing the words, tags, * etc. under standardized keys in the Map. * <p/> * For convenience, this class also contains standardized keys for * storing many other possible label attributes, such as head words, ner tags, etc. * * @author grenager */ public abstract class AbstractMapLabel implements Label, Serializable { static final int initCapacity = 5; // THE STANDARD KEYS /** * The standard key for storing a value in the map, as a String. */ public static final String VALUE_KEY = "value"; /** * The standard key for storing a tag in the map. */ public static final String TAG_KEY = "tag"; /** * The standard key for storing a word in the map, as a String. */ public static final String WORD_KEY = "word"; /** * The standard key for storing a lemma in the map. */ public static final String LEMMA_KEY = "lemma"; /** * The standard key for storing a category in the map, as a String. */ public static final String CATEGORY_KEY = "cat"; /** * The standard key for storing a projected category in the map, as a String. * For any word (leaf node), the projected category is the syntactic category * of the maximal constituent headed by the word. Used in SemanticGraph. */ public static final String PROJ_CAT_KEY = "pcat"; /** * The standard key for storing a head word in the map as a pointer to * another node. */ public static final String HEAD_WORD_KEY = "hw"; /** * The standard key for storing a head tag in the map as a pointer to * another node. */ public static final String HEAD_TAG_KEY = "ht"; /** * The standard key for storing an integer index in the map. */ public static final String INDEX_KEY = "idx"; /** * The standard key for a propbank label which is of type Argument */ public static final String ARG_KEY = "arg"; /** * Another key used for propbank - to signify core arg nodes or predicate nodes */ public static final String MARKING_KEY = "mark"; /** * The standard key for Semantic Head Word which is a String */ public static final String SEMANTIC_HEAD_WORD_KEY = "shw"; /** * The standard key for Semantic Head Word POS which is a String */ public static final String SEMANTIC_HEAD_POS_KEY = "shp"; /** * Probank key for the Verb sense given in the Propbank Annotation, should * only be in the verbnode */ public static final String VERB_SENSE_KEY = "vs"; /** * The standard key for storing category with functional tags. */ public static final String CATEGORY_FUNCTIONAL_TAG_KEY = "cft"; /** * the standard key for the NER label. */ public static final String NER_KEY = "ner"; /** * the standard key for the coref label. */ public static final String COREF_KEY = "coref"; /** The standard key for the "shape" of a word: a String representing * the type of characters in a word, such as "Xx" for a capitalized word. * See {@link edu.stanford.nlp.process.WordShapeClassifier} for functions * for making shape strings. */ public static final String SHAPE_KEY = "shape"; /** * The Standard key for storing the left terminal number relative to the * root of the tree of the leftmost terminal dominated by the current node */ public static final String LEFT_TERM_KEY = "LEFT_TERM"; /** * The standard key for the parent which is a String */ public static final String PARENT_KEY = "PARENT"; /** * The standard key for span which is a String */ public static final String SPAN_KEY = "SPAN"; /** * the standard key for the String that comes before this word * (from the InvertiblePTBTokenizer) */ public static final String BEFORE_KEY = "before"; /** * the standard key for the String that comes after this word * (from the InvertiblePTBTokenizer) */ public static final String AFTER_KEY = "after"; /** * the standard key for the actual, unmangled, pre-PTB'd word * (from the InvertiblePTBTokenizer) */ public static final String CURRENT_KEY = "current"; /** * The standard key for the answer which is a String */ public static final String ANSWER_KEY = "answer"; /** * The standard key for gold answer which is a String */ public static final String GOLDANSWER_KEY = "goldAnswer"; /** * The standard key for the features which is a Collection */ public static final String FEATURES_KEY = "features"; /** * The standard key for the semantic interpretation */ public static final String INTERPRETATION_KEY = "interpretation"; /** * The standard key for the semantic role label */ public static final String ROLE_KEY = "srl"; /** * The standard key for the gazetteer information */ public static final String GAZETTEER_KEY = "gazetteer"; public static final String STEM_KEY = "stem"; public static final String POLARITY_KEY = "polarity"; /** * for Chinese: character level information, segmentation */ public static final String CH_CHAR_KEY = "char"; public static final String CH_ORIG_SEG_KEY = "orig_seg"; // the segmentation info existing in the original text public static final String CH_SEG_KEY = "seg"; // the segmentation information from the segmenter /** This key is at present only used in CraigslistDemo. */ public static final String BEGIN_POSITION_KEY = "BEGIN_POS"; /** The character offset of last character of token in source. */ public static final String END_POSITION_KEY = "END_POS"; /** * The Map which stores all of the attributes for this label, and * the label value itself. */ protected Map map; /** * The MapFactory which will be used to make new Maps in this AbstractMapLabel. */ protected MapFactory mapFactory; protected AbstractMapLabel() { this(null); } protected AbstractMapLabel(MapFactory mapFactory) { if (mapFactory==null) { this.mapFactory = new MapFactory.HashMapFactory(); } else { this.mapFactory = mapFactory; } this.map = this.mapFactory.buildMap(); } // DIRECT MAP FUNCTIONALITY /** * Return the <code>Map</code> contained in this label. * * @return the <code>Map</code> contained in this AbstractMapLabel */ public Map map() { return map; } // yikes! [commented out by dramage 4/5/06] // // /** // * Set the <code>Map</code> contained in this AbstractMapLabel to the // * supplied <code>Map</code>. // * // * @param map the new <code>Map</code> for this label // */ // public void setMap(Map map) { // this.map = map; // } /** * Returns the value to which the map contained in this label * maps the specified key. Returns <code>null</code> if the map * contains no mapping for this key. (Analogous to {@link * Map#get <code>Map.get(Object key)</code>}.) * * @param key key whose associated value is to be returned. * @return the value to which the map contained in this label * maps the specified key, or <code>null</code> if the map * contains no mapping for this key. */ public Object get(Object key) { Object v = map.get(key); if (v == null) { return ""; } return v; } /** * Associates the specified value with the specified key in the * map contained in this label. (Analogous to {@link Map#put * <code>Map.put(Object key, Object value)</code>}.) * If the map previously contained a mapping for this key, the * old value is replaced by the specified value. * * @param key key with which the specified value is to be associated. * @param value value to be associated with the specified key. * @return previous value associated with specified key, or * <code>null</code> if there was no mapping for key. */ public Object put(Object key, Object value) { return map.put(key, value); } // LABEL METHODS /** * @return the value for the label */ public String value() { return (String) map.get(VALUE_KEY); } /** * Set the value for the label. * * @param value the value for the label */ public void setValue(final String value) { map.put(VALUE_KEY, value); } /** * Set value for the label from a String. * * @param str the string value for the label */ public void setFromString(final String str) { setValue(str); } // HASCATEGORY METHODS /** * Return the category of the label (or <code>null</code> if * none), which is stored in the map under the key {@link * AbstractMapLabel#CATEGORY_KEY <code>CATEGORY_KEY</code>}. * * @return the category for the label */ public String category() { Object cat = map.get(CATEGORY_KEY); if (cat != null && cat instanceof String) { return (String) cat; } else { return null; } } /** * Set the category for the label. * * @param category the category for the label */ public void setCategory(final String category) { map.put(CATEGORY_KEY, category); } // HASWORD METHODS /** * Return the word of the label, stored in the map under the key <code>WORD_KEY</code>. * * @return The word for this label */ public String word() { return (String) map.get(WORD_KEY); } /** * Set the word for the label. * * @param word the head word for the label */ public void setWord(String word) { map.put(WORD_KEY, word); } /** * The span of this node as begin and end positions if it exists * * @return The span */ public IntPair span() { return (IntPair) map.get(SPAN_KEY); } public void setSpan(String span) { map.put(SPAN_KEY, span); } /** * Return the head word of the label (or <code>null</code> if * none), which is stored in the map under the key {@link * AbstractMapLabel#HEAD_WORD_KEY <code>HEAD_WORD_KEY</code>}. * * @return the head word for the label */ public Object headWord() { return map.get(HEAD_WORD_KEY); } /** * Set a pointer to the head-word for the label. */ public void setHeadWord(Object headWordPtr) { map.put(HEAD_WORD_KEY, headWordPtr); if (headWordPtr instanceof HasWord) { setWord(((HasWord) headWordPtr).word()); } else if (headWordPtr instanceof Label) { setWord(((Label) headWordPtr).value()); } } /** * Returns the semantic head of the phrase if it exists, and null otherwise */ public String getSemanticWord() { Object word = map.get(SEMANTIC_HEAD_WORD_KEY); return word != null ? word.toString() : null; } /** * Set the semantic head of the phrase */ public void setSemanticWord(final String hWord) { map.put(SEMANTIC_HEAD_WORD_KEY, hWord); } /** * Returns the semantic head pos of the phrase if it exists, and null otherwise */ public String getSemanticTag() { Object word = map.get(SEMANTIC_HEAD_POS_KEY); return word != null ? word.toString() : null; } /** * Set the semantic head pos of the phrase */ public void setSemanticTag(final String hTag) { map.put(SEMANTIC_HEAD_POS_KEY, hTag); } /** * Return the head tag of the label (or <code>null</code> if none), * which is stored in the map under the key {@link * AbstractMapLabel#TAG_KEY <code>TAG_KEY</code>}. * * @return the head tag for the label */ public String tag() { Object tag = map.get(TAG_KEY); if (tag != null && tag instanceof String) { return (String) tag; } else { return null; } } /** * Set the head tag for the label by storing it in the map under * the key {@link AbstractMapLabel#HEAD_TAG_KEY * <code>HEAD_TAG_KEY</code>}. * * @param tag the head tag for the label */ public void setTag(final String tag) { map.put(TAG_KEY, tag); } public Object headTag() { return map.get(HEAD_TAG_KEY); } /** * Set a pointer to the head-word for the label. */ public void setHeadTag(Object headTagPtr) { map.put(HEAD_TAG_KEY, headTagPtr); if (headTagPtr instanceof HasTag) { setTag(((HasTag) headTagPtr).tag()); } else if (headTagPtr instanceof Label) { setTag(((Label) headTagPtr).value()); } } /** * Return the NER type of the word, * which is stored in the map under the key {@link * AbstractMapLabel#NER_KEY <code>NER_KEY</code>}. * * @return The NER label of the word */ public String ner() { Object ner = map.get(NER_KEY); return (String) ner; } /** * Set the NER label for the word, using * the key {@link AbstractMapLabel#NER_KEY * <code>NER_KEY</code>}. * * @param ner The String NER label of the word */ public void setNER(String ner) { map.put(NER_KEY, ner); } /** * Return the shape attribute of the word, * which is stored in the map under the key {@link * AbstractMapLabel#SHAPE_KEY <code>SHAPE_KEY</code>}. * * @return The shape of the word. */ public String shape() { return (String) map.get(SHAPE_KEY); } /** * Set the shape property for the word, using * the key {@link AbstractMapLabel#SHAPE_KEY * <code>SHAPE_KEY</code>}. * * @param shape A String giving the "shape" of the word. */ public void setShape(String shape) { map.put(SHAPE_KEY, shape); } /** * Return the index of the label (or -1 if none), which is stored in * the map under the key {@link AbstractMapLabel#INDEX_KEY * <code>INDEX_KEY</code>}. * * @return the index for the label */ public int index() { Object index = map.get(INDEX_KEY); if (index != null && index instanceof Integer) { return ((Integer) index).intValue(); } else { return -1; } } /** * Set the index for the label by storing it in the contained map * under the key {@link AbstractMapLabel#INDEX_KEY * <code>INDEX_KEY</code>}. * * WARNING: do NOT call this if the vertice is already in a SemanticGraph. * Doing so will disrupt the equality criteria for the map, and will throw off * routines that check to see if this vertice is in the SemanticGraph. */ public void setIndex(int index) { map.put(INDEX_KEY, new Integer(index)); } /** * Return the beginning character offset of the label (or -1 if none). * This is stored in * the map under the key {@link AbstractMapLabel#BEGIN_POSITION_KEY} * <code>INDEX_KEY</code>. * * @return the beginning position for the label */ public int beginPosition() { Object index = map.get(BEGIN_POSITION_KEY); if (index != null && index instanceof Integer) { return ((Integer) index).intValue(); } else { return -1; } } /** * Set the beginning character offset for the label * by storing it in the contained map * under the key {@link AbstractMapLabel#BEGIN_POSITION_KEY} * <code>INDEX_KEY</code>. Setting this key to "-1" can be used to * indicate no valid value. * * @param beginPos The beginning position */ public void setBeginPosition(int beginPos) { map.put(BEGIN_POSITION_KEY, new Integer(beginPos)); } /** * Return the ending character offset of the label (or -1 if none). * This is stored in * the map under the key {@link AbstractMapLabel#END_POSITION_KEY} * <code>INDEX_KEY</code>. * * @return the end position for the label */ public int endPosition() { Object index = map.get(END_POSITION_KEY); if (index != null && index instanceof Integer) { return ((Integer) index).intValue(); } else { return -1; } } /** * Set the ending character offset for the label * by storing it in the contained map * under the key {@link AbstractMapLabel#END_POSITION_KEY} * <code>INDEX_KEY</code>. Setting this key to "-1" can be used to * indicate no valid value. * * @param endPos The end position */ public void setEndPosition(int endPos) { map.put(END_POSITION_KEY, new Integer(endPos)); } // HAS CONTEXT METHODS /** * Return the String before the word, * which is stored in the map under the key {@link * AbstractMapLabel#BEFORE_KEY <code>BEFORE_KEY</code>}. * * @return the String before the word */ public String before() { Object before = map.get(BEFORE_KEY); if (before == null) { before = ""; } return (String) before; } /** * Set the String before the word by storing it in the map under * the key {@link AbstractMapLabel#BEFORE_KEY <code>BEFORE_KEY</code>}. * * @param before the String before the word */ public void setBefore(String before) { map.put(BEFORE_KEY, before); } /** * Prepend this String to the current before String * * @param before the String to be prepended */ public void prependBefore(String before) { String oldBefore = before(); if (oldBefore == null) { oldBefore = ""; } setBefore(before + oldBefore); } /** * Return the String which is the unmangled word, * which is stored in the map under the key {@link * AbstractMapLabel#CURRENT_KEY <code>CURRENT_KEY</code>}. * * @return the unmangled word */ public String current() { Object current = map.get(CURRENT_KEY); if (current == null) { current = ""; } return (String) current; } /** * Set the String which is the unmangled word, * which is stored in the map under the key {@link * AbstractMapLabel#CURRENT_KEY <code>CURRENT_KEY</code>}. * * @param current the unmangled word */ public void setCurrent(String current) { map.put(CURRENT_KEY, current); } /** * Return the String after the word, * which is stored in the map under the key {@link * AbstractMapLabel#AFTER_KEY <code>AFTER_KEY</code>}. * * @return the String after the word */ public String after() { Object after = map.get(AFTER_KEY); if (after == null) { after = ""; } return (String) after; } /** * Set the String after the word by storing it in the map under * the key {@link AbstractMapLabel#AFTER_KEY * <code>AFTER_KEY</code>}. * * @param after The String after the word */ public void setAfter(String after) { map.put(AFTER_KEY, after); } /** * Append this String to the current after String * * @param after The String to be prepended */ public void appendAfter(String after) { String oldAfter = after(); if (oldAfter == null) { oldAfter = ""; } setAfter(oldAfter + after); } /** * convenience method for getting answer * */ public String answer() { return (String) get(ANSWER_KEY); } /** * convenience method for setting answer * */ public void setAnswer(String answer) { put(ANSWER_KEY, answer); } /** * convenience method for getting gold answer * */ public String goldAnswer() { return (String) get(GOLDANSWER_KEY); } /** * convenience method for setting gold answer * */ public void setGoldAnswer(String goldAnswer) { put(GOLDANSWER_KEY, goldAnswer); } public Collection getFeatures() { return (Collection) map.get(FEATURES_KEY); } public void setFeatures(Collection features) { map.put(FEATURES_KEY, features); } public Object interpretation() { return map.get(INTERPRETATION_KEY); } public void setInterpretation(Object interpretation) { map.put(INTERPRETATION_KEY, interpretation); } public String getLemma() { return (String) map.get(LEMMA_KEY); } public void setLemma(String lemma) { map.put(LEMMA_KEY, lemma); } public String getRole() { return (String) map.get(ROLE_KEY); } public void setRole(String role) { map.put(ROLE_KEY, role); } private static final long serialVersionUID = -980833749513621054L; }