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