1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package de.fu_berlin.ties.context;
23
24 import java.util.Iterator;
25 import java.util.LinkedList;
26
27 import org.apache.commons.collections.buffer.CircularFifoBuffer;
28 import org.apache.commons.collections.iterators.EmptyIterator;
29 import org.apache.commons.lang.builder.ToStringBuilder;
30
31 import de.fu_berlin.ties.classify.feature.Feature;
32
33 /***
34 * A buffer of prior {@link de.fu_berlin.ties.context.Recognition}s that should
35 * be considered in the context representation. The buffer adjusts its size
36 * automatically, discarding the least recently added recognitions when enough
37 * recognitions are stored.
38 *
39 * <p>Allows to cache feature vectors representing recognitions (caching should
40 * only be used for
41 * {@linkplain de.fu_berlin.ties.context.Recognition#isSealed() sealed}
42 * recognitions because otherwise the cached features might get out-of-date).
43 *
44 * <p>Instances of this class and the nested class
45 * {@link PriorRecognitions.Pair} are not thread-safe.
46 *
47 * @author Christian Siefkes
48 * @version $Revision: 1.8 $, $Date: 2006/10/21 16:04:03 $, $Author: siefkes $
49 */
50 public class PriorRecognitions {
51
52 /***
53 * An inner class wrapping a recognition and optionally a feature vector
54 * representing the recognition.
55 */
56 public static class Pair {
57
58 /***
59 * The recognition wrapped in this pair.
60 */
61 private final Recognition recognition;
62
63 /***
64 * A list of features representing the recognition,
65 * initially <code>null</code>.
66 */
67 private LinkedList<Feature> cachedFeatures = null;
68
69 /***
70 * Creates a new instance.
71 * @param recog the recognition to wrap
72 */
73 public Pair(final Recognition recog) {
74 recognition = recog;
75 }
76
77 /***
78 * Returns the list of features representing the recognition,
79 * initially <code>null</code>.
80 * @return the value of the attribute
81 */
82 public LinkedList<Feature> getCachedFeatures() {
83 return cachedFeatures;
84 }
85
86 /***
87 * Returns the recognition wrapped in this pair.
88 * @return the value of the attribute
89 */
90 public Recognition getRecognition() {
91 return recognition;
92 }
93
94 /***
95 * Sets the list of features representing the recognition.
96 * @param features the new value of the attribute
97 */
98 public void setCachedFeatures(final LinkedList<Feature> features) {
99 cachedFeatures = features;
100 }
101
102 /***
103 * Returns a string representation of this object.
104 *
105 * @return a textual representation
106 */
107 public String toString() {
108 return new ToStringBuilder(this)
109 .append("recognition", recognition)
110 .append("features are cached", (cachedFeatures != null))
111 .toString();
112 }
113 }
114
115 /***
116 * The buffer used to store the pairs; <code>null</code> if the number of
117 * recognitions to store is 0.
118 */
119 private final CircularFifoBuffer pairBuffer;
120
121 /***
122 * Creates a new instance.
123 * @param size the number of prior recognitions to store; if 0 this is
124 * just a dummy instance that throws away any recognitions that are
125 * {@linkplain #add(Recognition) added}
126 */
127 public PriorRecognitions(final int size) {
128 super();
129 pairBuffer = (size > 0) ? new CircularFifoBuffer(size) : null;
130 }
131
132 /***
133 * Adds the given recognition to this buffer, discarding the least recently
134 * added recognition if appropriate.
135 * @param recognition the recognition to add
136 */
137 public void add(final Recognition recognition) {
138 if (pairBuffer != null) {
139 pairBuffer.add(new Pair(recognition));
140 }
141 }
142
143 /***
144 * Returns an iterator over the elements stored in this instance.
145 * <em>Note that the objects referred by the iterator will be
146 * {@link PriorRecognitions.Pair}s (<strong>not</strong>
147 * {@link Recognition}s). These pairs can be used to access the recognition
148 * and to retrieve and store feature vectors representing the recognition.
149 * Feature vectors should be cached only for
150 * {@linkplain Recognition#isSealed() sealed} recognitions because otherwise
151 * the cached features might get out-of-date</em>.
152 *
153 * @return an iterator over the stored {@link PriorRecognitions.Pair}s
154 */
155 public Iterator iterator() {
156 if (pairBuffer != null) {
157 return pairBuffer.iterator();
158 } else {
159 return EmptyIterator.INSTANCE;
160 }
161 }
162
163 /***
164 * Removes the most recently inserted recognition from this buffer.
165 *
166 * @return the removed recognition; or <code>null</code> if this container
167 * is empty
168 */
169 public Recognition removeLast() {
170 if (size() > 0) {
171
172
173 final Iterator pairIter = pairBuffer.iterator();
174 Pair pair = null;
175
176 while (pairIter.hasNext()) {
177 pair = (Pair) pairIter.next();
178 }
179
180
181 pairIter.remove();
182 return pair.getRecognition();
183 } else {
184
185 return null;
186 }
187 }
188
189 /***
190 * Returns the number of recognitions stored in the buffer.
191 * @return the number of recognitions stored
192 */
193 public int size() {
194 if (pairBuffer != null) {
195 return pairBuffer.size();
196 } else {
197 return 0;
198 }
199 }
200
201 /***
202 * Returns a string representation of this object.
203 *
204 * @return a textual representation
205 */
206 public String toString() {
207 return new ToStringBuilder(this)
208 .append("pair buffer", pairBuffer)
209 .toString();
210 }
211
212 }