Source code: recoin/container/RetrievalContainer.java
1
2 package recoin.container;
3
4 import java.util.Enumeration;
5 import java.util.Vector;
6
7 import org.apache.log4j.Logger;
8
9 import recoin.exception.ComponentException;
10 import recoin.exception.ComponentRunnableException;
11 import recoin.group.ComponentRunnable;
12 import recoin.group.ComponentSupport;
13 import recoin.group.ComponentSupportImpl;
14 import recoin.system.session.ComponentChain;
15 import recoin.util.TimeLog;
16
17 /**
18 * A RetrievalContainer is a very simple container object that can be used in a RetrievalCycle
19 * to store data that is used during retrieval. This data could be anything from
20 * input to the retrieval process like a query, output that has been created, result lists for example,
21 * or any other data that aids in the retrieval process.
22 * <br><br>
23 * The RetrievalContainer is passed along different ModuleGroup objects and it lets the Component
24 * objects of a particular group access, process and store information inside the container.
25 * A RetrievalContainer object can switch between two different states to signal if there
26 * still are threads operating on its data. The RetrievalContainer class provides functions to
27 * block and wake up threads when this state changes.<br>
28 * This is important, because the RetrievalCycle waits for this signal in the wait set
29 * of this RetrievalContainer while it is being processed by a certain ModuleGroup.
30 * <br><br>
31 * It extends the simple class ComponentSupportImpl in order for a RetrievalContainer
32 * object to be passed to Component objects.
33 * @author Jan H. Scheufen
34 * @version 0.2.9
35 */
36 public class RetrievalContainer extends ComponentSupportImpl
37 {
38 /**
39 * The logger for this class
40 */
41 static Logger logger;
42 /**
43 * The flag to signal the end of processing this RetrievalContainer. Inital value is 'true'.
44 */
45 private boolean finished = true;
46 /**
47 * A ComponentChain object that can be used to distribute the container to a
48 * predefined number Component objects.
49 */
50 private ComponentChain componentChain = null;
51 /**
52 * The ThreadGroup to group the threads working on this RetrievalContainer.
53 */
54 protected ThreadGroup threadGroup;
55 /**
56 * The ComponentRunnable objects that process this RetrievalContainer.
57 */
58 protected Vector runnables;
59 /**
60 * The ComponentSupport objects used in the retrieval process.
61 */
62 protected Vector componentSupport;
63 /**
64 * A special Vector that stores exceptions there was a problem inside a Component
65 * that processed this RetrievalContainer.
66 */
67 protected Vector exceptions;
68 /**
69 * The timelog to protocol the time needed for the RetrievalCycle and by individual components.
70 */
71 public TimeLog timeLog;
72
73 /**
74 * Creates a new RetrievalContainer.<br>
75 * The TimeLog of the RetrievalContainer is initiated with a new DurationStamp.
76 */
77 public RetrievalContainer()
78 {
79 logger = Logger.getLogger( RetrievalContainer.class.getName() );
80 runnables = new Vector();
81 componentSupport = new Vector();
82 exceptions = new Vector();
83 threadGroup = new ThreadGroup("");
84 timeLog = new TimeLog(true);
85 }
86
87 /**
88 * Sets the field <code>finished</code> to the specified value. If 'true' it
89 * wakes up a single thread waiting in the wait set of this RetrievalContainer.
90 * Normaly this should only be a RetrievalCycle object, because the
91 * method cannot garantue to wake up a specific thread waiting for a notify()
92 * from this RetrievalContainer.
93 * @param fin the state of this RetrievalContainer
94 */
95 public void setFinished(boolean fin)
96 {
97 finished = fin;
98 if( finished )
99 {
100 logger.debug("Notifying waiting RetrievalCycle.");
101 notify();
102 }
103 }
104
105 /**
106 * Adds the calling thread to the wait set of this RetrievalContainer object. The method
107 * uses a guarded wait by re-checking the value of the finished field to avoid spurious
108 * or accidental wake ups.
109 * @throws InterruptedException
110 */
111 public synchronized void waitForFinished() throws InterruptedException
112 {
113 while( !finished )
114 {
115 wait();
116 }
117 }
118
119 /**
120 * Returns the TimeLog of the RetrievalContainer.
121 * @return the TimeLog
122 */
123 public TimeLog getTimeLog()
124 {
125 return timeLog;
126 }
127
128 /**
129 * Starts all ComponentRunnables currently contained in this RetrievalContainer.
130 */
131 public void startRunnables()
132 {
133 if( runnables.size() > 0 )
134 {
135 threadGroup = new ThreadGroup("RunnableGroup");
136 logger.debug("Starting "+runnables.size()+" ComponentRunnables.");
137 for( Enumeration enum = runnables.elements(); enum.hasMoreElements(); )
138 {
139 ComponentRunnable runnable = null;
140 try
141 {
142 runnable = (ComponentRunnable) enum.nextElement();
143 }
144 catch (ClassCastException e)
145 {
146 logger.error("ClassCastException while starting ComponentRunnable.");
147 }
148 logger.debug("Starting ComponentRunnable "+runnable.getClass().getName());
149 Thread t = new Thread( threadGroup, runnable );
150 t.setName( runnable.getThreadName() );
151 runnable.setUp();
152 t.start();
153 }
154 }
155 else
156 {
157 logger.debug("No ComponentRunnables found! Proceeding ...");
158 checkFinished();
159 }
160 }
161
162 /**
163 * Adds the specified ComponentRunnable to this RetrievalContainer.
164 * @param runnable the ComponentRunnable
165 */
166 public void addRunnable( ComponentRunnable runnable )
167 {
168 logger.debug("Adding Runnable to container.");
169 this.runnables.add( runnable );
170 }
171
172 /**
173 * Adds the ComponentRunnable objects inside the specified Vector to this RetrievalContainer.
174 * @param runnableVector a Vector containing ComponentRunnable objects
175 */
176 public void addRunnables(Vector runnableVector)
177 {
178 logger.debug("Adding Runnables to container.");
179 for( Enumeration enum = runnableVector.elements(); enum.hasMoreElements(); )
180 {
181 this.runnables.add( ((ComponentRunnable) enum.nextElement()) );
182 }
183 }
184
185 /**
186 * Adds the specified ComponentSupport to this RetrievalContainer.
187 * @param support the ComponentSupport to add
188 */
189 public synchronized void addComponentSupport( ComponentSupport support )
190 {
191 this.componentSupport.add( support );
192 }
193
194 /**
195 * Adds the specified Vector of ComponentSupport objects to this RetrievalContainer.
196 * @param support the ComponentSupport objects
197 */
198 public synchronized void addComponentSupports( Vector supports )
199 {
200 this.componentSupport.add( supports );
201 }
202
203 /**
204 * Adds the specified ComponentException to this RetrievalContainer.
205 * @param e the ComponentException
206 */
207 public synchronized void addException( ComponentException e )
208 {
209 this.exceptions.add( e );
210 }
211
212 /**
213 * Adds the specified ComponentRunnableException to this RetrievalContainer.
214 * @param e the ComponentRunnableException
215 */
216 public synchronized void addException( ComponentRunnableException e )
217 {
218 this.exceptions.add( e );
219 }
220
221 /**
222 * Returns the ComponentChain of this RetrievalContainer.
223 * @return the ComponentChain
224 */
225 public ComponentChain getComponentChain()
226 {
227 return componentChain;
228 }
229
230 /**
231 * Sets the ComponentChain of this RetrievalContainer.
232 * @param chain the ComponentChain
233 */
234 public void setComponentChain( ComponentChain chain )
235 {
236 this.componentChain = chain;
237 }
238
239 /**
240 * Returns all ComponentSupport objects currently contained in this RetrievalContainer.
241 * @return a Vector of ComponentSupport objects.
242 */
243 public Vector getComponentSupport()
244 {
245 return componentSupport;
246 }
247
248 /**
249 * Returns all ComponentSupport objects in this RetrievalContainer that are instances
250 * of the ResultList class.
251 * @return a Vector of ResultList objects
252 */
253 public Vector getResultLists()
254 {
255 Vector r = new Vector();
256 for( Enumeration enum = componentSupport.elements(); enum.hasMoreElements(); )
257 {
258 ComponentSupport cs = (ComponentSupport) enum.nextElement();
259 if( cs instanceof ResultList )
260 r.add( cs );
261 }
262 return r;
263 }
264
265 /**
266 * Returns the exceptions that are currently contained in this RetrievalContainer.
267 * @return Vector
268 */
269 public Vector getExceptions()
270 {
271 return exceptions;
272 }
273
274 /**
275 * Returns the ComponentSupport that has the specified chain ID. NULL if the specified
276 * ComponentSupport could not be found.
277 * @param chainID the chain ID of the desired ComponentSupport
278 * @return the ComponentSupport or NULL if it could not be found
279 */
280 public ComponentSupport getComponentSupport( String chainID )
281 {
282 for( Enumeration enum = componentSupport.elements(); enum.hasMoreElements(); )
283 {
284 ComponentSupport support = (ComponentSupport) enum.nextElement();
285 if( support.getChainID().equals(chainID) )
286 return support;
287 }
288 return null;
289 }
290
291 /**
292 * This method checks if there are any more active threads working on this RetrievalContainer.
293 * If there are none or they have all finished processing, setFinished(true) is called
294 * and the Vector runnables is emptied to dispose of the no longer needed ComponentRunnable
295 * objects.
296 */
297 public synchronized void checkFinished()
298 {
299 logger.debug("CheckFinish() called on RetrievalContainer. Active Threads: "+threadGroup.activeCount());
300 if( threadGroup.activeCount() <= 1 ) // calling Thread may still be active!
301 {
302 runnables = new Vector();
303 setFinished(true);
304 }
305 }
306
307 }