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