ConditionalSerialController.java
001 /*
002  *  Copyright (c) 1995-2012, The University of Sheffield. See the file
003  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
004  *
005  *  This file is part of GATE (see http://gate.ac.uk/), and is free
006  *  software, licenced under the GNU Library General Public License,
007  *  Version 2, June 1991 (in the distribution as file licence.html,
008  *  and also available at http://gate.ac.uk/gate/licence.html).
009  *
010  *  Valentin Tablan 11 Apr 2002
011  *
012  *  $Id: ConditionalSerialController.java 17606 2014-03-09 12:12:49Z markagreenwood $
013  */
014 
015 package gate.creole;
016 
017 import java.util.*;
018 
019 import gate.*;
020 import gate.creole.RunningStrategy.UnconditionalRunningStrategy;
021 import gate.creole.metadata.CreoleResource;
022 import gate.event.ControllerEvent;
023 import gate.util.Benchmark;
024 import gate.util.Err;
025 
026 /**
027  * Execute a list of PRs serially. For each PR a running strategy is stored
028  * which decides whether the PR will be run always, never or upon a condition
029  * being satisfied.
030  * This controller uses {@link AnalyserRunningStrategy} objects as running
031  * strategies and they only work with {@link LanguageAnalyser}s so the PRs that
032  * are not analysers will get a default "run always" strategy.
033  */
034 @CreoleResource(name = "Conditional Pipeline",
035     comment = "A simple serial controller for conditionally run PRs.",
036     helpURL = "http://gate.ac.uk/userguide/sec:developer:cond")
037 public class ConditionalSerialController extends SerialController
038                                          implements ConditionalController{
039 
040   private static final long serialVersionUID = -3791943170768459208L;
041 
042   public ConditionalSerialController(){
043     strategiesList = new ArrayList<RunningStrategy>();
044   }
045 
046   @Override
047   public List<RunningStrategy> getRunningStrategies(){
048     return Collections.unmodifiableList(strategiesList);
049   }
050 
051   /**
052    * Set a PR at a specified location.
053    * The running strategy defaults to run always.
054    @param index the position for the PR
055    @param pr the PR to be set.
056    */
057   @Override
058   public void add(int index, ProcessingResource pr){
059     if(pr instanceof LanguageAnalyser){
060       strategiesList.add(index,
061                          new AnalyserRunningStrategy((LanguageAnalyser)pr,
062                                                       RunningStrategy.RUN_ALWAYS,
063                                                       null, null));
064     }else{
065       strategiesList.add(index, new RunningStrategy.UnconditionalRunningStrategy(pr, true));
066     }
067     super.add(index, pr);
068   }
069 
070   /**
071    * Add a PR to the end of the execution list.
072    @param pr the PR to be added.
073    */
074   @Override
075   public void add(ProcessingResource pr){
076     if(pr instanceof LanguageAnalyser){
077       strategiesList.add(new AnalyserRunningStrategy((LanguageAnalyser)pr,
078                                                       RunningStrategy.RUN_ALWAYS,
079                                                       null, null));
080     }else{
081       strategiesList.add(new RunningStrategy.UnconditionalRunningStrategy(pr, true));
082     }
083     super.add(pr);
084   }
085 
086   @Override
087   public ProcessingResource remove(int index){
088     ProcessingResource aPr = super.remove (index);
089     strategiesList.remove(index);
090     fireResourceRemoved(new ControllerEvent(this, 
091             ControllerEvent.RESOURCE_REMOVED, aPr));
092     return aPr;
093   }
094 
095   @Override
096   public boolean remove(ProcessingResource pr){
097     int index = prList.indexOf(pr);
098     if(index != -1){
099       prList.remove(index);
100       strategiesList.remove(index);
101       fireResourceRemoved(new ControllerEvent(this, 
102               ControllerEvent.RESOURCE_REMOVED, pr));
103       return true;
104     }
105     return false;
106   }
107 
108   public void setRunningStrategy(int index, AnalyserRunningStrategy strategy){
109     strategiesList.set(index, strategy);
110   }
111 
112   /**
113    * Populates this controller with the appropiate running strategies from a
114    * collection of running strategies
115    * (optional operation).
116    *
117    * Controllers that are serializable must implement this method needed by GATE
118    * to restore their contents.
119    @throws UnsupportedOperationException if the <tt>setPRs</tt> method
120    *          is not supported by this controller.
121    */
122   @Override
123   public void setRunningStrategies(Collection<RunningStrategy> strategies){
124     strategiesList.clear();
125     Iterator<RunningStrategy> stratIter = strategies.iterator();
126     while(stratIter.hasNext()) strategiesList.add(stratIter.next());
127   }
128 
129   /**
130    * Executes a {@link ProcessingResource}.
131    */
132   @Override
133   protected void runComponent(int componentIndexthrows ExecutionException{
134     ProcessingResource currentPR = prList.get(componentIndex);
135 
136     //create the listeners
137     //FeatureMap listeners = Factory.newFeatureMap();
138     Map<String, Object> listeners = new HashMap<String, Object>();
139     listeners.put("gate.event.StatusListener", sListener);
140     int componentProgress = 100 / prList.size();
141     listeners.put("gate.event.ProgressListener",
142                   new IntervalProgressListener(
143                           componentIndex * componentProgress,
144                           (componentIndex +1* componentProgress)
145                   );
146 
147     //add the listeners
148     try{
149       AbstractResource.setResourceListeners(currentPR, listeners);
150     }catch(Exception e){
151       // the listeners setting failed; nothing important
152       Err.prln("Could not set listeners for " + currentPR.getClass().getName() +
153                "\n" + e.toString() "\n...nothing to lose any sleep over.");
154     }
155 
156 
157     //run the thing
158     if(strategiesList.get(componentIndex).shouldRun()){
159       benchmarkFeatures.put(Benchmark.PR_NAME_FEATURE, currentPR.getName());
160 
161       long startTime = System.currentTimeMillis();
162       // run the thing
163       Benchmark.executeWithBenchmarking(currentPR,
164               Benchmark.createBenchmarkId(Benchmark.PR_PREFIX + currentPR.getName(),
165                       getBenchmarkId()), this, benchmarkFeatures);
166 
167       benchmarkFeatures.remove(Benchmark.PR_NAME_FEATURE);
168       
169       // calculate the time taken by the PR
170       long timeTakenByThePR = System.currentTimeMillis() - startTime;
171       Long time = prTimeMap.get(currentPR.getName());
172       if(time == null) {
173         time = new Long(0);
174       }
175       time = new Long(time.longValue() + timeTakenByThePR);
176       prTimeMap.put(currentPR.getName(), time);
177     }
178 
179 
180     //remove the listeners
181     try{
182       AbstractResource.removeResourceListeners(currentPR, listeners);
183     }catch(Exception e){
184       // the listeners removing failed; nothing important
185       Err.prln("Could not clear listeners for " +
186                currentPR.getClass().getName() +
187                "\n" + e.toString() "\n...nothing to lose any sleep over.");
188     }
189   }//protected void runComponent(int componentIndex)
190 
191   /**
192    * Cleans the internal data and prepares this object to be collected
193    */
194   @Override
195   public void cleanup(){
196     super.cleanup();
197     strategiesList.clear();
198   }
199 
200   /**
201    * Custom duplication method for conditional controllers to handle
202    * duplicating the running strategies.
203    */
204   @Override
205   public Resource duplicate(Factory.DuplicationContext ctx)
206           throws ResourceInstantiationException {
207     ConditionalController c = (ConditionalController)super.duplicate(ctx);
208     Collection<ProcessingResource> newPRs = c.getPRs();
209     List<RunningStrategy> newStrategies = new ArrayList<RunningStrategy>(
210             strategiesList.size());
211     Iterator<RunningStrategy> oldRSIt = getRunningStrategies().iterator();
212     Iterator<ProcessingResource> prIt = newPRs.iterator();
213     while(oldRSIt.hasNext()) {
214       RunningStrategy oldStrat = oldRSIt.next();
215       ProcessingResource currentPR = prIt.next();
216       if(oldStrat instanceof AnalyserRunningStrategy) {
217         newStrategies.add(new AnalyserRunningStrategy(
218                 (LanguageAnalyser)currentPR,
219                 ((AnalyserRunningStrategy)oldStrat).getRunMode(),
220                 ((AnalyserRunningStrategy)oldStrat).getFeatureName(),
221                 ((AnalyserRunningStrategy)oldStrat).getFeatureValue()));
222       }
223       else {
224         boolean run = true;
225         if(oldStrat instanceof UnconditionalRunningStrategy) {
226           run = oldStrat.shouldRun();
227         }
228         // assume an unconditional strategy.  Subclasses that know about other types
229         // of strategies can fix this up later
230         newStrategies.add(new RunningStrategy.UnconditionalRunningStrategy(currentPR, run));
231       }
232     }
233     c.setRunningStrategies(newStrategies);
234     
235     return c;
236   }
237 
238   /**
239    * The list of running strategies for the member PRs.
240    */
241   protected List<RunningStrategy> strategiesList;
242 // class SerialController