1
2
3
4
5
6
7
8
9
10
11 package org.astrogrid.portal.workflow.intf;
12
13 import org.astrogrid.applications.beans.v1.ApplicationBase;
14 import org.astrogrid.applications.beans.v1.Interface;
15 import org.astrogrid.applications.beans.v1.InterfacesType;
16 import org.astrogrid.applications.beans.v1.ParameterRef;
17 import org.astrogrid.applications.beans.v1.Parameters;
18 import org.astrogrid.applications.beans.v1.parameters.BaseParameterDefinition;
19 import org.astrogrid.applications.beans.v1.parameters.ParameterValue;
20 import org.astrogrid.common.bean.BaseBean;
21 import org.astrogrid.workflow.beans.v1.Input;
22 import org.astrogrid.workflow.beans.v1.Output;
23 import org.astrogrid.workflow.beans.v1.Tool;
24
25 import org.exolab.castor.types.AnyNode;
26 import org.exolab.castor.xml.ValidationException;
27 import org.w3c.dom.Element;
28
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.Map;
32
33 /*** Description of an application
34 * <p>
35 * This class provides access to the descriptor of an application - by wrapping a {@link org.astrogrid.applications.beans.v1.ApplicationBase} object.
36 * <ul>
37 * <li>{@link #getInterfaces}
38 * <li>{@link #getName}
39 * <li>{@link #getParameters}
40 * </ul>
41 *
42 * <p>
43 * It also provides methods to create a new workflow {@link org.astrogrid.workflow.beans.v1.Tool} object that can be used to call the application this class describes
44 * <ul>
45 * <li>{@link #createToolFromDefaultInterface}
46 * <li>{@link #createToolFromInterface}
47 * </ul>
48 *
49 * <p>
50 * ParameterValues can be added to a <tt>Tool</tt> by hand, with the assistance of these methods:
51 * <ul>
52 * <li>{@link c#reateValueFromDefinition}
53 * <li>{@link #getDefinitionForValue}
54 * <li>{@link #getReferenceForValue}
55 * <li>{@link #getDefinitionForReference}
56 * </ul>
57 *
58 * <p>
59 * Finally, a Tool object can be checked that it conforms to the application description by calling the {@link #validate} method
60 * @author Noel Winstanley nw@jb.man.ac.uk 09-Mar-2004
61 * @modified Noel Winstanley - add method and constructor to access original DOM.
62 *
63 */
64 public class ApplicationDescription {
65 /*** Construct a new ApplicationDescription
66 *
67 */
68 public ApplicationDescription(ApplicationBase app) {
69 this(app,null);
70
71 }
72
73 /***
74 * Construct a new ApplicationDescription
75 * @param app the application base object
76 * @param voDesc the defining registry entry - i.e. a vodescrption.
77 */
78 public ApplicationDescription(ApplicationBase app, Element voDesc) {
79 this.app = app;
80 this.paramMap = populateParamMap(app);
81 this.voDesc = voDesc;
82 }
83
84 private final ApplicationBase app;
85 private final Map paramMap;
86 private final Element voDesc;
87
88 private final Map populateParamMap(ApplicationBase app){
89 Map m = new HashMap();
90 Parameters params = app.getParameters();
91 for (int i = 0; i < params.getParameterCount(); i++) {
92 BaseParameterDefinition param = params.getParameter(i);
93 m.put(param.getName(),param);
94 }
95 return m;
96 }
97
98 /*** interfaces contain a bunch of 'ParameterRef' objects, that reference 'BaseParameterDefinitions' that are defined elsewhere, and give the type, user interface
99 * description, etc of the paramter. This method will get a definition for a parameter reference
100 * @param parameterRef the reference to look up
101 * @return the associated parameter definition.
102 * @throws IllegalArgumentException when asked to find definition for a reference that is not in the application description.
103 */
104 public BaseParameterDefinition getDefinitionForReference(ParameterRef parameterRef) throws IllegalArgumentException {
105 BaseParameterDefinition result = (BaseParameterDefinition)paramMap.get(parameterRef.getRef());
106 if (result == null) {
107 throw new IllegalArgumentException("ParameterRef " + parameterRef.getRef() + " not found in this application description");
108 }
109 return result;
110 }
111
112 /*** find the parameter reference assocuated with a parameter value in a particular interface*/
113 public ParameterRef getReferenceForValue(ParameterValue paramVal, Interface intf) throws IllegalArgumentException {
114 ParameterRef[] refs = intf.getInput().getPref();
115 String name = paramVal.getName();
116 if (name == null || name.trim().length() == 0) {
117 throw new IllegalArgumentException("Empty name in this parameter value");
118 }
119 for (int i = 0; i < refs.length; i++) {
120 if (refs[i].getRef().equals(name)) {
121 return refs[i];
122 }
123 }
124
125 refs = intf.getOutput().getPref();
126 for (int i = 0; i < refs.length; i++) {
127 if (refs[i].getRef().equals(name)) {
128 return refs[i];
129 }
130 }
131
132 throw new IllegalArgumentException("ParameterValue " + paramVal.getName() + "not found in this interface");
133 }
134
135 /*** convenience method to get a parameter definition for a parameter value.
136 * <p>
137 * equivalent to <tt> getDefinitionForReference(getReferenceForValue(p,i))</tt>
138 * @param paramVal
139 * @param intf
140 * @return
141 * @throws IllegalArgumentException
142 */
143 public BaseParameterDefinition getDefinitionForValue(ParameterValue paramVal, Interface intf) throws IllegalArgumentException {
144 return getDefinitionForReference(getReferenceForValue(paramVal,intf));
145 }
146
147
148 /*** from a definition of a parameter, create a new, initialized parameter value.
149 *
150 * @param defn definition of the parameter
151 * @return a parameter value with name, type initialized. if <tt>defn</tt> provides a defaultValue, this is set as <tt>content</tt>
152 * @todo check this still works.
153 */
154 public ParameterValue createValueFromDefinition(BaseParameterDefinition defn) {
155 ParameterValue paramVal = new ParameterValue();
156 paramVal.setName(defn.getName());
157 Object o= defn.getDefaultValue();
158 if (o != null) {
159 if (o instanceof AnyNode) {
160 AnyNode any = (AnyNode)o;
161 paramVal.setValue(any.getStringValue());
162 } else {
163 paramVal.setValue(o.toString());
164 }
165 } else {
166 paramVal.setValue("");
167 }
168 return paramVal;
169 }
170
171
172 /*** construct a new, initialized tool from the default (first) interface in the application descriptor */
173 public Tool createToolFromDefaultInterface() {
174 return createToolFromInterface(app.getInterfaces().get_interface(0));
175 }
176
177
178 /*** construct a new, initialized tool from an interface in this application descriptor
179 * @param intf the interface to create a tool instance from
180 * @return a populated tool object
181 * @throws IllegalArgumentException if the interface does not belong to this application description.*/
182 public Tool createToolFromInterface(Interface intf) throws IllegalArgumentException {
183 Tool t = new Tool();
184 t.setInterface(intf.getName());
185 t.setName(app.getName());
186 Input input = new Input();
187 Output output = new Output();
188 t.setInput(input);
189 t.setOutput(output);
190
191 ParameterRef[] parameterRefs = intf.getInput().getPref();
192 for (int i = 0; i < parameterRefs.length; i++) {
193 ParameterRef paramRef = parameterRefs[i];
194 BaseParameterDefinition paramDef = getDefinitionForReference(paramRef);
195 ParameterValue paramVal = createValueFromDefinition(paramDef);
196 input.addParameter(paramVal);
197 }
198
199 parameterRefs = intf.getOutput().getPref();
200 for (int i = 0; i < parameterRefs.length; i++) {
201 ParameterRef paramRef = parameterRefs[i];
202 BaseParameterDefinition paramDef = getDefinitionForReference(paramRef);
203 ParameterValue paramVal = createValueFromDefinition(paramDef);
204 output.addParameter(paramVal);
205 }
206
207 return t;
208 }
209
210 /*** verify that a tool object matches what is expected by the application (as defined by this descriptor)
211 * <p>
212 * at moment, checks against information in the application description. in future, could access web services to resolve ucds, or check url parameters, etc.
213 */
214 public void validate(Tool t) throws ToolValidationException{
215
216 try {
217 t.validate();
218 } catch (ValidationException e) {
219 throw new ToolValidationException(e);
220 }
221
222 Interface[] intfs = getInterfaces().get_interface();
223 Interface intf = null;
224 for (int i = 0; i < intfs.length; i++) {
225 if (intfs[i].getName().equals(t.getInterface())) {
226 intf = intfs[i];
227 }
228 }
229 if (intf == null) {
230 throw new ToolValidationException("Interface " + t.getInterface() + " not found");
231 }
232
233 ParameterRef[] refs = intf.getInput().getPref();
234 BaseBean searchRoot = t.getInput();
235 for (int i =0; i < refs.length; i++) {
236 validateReference(refs[i],searchRoot);
237 }
238
239 refs = intf.getOutput().getPref();
240 searchRoot = t.getOutput();
241 for (int i =0; i < refs.length; i++) {
242 validateReference(refs[i],searchRoot);
243 }
244 }
245
246 private void validateReference(ParameterRef reference,BaseBean searchRoot) throws ToolValidationException {
247 Iterator results = searchRoot.findXPathIterator("/parameter[name = '" + reference.getRef() + "']");
248 try {
249 BaseParameterDefinition paramDef = getDefinitionForReference(reference);
250 int occurenceCount = 0;
251 while( results.hasNext()) {
252 occurenceCount ++;
253 ParameterValue val = (ParameterValue)results.next();
254
255 }
256
257
258 if (occurenceCount < reference.getMinoccurs() ||
259 (reference.getMaxoccurs() != 0 ?occurenceCount > reference.getMaxoccurs():false)) {
260 throw new ToolValidationException("Parameter " + reference.getRef() + " occurs " + occurenceCount
261 + ". Should occur between " + reference.getMinoccurs() + " and " + reference.getMaxoccurs() + " times");
262 }
263
264 } catch (IllegalArgumentException e) {
265 throw new ToolValidationException(e);
266 }
267 }
268
269
270 /***
271 * @see org.astrogrid.applications.beans.v1.ApplicationBase#getInterfaces()
272 */
273 public InterfacesType getInterfaces() {
274 return app.getInterfaces();
275 }
276
277 /***
278 * @see org.astrogrid.applications.beans.v1.ApplicationBase#getName()
279 */
280 public String getName() {
281 return app.getName();
282 }
283
284 /***
285 * @see org.astrogrid.applications.beans.v1.ApplicationBase#getParameters()
286 */
287 public Parameters getParameters() {
288 return app.getParameters();
289 }
290
291 /*** access the xml of the original registry entry that defines this Application
292 * @return dom of registry entry. may be null; if not, root element will be <tt><VODescription></tt>
293 *
294 * @author Noel Winstanley nw@jb.man.ac.uk 28-Oct-2004
295 *
296 */
297 public Element getOriginalVODescription() {
298 return voDesc;
299 }
300
301 }
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339