1   /*
2    *  Copyright (c) 1998-2005, The University of Sheffield.
3    *
4    *  This file is part of GATE (see http://gate.ac.uk/), and is free
5    *  software, licenced under the GNU Library General Public License,
6    *  Version 2, June 1991 (in the distribution as file licence.html,
7    *  and also available at http://gate.ac.uk/gate/licence.html).
8    *
9    *  Valentin Tablan 27 Sep 2001
10   *
11   *  $I$
12   */
13  package gate.creole;
14  
15  import java.util.*;
16  
17  import gate.*;
18  import gate.event.*;
19  
20  
21  public abstract class AbstractController extends AbstractResource
22                                           implements Controller{
23  
24  
25    //executable code
26    /**
27     * Starts the execution of this executable
28     */
29    public void execute() throws ExecutionException {
30      throw new ExecutionException(
31        "Controller " + getClass() + " hasn't overriden the execute() method"
32      );  }
33  
34  
35    /** Initialise this resource, and return it. */
36    public Resource init() throws ResourceInstantiationException{
37      return this;
38    }
39  
40    /** Clears the internal data of the resource, when it gets released **/
41    public void cleanup(){
42    }
43  
44    /**
45     * Populates this controller from a collection of {@link ProcessingResource}s
46     * (optional operation).
47     *
48     * Controllers that are serializable must implement this method needed by GATE
49     * to restore their contents.
50     * @throws UnsupportedOperationException if the <tt>setPRs</tt> method
51     *         is not supported by this controller.
52     */
53    public void setPRs(Collection PRs){}
54  
55    /**
56     * Notifies all the PRs in this controller that they should stop their
57     * execution as soon as possible.
58     */
59    public synchronized void interrupt(){
60      interrupted = true;
61      Iterator prIter = getPRs().iterator();
62      while(prIter.hasNext()){
63        ((ProcessingResource)prIter.next()).interrupt();
64      }
65    }
66  
67    public synchronized boolean isInterrupted() {
68      return interrupted;
69    }
70  
71  
72    //events code
73    /**
74     * Removes a {@link gate.event.StatusListener} from the list of listeners for
75     * this processing resource
76     */
77    public synchronized void removeStatusListener(StatusListener l) {
78      if (statusListeners != null && statusListeners.contains(l)) {
79        Vector v = (Vector) statusListeners.clone();
80        v.removeElement(l);
81        statusListeners = v;
82      }
83    }
84  
85    /**
86     * Adds a {@link gate.event.StatusListener} to the list of listeners for
87     * this processing resource
88     */
89    public synchronized void addStatusListener(StatusListener l) {
90      Vector v = statusListeners == null ? new Vector(2) : (Vector) statusListeners.clone();
91      if (!v.contains(l)) {
92        v.addElement(l);
93        statusListeners = v;
94      }
95    }
96  
97    /**
98     * Notifies all the {@link gate.event.StatusListener}s of a change of status.
99     * @param e the message describing the status change
100    */
101   protected void fireStatusChanged(String e) {
102     if (statusListeners != null) {
103       Vector listeners = statusListeners;
104       int count = listeners.size();
105       for (int i = 0; i < count; i++) {
106         ((StatusListener) listeners.elementAt(i)).statusChanged(e);
107       }
108     }
109   }
110 
111   /**
112    * Adds a {@link gate.event.ProgressListener} to the list of listeners for
113    * this processing resource.
114    */
115   public synchronized void addProgressListener(ProgressListener l) {
116     Vector v = progressListeners == null ? new Vector(2) : (Vector) progressListeners.clone();
117     if (!v.contains(l)) {
118       v.addElement(l);
119       progressListeners = v;
120     }
121   }
122 
123   /**
124    * Removes a {@link gate.event.ProgressListener} from the list of listeners
125    * for this processing resource.
126    */
127   public synchronized void removeProgressListener(ProgressListener l) {
128     if (progressListeners != null && progressListeners.contains(l)) {
129       Vector v = (Vector) progressListeners.clone();
130       v.removeElement(l);
131       progressListeners = v;
132     }
133   }
134 
135 
136 
137   /**
138    * Notifies all the {@link gate.event.ProgressListener}s of a progress change
139    * event.
140    * @param e the new value of execution completion
141    */
142   protected void fireProgressChanged(int e) {
143     if (progressListeners != null) {
144       Vector listeners = progressListeners;
145       int count = listeners.size();
146       for (int i = 0; i < count; i++) {
147         ((ProgressListener) listeners.elementAt(i)).progressChanged(e);
148       }
149     }
150   }
151 
152   /**
153    * Notifies all the {@link gate.event.ProgressListener}s of a progress
154    * finished.
155    */
156   protected void fireProcessFinished() {
157     if (progressListeners != null) {
158       Vector listeners = progressListeners;
159       int count = listeners.size();
160       for (int i = 0; i < count; i++) {
161         ((ProgressListener) listeners.elementAt(i)).processFinished();
162       }
163     }
164   }
165 
166   /**
167    * A progress listener used to convert a 0..100 interval into a smaller one
168    */
169   protected class IntervalProgressListener implements ProgressListener{
170     public IntervalProgressListener(int start, int end){
171       this.start = start;
172       this.end = end;
173     }
174     public void progressChanged(int i){
175       fireProgressChanged(start + (end - start) * i / 100);
176     }
177 
178     public void processFinished(){
179       fireProgressChanged(end);
180     }
181 
182     int start;
183     int end;
184   }//CustomProgressListener
185 
186 
187   /**
188    * A simple status listener used to forward the events upstream.
189    */
190   protected class InternalStatusListener implements StatusListener{
191     public void statusChanged(String message){
192       fireStatusChanged(message);
193     }
194   }
195 
196 
197   /**
198    * Checks whether all the contained PRs have all the required runtime
199    * parameters set.
200    *
201    * @return a {@link List} of {@link ProcessingResource}s that have required
202    * parameters with null values if they exist <tt>null</tt> otherwise.
203    * @throws {@link ResourceInstantiationException} if problems occur while
204    * inspecting the parameters for one of the resources. These will normally be
205    * introspection problems and are usually caused by the lack of a parameter
206    * or of the read accessor for a parameter.
207    */
208   public List getOffendingPocessingResources()
209          throws ResourceInstantiationException{
210     //take all the contained PRs
211     ArrayList badPRs = new ArrayList(getPRs());
212     //remove the ones that no parameters problems
213     Iterator prIter = getPRs().iterator();
214     while(prIter.hasNext()){
215       ProcessingResource pr = (ProcessingResource)prIter.next();
216       ResourceData rData = (ResourceData)Gate.getCreoleRegister().
217                                               get(pr.getClass().getName());
218       if(AbstractResource.checkParameterValues(pr,
219                                                rData.getParameterList().
220                                                getRuntimeParameters())){
221         badPRs.remove(pr);
222       }
223     }
224     return badPRs.isEmpty() ? null : badPRs;
225   }
226 
227   /** Sets the name of this resource*/
228   public void setName(String name){
229     this.name = name;
230   }
231 
232   /** Returns the name of this resource*/
233   public String getName(){
234     return name;
235   }
236 
237   public synchronized void removeControllerListener(ControllerListener l) {
238     if (controllerListeners != null && controllerListeners.contains(l)) {
239       Vector v = (Vector) controllerListeners.clone();
240       v.removeElement(l);
241       controllerListeners = v;
242     }
243   }
244 
245   public synchronized void addControllerListener(ControllerListener l) {
246     Vector v = controllerListeners == null ? new Vector(2) : (Vector) controllerListeners.clone();
247     if (!v.contains(l)) {
248       v.addElement(l);
249       controllerListeners = v;
250     }
251   }
252 
253   protected String name;
254 
255   /**
256    * The list of {@link gate.event.StatusListener}s registered with this
257    * resource
258    */
259   private transient Vector statusListeners;
260 
261   /**
262    * The list of {@link gate.event.ProgressListener}s registered with this
263    * resource
264    */
265   private transient Vector progressListeners;
266 
267 
268   /**
269    * The list of {@link gate.event.ControllerListener}s registered with this
270    * resource
271    */
272   private transient Vector controllerListeners;
273 
274   protected boolean interrupted = false;
275   protected void fireResourceAdded(ControllerEvent e) {
276     if (controllerListeners != null) {
277       Vector listeners = controllerListeners;
278       int count = listeners.size();
279       for (int i = 0; i < count; i++) {
280         ((ControllerListener) listeners.elementAt(i)).resourceAdded(e);
281       }
282     }
283   }
284   protected void fireResourceRemoved(ControllerEvent e) {
285     if (controllerListeners != null) {
286       Vector listeners = controllerListeners;
287       int count = listeners.size();
288       for (int i = 0; i < count; i++) {
289         ((ControllerListener) listeners.elementAt(i)).resourceRemoved(e);
290       }
291     }
292   }
293 }