TeamwareUtils.java
001 /*
002  *  Copyright (c) 1995-2010, 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  *  Ian Roberts 14/02/2009
011  *
012  *  $Id: TeamwareUtils.java 12006 2009-12-01 17:24:28Z thomas_heitz $
013  *
014  */
015 
016 package gate.gui.teamware;
017 
018 import gate.Controller;
019 import gate.Gate;
020 import gate.ProcessingResource;
021 import gate.creole.Parameter;
022 import gate.creole.ResourceData;
023 
024 import java.util.Collection;
025 import java.util.HashSet;
026 import java.util.List;
027 import java.util.Set;
028 
029 /**
030  * Class containing utility methods for GATE teamware.
031  */
032 public class TeamwareUtils {
033 
034   public static final String INPUT_ANNOTATION_SETS_FEATURE = "gate.teamware.inputAnnotationSets";
035 
036   public static final String OUTPUT_ANNOTATION_SETS_FEATURE = "gate.teamware.outputAnnotationSets";
037 
038   /**
039    * Private constructor - this class should not be instantiated.
040    */
041   private TeamwareUtils() {
042 
043   }
044 
045   /**
046    * Get the set of annotation set names that an application requires
047    * for input. If the controller does not yet have a set of input
048    * annotation set names, an initial one is constructed using some
049    * simple heuristics. The returned set is a reference to the
050    * controller's stored set of annotation set names, and changes will
051    * propagate back to the controller. The set may be empty, and it may
052    * contain a <code>null</code> entry (denoting the default
053    * annotation set).
054    */
055   public static Set<String> getInputAnnotationSets(Controller c) {
056     Object setNamesObj = c.getFeatures().get(INPUT_ANNOTATION_SETS_FEATURE);
057     if(setNamesObj != null && setNamesObj instanceof Set) {
058       return (Set<String>)setNamesObj;
059     }
060     else {
061       Set<String> setNames = new HashSet<String>();
062       c.getFeatures().put(INPUT_ANNOTATION_SETS_FEATURE, setNames);
063       populateInputSetNamesForController(setNames, c, true);
064 
065       return setNames;
066     }
067   }
068 
069   /**
070    * Analyse the given controller and return a list of likely candidate
071    * input annotation sets. The set will not be empty, as it will always
072    * include at least a <code>null</code> entry, denoting the default
073    * annotation set.
074    */
075   public static Set<String> getLikelyInputAnnotationSets(Controller c) {
076     Set<String> likelySets = new HashSet<String>();
077     populateInputSetNamesForController(likelySets, c, false);
078     return likelySets;
079   }
080 
081   /**
082    * Populate the set of input annotation set names for a controller
083    * based on heuristics. In the strict case we assume that if a PR in
084    * the controller has an inputASName parameter whose value is not the
085    * default set, and there is no PR earlier in the pipeline which has
086    * the same set as its outputASName or annotationSetName parameter,
087    * then it is probably a set that needs to be provided externally. In
088    * the non-strict case we simply take all inputASName and
089    * annotationSetName parameter values from the controller's PRs,
090    * without regard for whether they may have been satisfied by an
091    * earlier PR in the pipeline.
092    
093    @param setNames
094    @param c
095    @param strict
096    */
097   private static void populateInputSetNamesForController(Set<String> setNames,
098           Controller c, boolean strict) {
099     Set<String> outputSetNamesSoFar = new HashSet<String>();
100     Collection<ProcessingResource> prs = c.getPRs();
101     try {
102       for(ProcessingResource pr : prs) {
103         ResourceData rd = Gate.getCreoleRegister().get(pr.getClass().getName());
104         List<List<Parameter>> runtimeParams = rd.getParameterList()
105                 .getRuntimeParameters();
106         // check for inputASName and annotationSetName params
107         for(List<Parameter> disjunction : runtimeParams) {
108           for(Parameter param : disjunction) {
109             if(param.getName().equals("inputASName")) {
110               String setName = (String)pr.getParameterValue(param.getName());
111               if(!strict
112                       || (setName != null && !outputSetNamesSoFar
113                               .contains(setName))) {
114                 setNames.add(setName);
115               }
116             }
117             else if(!strict && param.getName().equals("annotationSetName")) {
118               setNames.add((String)pr.getParameterValue(param.getName()));
119             }
120           }
121         }
122 
123         // check for output set names and update that set
124         if(strict) {
125           for(List<Parameter> disjunction : runtimeParams) {
126             for(Parameter param : disjunction) {
127               if(param.getName().equals("outputASName")
128                       || param.getName().equals("annotationSetName")) {
129                 outputSetNamesSoFar.add(String.valueOf(pr
130                         .getParameterValue(param.getName())));
131               }
132             }
133           }
134         }
135       }
136     }
137     catch(Exception e) {
138       // ignore - this is all heuristics, after all
139     }
140   }
141 
142   /**
143    * Get the set of annotation set names that an application uses for
144    * output. If the controller does not yet have a set of output
145    * annotation set names, an initial one is constructed using some
146    * simple heuristics. The returned set is a reference to the
147    * controller's stored set of annotation set names, and changes will
148    * propagate back to the controller. The set may be empty, and it may
149    * contain a <code>null</code> entry (denoting the default
150    * annotation set).
151    */
152   public static Set<String> getOutputAnnotationSets(Controller c) {
153     Object setNamesObj = c.getFeatures().get(OUTPUT_ANNOTATION_SETS_FEATURE);
154     if(setNamesObj != null && setNamesObj instanceof Set) {
155       return (Set<String>)setNamesObj;
156     }
157     else {
158       Set<String> setNames = new HashSet<String>();
159       c.getFeatures().put(OUTPUT_ANNOTATION_SETS_FEATURE, setNames);
160       populateOutputSetNamesForController(setNames, c, true);
161 
162       return setNames;
163     }
164   }
165 
166   /**
167    * Analyse the given controller and return a list of likely candidate
168    * output annotation sets. The set will not be empty, as it will
169    * always include at least a <code>null</code> entry, denoting the
170    * default annotation set.
171    */
172   public static Set<String> getLikelyOutputAnnotationSets(Controller c) {
173     Set<String> likelySets = new HashSet<String>();
174     populateOutputSetNamesForController(likelySets, c, false);
175     return likelySets;
176   }
177 
178   /**
179    * Populate the set of output annotation set names for a controller
180    * based on heuristics. In the strict case, we assume that if a PR in
181    * the controller has an outputASName or annotationSetName parameter
182    * whose value is not used as the inputASName or annotationSetName of
183    * a later PR then it is probably a set that will be output from the
184    * controller. In the non-strict case we simply take all outputASName
185    * and annotationSetName parameter values from the controller's PRs
186    * without regard for which ones may simply be feeding later PRs in
187    * the controller (also, the default annotation set is always included
188    * in non-strict mode).
189    */
190   private static void populateOutputSetNamesForController(Set<String> setNames,
191           Controller c, boolean strict) {
192     Collection<ProcessingResource> prs = c.getPRs();
193     try {
194       for(ProcessingResource pr : prs) {
195         ResourceData rd = Gate.getCreoleRegister().get(pr.getClass().getName());
196         List<List<Parameter>> runtimeParams = rd.getParameterList()
197                 .getRuntimeParameters();
198         // (strict mode) remove any candidates from the list which are
199         // used as the inputASName or annotationSetName of the current
200         // PR.
201         if(strict) {
202           for(List<Parameter> disjunction : runtimeParams) {
203             for(Parameter param : disjunction) {
204               if(param.getName().equals("inputASName")
205                       || param.getName().equals("annotationSetName")) {
206                 setNames.remove(pr.getParameterValue(param.getName()));
207               }
208             }
209           }
210         }
211 
212         // now add all values from outputASName and annotationSetName
213         // parameters
214         for(List<Parameter> disjunction : runtimeParams) {
215           for(Parameter param : disjunction) {
216             if(param.getName().equals("outputASName")
217                     || param.getName().equals("annotationSetName")) {
218               setNames.add((String)pr.getParameterValue(param.getName()));
219             }
220           }
221         }
222       }
223       
224       // finally, add the default set for non-strict mode
225       if(!strict) {
226         setNames.add(null);
227       }
228     }
229     catch(Exception e) {
230       // ignore - this is all heuristics, after all
231     }
232   }
233 }