View Javadoc

1   /*
2    * Copyright (C) 2004-2006 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 program is free software; you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation; either version 2 of the License, or
10   * (at your option) any later version.
11   *
12   * This program 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
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, visit
19   * http://www.gnu.org/licenses/gpl.html or write to the Free Software
20   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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             // we have use the iterator because we cannot access the last
172             // element directly
173             final Iterator pairIter = pairBuffer.iterator();
174             Pair pair = null;
175 
176             while (pairIter.hasNext()) {
177                 pair = (Pair) pairIter.next();
178             }
179 
180             // remove the last pair and recogn its recognition
181             pairIter.remove();
182             return pair.getRecognition();
183         } else {
184             // empty/no buffer
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 }