View Javadoc

1   /*
2    * Copyright (C) 2004 Christian Siefkes <christian@siefkes.net>.
3    * Development of this software is supported by the German Research Society,
4    * Berlin-Brandenburg Graduate School in Distributed Information Systems
5    * (DFG grant no. GRK 316).
6    *
7    * This library is free software; you can redistribute it and/or
8    * modify it under the terms of the GNU Lesser General Public
9    * License as published by the Free Software Foundation; either
10   * version 2.1 of the License, or (at your option) any later version.
11   *
12   * This library is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this library; if not, visit
19   * http://www.gnu.org/licenses/lgpl.html or write to the Free Software
20   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21   */
22  package de.fu_berlin.ties.eval;
23  
24  import java.util.HashMap;
25  import java.util.Map;
26  
27  import org.apache.commons.lang.StringUtils;
28  
29  /***
30   * Type-safe enumeration of possible evaluation states for predictions
31   * (unknown, correct, spurious etc.) and answer keys (missing etc.).
32   *
33   * @author Christian Siefkes
34   * @version $Revision: 1.4 $, $Date: 2004/11/07 18:21:27 $, $Author: siefkes $
35   */
36  public final class EvalStatus {
37  
38      /***
39       * A map of all instantiated instances of this class. The name of the
40       * instance is mapped to the instance itself. There is no need to
41       * synchronize this map as it is only modified during the static
42       * initialization of this class.
43       */
44      private static final Map<String, EvalStatus> ALL_INSTANCES =
45          new HashMap<String, EvalStatus>();
46  
47      /***
48       * Serialization key recommended for instances of this class.
49       */
50      public static final String KEY_EVAL_STATUS = "EvalStatus";
51  
52      /***
53       * Constant for predictions whose evaluation status is unknown (not
54       * yet evaluated).
55       */
56      public static final EvalStatus UNKNOWN =
57          new EvalStatus("unknown", true, false);
58  
59      /***
60       * Constant for items defined to be true (answer keys, "gold standard").
61       */
62      public static final EvalStatus TRUTH = new EvalStatus("truth", false, true);
63  
64      /***
65       * Constant for correct predictions (true positives) resp for answer
66       * keys matched by a prediction. This is the only instance that is suitable
67       * for both {@link #isAnswerState() answer keys} and
68       * {@link #isPredictionState() predictions}.
69       */
70      public static final EvalStatus CORRECT =
71          new EvalStatus("correct", true, true);
72  
73      /***
74       * Constant for missing answer keys (false negatives).
75       */
76      public static final EvalStatus MISSING =
77          new EvalStatus("missing", false, true);
78  
79      /***
80       * Constant for spurious predictions (false positives).
81       */
82      public static final EvalStatus SPURIOUS =
83          new EvalStatus("spurious", true, false);
84  
85      /***
86       * Constant for answer keys that could have proposed as predictions but
87       * were not. When there is only a single instance of each type to predict
88       * ("best match" mode), one of the answer keys should be tagged as
89       * {@link #CORRECT} resp. {@link #MISSING}; the others should be tagged
90       * as {@link #ALTERNATIVE}s.
91       */
92      public static final EvalStatus ALTERNATIVE =
93          new EvalStatus("alternative", false, true);
94  
95      /***
96       * Constant for predictions that were ignored. When there is only a single
97       * instance of each type to predict ("best match" mode), the most probably
98       * prediction will be evaluated, while the others of the same type will be
99       * ignored.
100      */
101     public static final EvalStatus IGNORED =
102         new EvalStatus("ignored", true, false);
103 
104     /***
105      * Parses a textual representation into an eval status, without using a
106      * default object. This method can convert to results of {@link #getName()}
107      * and {@link #toString()} back into the corresponding instance.
108      *
109      * @param representation the textual representation to parse
110      * @return the eval status object corresponding to the given string
111      * @throws IllegalArgumentException if a given string does not represent a
112      * known evaluation status
113      */
114     public static EvalStatus parse(final String representation)
115             throws IllegalArgumentException {
116         return parse(representation, false);
117     }
118 
119     /***
120      * Parses a textual representation into an eval status. This method can
121      * convert to results of {@link #getName()} and {@link #toString()} back
122      * into the corresponding instance.
123      *
124      * @param representation the textual representation to parse
125      * @param useDefault if <code>true</code>, {@link #UNKNOWN} is returned if
126      * the representation is an unparsable (invalid) or <code>null</code>;
127      * otherwise an exception is thrown in this case
128      * @return the eval status object corresponding to the given string
129      * @throws IllegalArgumentException if a given string does not represent a
130      * known evaluation status and <code>useDefault</code> is <code>false</code>
131      */
132     public static EvalStatus parse(final String representation,
133             final boolean useDefault) throws IllegalArgumentException {
134         // using StringUtils so null is handled
135         final EvalStatus result =
136             ALL_INSTANCES.get(StringUtils.trim(representation));
137 
138         if (result != null) {
139             return result;
140         } else {
141             if (useDefault) {
142                 return EvalStatus.UNKNOWN;
143             }  else {
144                 throw new IllegalArgumentException(
145                         "Cannot parse to eval status: " + representation);
146             }
147         }
148     }
149 
150     /***
151      * The name of this instance.
152      */
153     private final String name;
154 
155     /***
156      * Whether this state is suitable for an answer key.
157      */
158     private final boolean answerState;
159 
160     /***
161      * Whether this state is suitable for a prediction.
162      */
163     private final boolean predictionState;
164 
165     /***
166      * Private constructor to prevent creation of further instances.
167      * The static constants defined in this class are the only instantiations.
168      *
169      * @param newName the name of this instance
170      * @param predState whether this state is suitable for a prediction
171      * @param ansState whether this state is suitable for an answer key
172      * @throws IllegalArgumentException if the specified name is already used
173      * by another instance
174      */
175     private EvalStatus(final String newName, final boolean predState,
176             final boolean ansState) throws IllegalArgumentException {
177         super();
178         name = newName;
179         predictionState = predState;
180         answerState = ansState;
181 
182         // register myself
183         final EvalStatus previousValue = ALL_INSTANCES.put(newName, this);
184         if (previousValue != null) {
185             throw new IllegalArgumentException(
186                 "Name " + newName + " already in use!");
187         }
188     }
189 
190     /***
191      * Returns the name of this instance.
192      * @return the value of the attribute
193      */
194     public String getName() {
195         return name;
196     }
197 
198     /***
199      * Returns a string representation, printing the
200      * {@linkplain #getName() name} of this instance.
201      *
202      * @return a textual representation
203      */
204     public String toString() {
205         return name;
206     }
207 
208     /***
209      * Whether this state is suitable for an answer key.
210      * @return <code>true</code> iff this state is suitable for an answer key
211      */
212     public boolean isAnswerState() {
213         return answerState;
214     }
215 
216     /***
217      * Whether this state is suitable for a prediction.
218      * @return <code>true</code> iff this state is suitable for a prediction
219      */
220     public boolean isPredictionState() {
221         return predictionState;
222     }
223 
224 }