001/*
002 * Copyright (c) 1998-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2012-11-26 22:19:36 +0000 (Mon, 26 Nov 2012) $' 
007 * '$Revision: 31113 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.sdm.spa;
031
032import java.util.Iterator;
033import java.util.List;
034import java.util.Vector;
035
036import ptolemy.actor.IOPort;
037import ptolemy.actor.TypedAtomicActor;
038import ptolemy.actor.TypedIOPort;
039import ptolemy.data.ArrayToken;
040import ptolemy.data.ObjectToken;
041import ptolemy.data.Token;
042import ptolemy.data.expr.StringParameter;
043import ptolemy.data.type.ArrayType;
044import ptolemy.data.type.BaseType;
045import ptolemy.data.type.BaseType.BooleanType;
046import ptolemy.data.type.BaseType.DoubleType;
047import ptolemy.data.type.BaseType.IntType;
048import ptolemy.data.type.BaseType.LongType;
049import ptolemy.data.type.BaseType.StringType;
050import ptolemy.data.type.BaseType.UnsignedByteType;
051import ptolemy.data.type.Type;
052import ptolemy.gui.GraphicalMessageHandler;
053import ptolemy.kernel.CompositeEntity;
054import ptolemy.kernel.util.Attribute;
055import ptolemy.kernel.util.IllegalActionException;
056import ptolemy.kernel.util.NameDuplicationException;
057
058///////////////////////////////////////////////////////////////
059////SoaplabChooseOperation
060/**
061 * <p>
062 * The following actor is for choosing set_&lt;name&gt; operations for executing
063 * any derived web service registered at EBI. The following actor takes in an
064 * input values to serve as parameters for the set_&lt;name&gt; web service
065 * operation. The actor asks the user to choose the desired set_&lt;name&gt;
066 * operation. The inputValues and set_&lt;name&gt; operation name are further
067 * forwarded to the next actor SoaplabServiceStarter.
068 * </p>
069 * 
070 * @author Nandita Mangal
071 * @version $Id: SoaplabChooseOperation.java, v 1.0 2005/19/07
072 * @category.name web
073 * @category.name external execution
074 */
075
076public class SoaplabChooseOperation extends TypedAtomicActor {
077
078        /**
079         * Construct a SoaplabChooseOperation actor with given container and name.
080         * 
081         * @param container
082         *            The container.
083         * @param name
084         *            The name of this actor.
085         * @exception NameDuplicationException
086         *                If the container already has an actor with this name
087         */
088
089        public SoaplabChooseOperation(CompositeEntity container, String name)
090                        throws NameDuplicationException, IllegalActionException {
091                super(container, name);
092
093                wsdlUrl = new StringParameter(this, "wsdlUrl");
094                selectInputSetMethods = new StringParameter(this, "inputSetMethods");
095
096                input = new TypedIOPort(this, "input", true, false);
097                input.setTypeEquals(BaseType.UNKNOWN); // type of input value expected
098                                                                                                // is not known yet
099
100                output = new TypedIOPort(this, "output", false, true);
101                output.setTypeEquals(BaseType.OBJECT);
102
103                _attachText("_iconDescription", "<svg>\n" + "<rect x=\"0\" y=\"0\" "
104                                + "width=\"60\" height=\"30\" " + "style=\"fill:white\"/>\n"
105                                + "</svg>\n");
106        }
107
108        // //////////////////////////////////////////////////////////////////////////////
109        // // Ports and Parameters ////
110
111        /**
112         * The web service URL which is registered at EBI
113         */
114        public StringParameter wsdlUrl = null;
115
116        /**
117         * The standard "set_&lt;name&gt;" method choices for SoaplabServices
118         */
119        public StringParameter selectInputSetMethods = null;
120
121        /**
122         * Outputs the username and input values to next actor namely
123         * "SoaplabServiceStarter"
124         */
125        public TypedIOPort output;
126
127        /**
128         * The parameters for the "set_&lt;name&gt;" operations
129         */
130        public TypedIOPort input;
131
132        // //////////////////////////////////////////////////////////////////////////////
133        // // public Methods ////
134
135        /**
136         * Callback for changes in attribute values Get the WSDL from the given URL.
137         * 
138         * @param at
139         *            The attribute that changed.
140         * @exception IllegalActionException
141         */
142        public void attributeChanged(Attribute at) throws IllegalActionException {
143
144                if (at == wsdlUrl) {
145
146                        if (wsdlUrl.getExpression().equals("")) {
147                                selectInputSetMethods.removeAllChoices();
148                        } else {
149                                selectInputSetMethods.removeAllChoices();
150                                try {
151
152                                        // NOTE:- The following client is just created for geting
153                                        // the WSDL input methods
154                                        // in the very first stage of the workflow beforehand.The
155                                        // client created at this
156                                        // stage is not utilized after getting the required
157                                        // inputMethods.
158
159                                        SoaplabServiceClient client = new SoaplabServiceClient(
160                                                        wsdlUrl.getExpression());
161                                        client.setJobId(); // create Job in order to be able to
162                                                                                // generate input method names
163                                        client.generateInputMethods(); // get the set_&lt;name&gt;
164                                                                                                        // operations
165                                        Vector inputMethods = client.getInputMethods();
166                                        for (int i = 0; i < inputMethods.size(); i++) {
167                                                selectInputSetMethods.addChoice("set_"
168                                                                + (String) (inputMethods.elementAt(i)));
169                                        }
170
171                                } catch (Exception ex) {
172                                        _debug("<EXCEPTION> There was an error while parsing the WSDL. "
173                                                        + ex + ". </EXCEPTION>");
174                                        // GraphicalMessageHandler.message(
175                                        _confErrorStr += "\n"
176                                                        + ex.getMessage()
177                                                        + "There was an error while parsing the WSDL in the actor: "
178                                                        + this.getName();// );
179                                }
180
181                                if (!(_confErrorStr.equals(""))) {
182                                        GraphicalMessageHandler.message(_confErrorStr);
183
184                                }
185                        }
186
187                }
188
189        } // end of attributeChanged
190
191        /**
192         * Gets a list of input ports configured with the actor and finally outputs
193         * an object containing all the inputValues for the set_&lt;name&gt;
194         * operation as well as name of operation itself.
195         * 
196         * @exception IllegalActionException
197         *                If there is no director.
198         */
199
200        public void fire() throws IllegalActionException {
201
202                super.fire();
203
204                // a vector to contain all user input data such as operation
205                // name,operation input values
206                Vector userInputs = new Vector();
207
208                List inPortList = this.inputPortList();
209                Iterator ports = inPortList.iterator();
210
211                while (ports.hasNext()) {
212
213                        IOPort p = (IOPort) ports.next();
214                        List connections = p.connectedPortList();
215                        if (!(connections.isEmpty())) {
216
217                                if (wsdlUrl.getExpression().equals(""))
218                                        GraphicalMessageHandler.message("\nWSDL is empty in actor:"
219                                                        + this.getName());
220                                else if (selectInputSetMethods.getExpression().equals(""))
221                                        GraphicalMessageHandler
222                                                        .message("\nSet Method is empty in actor:"
223                                                                        + this.getName());
224
225                                Token originalToken = p.get(0); // getInputVaulue
226                                Object tokenObjectForm = _getTokenConvertedObject(originalToken); // get
227                                                                                                                                                                        // the
228                                                                                                                                                                        // Java
229                                                                                                                                                                        // object
230                                                                                                                                                                        // form
231                                                                                                                                                                        // of
232                                                                                                                                                                        // input
233                                                                                                                                                                        // Token
234                                userInputs.add(tokenObjectForm);
235
236                        }
237
238                }
239                userInputs.add(selectInputSetMethods.getExpression()); // add the
240                                                                                                                                // set_&lt;name&gt;
241                                                                                                                                // operation
242                                                                                                                                // name
243                output.broadcast(new ObjectToken(userInputs)); // braodcast the object
244                                                                                                                // consisting of input
245                                                                                                                // values + operation
246                                                                                                                // name.
247
248        }// end of fire
249
250        /**
251         * Before executing the actor, delete any unconnected input ports to the
252         * actor done in order to prevent possible SDF disconnected graphs problem
253         * for users.
254         */
255        public boolean prefire() throws IllegalActionException {
256
257                List inPortList = this.inputPortList();
258                Iterator ports = inPortList.iterator();
259
260                while (ports.hasNext()) {
261
262                        IOPort p = (IOPort) ports.next();
263                        List connections = p.connectedPortList();
264                        if (connections.isEmpty()) {
265                                // delete the empty/unconnected port
266                                try {
267                                        p.setContainer(null);
268                                } catch (Exception ex) {
269                                        // Exceptions: IllegalAction or NameDuplicationException
270                                        _debug("<EXCEPTION> There was an error while attempting to delete unused ports "
271                                                        + ex + ". </EXCEPTION>");
272                                        _confErrorStr += "\n"
273                                                        + ex.getMessage()
274                                                        + "There was an error while deleting the unused input ports of the actor."
275                                                        + this.getName();// );
276                                }
277                        }
278                }
279
280                return super.prefire();
281
282        } // end of prefire
283
284        // //////////////////////////////////////////////////////////////////
285        // // private Methods ///
286
287        /**
288         * Given a token recieved from the input ports, the following attempts to
289         * get the token Value and convert it to a java Object form.
290         * 
291         * @param portToken
292         *            The input Token retrieved from the input port
293         */
294
295        private Object _getTokenConvertedObject(Token portToken) {
296
297                if (portToken.getType() instanceof BooleanType) {
298                        return new Boolean(portToken.toString());
299                } else if (portToken.getType() instanceof IntType) {
300                        return new Integer(portToken.toString());
301                } else if (portToken.getType() instanceof LongType) {
302                        return new Long(portToken.toString());
303                } else if (portToken.getType() instanceof StringType) {
304                        String returnValueStr = portToken.toString();
305                        String suffix = "\"";
306                        // extra step to delete the "" quotation prefixes around the string
307                        if (returnValueStr.endsWith(suffix)
308                                        && returnValueStr.startsWith(suffix)) {
309                                return returnValueStr.substring(1,
310                                                (returnValueStr.length()) - 1);
311                        }
312                } else if (portToken.getType() instanceof DoubleType) {
313                        return new Double(portToken.toString());
314                } else if (portToken.getType() instanceof UnsignedByteType) {
315                        // ->There is no byte in Ptolemy type sys. cast the byte to INT.
316                        return new Integer(portToken.toString());
317                } else if (portToken.getType() instanceof ArrayType) {
318
319                        // get the type of elements inside the ArrayToken
320                        Type tokenType = ((ArrayToken) portToken).getElementType();
321
322                        if (tokenType instanceof BooleanType) {
323
324                                Boolean arrayBool[] = new Boolean[((ArrayToken) portToken)
325                                                .length()];
326                                for (int i = 0; i < ((ArrayToken) portToken).length(); i++) {
327                                        arrayBool[i] = new Boolean((((ArrayToken) portToken)
328                                                        .getElement(i)).toString());
329                                }
330                                return arrayBool;
331                        } else if (tokenType instanceof IntType) {
332
333                                Integer arrayInt[] = new Integer[((ArrayToken) portToken)
334                                                .length()];
335                                for (int i = 0; i < ((ArrayToken) portToken).length(); i++) {
336                                        arrayInt[i] = new Integer((((ArrayToken) portToken)
337                                                        .getElement(i)).toString());
338                                }
339                                return arrayInt;
340
341                        } else if (tokenType instanceof LongType) {
342
343                                Long arrayLong[] = new Long[((ArrayToken) portToken).length()];
344                                for (int i = 0; i < ((ArrayToken) portToken).length(); i++) {
345                                        arrayLong[i] = new Long((((ArrayToken) portToken)
346                                                        .getElement(i)).toString());
347                                }
348                                return arrayLong;
349
350                        } else if (tokenType instanceof StringType) {
351
352                                String arrayString[] = new String[((ArrayToken) portToken)
353                                                .length()];
354                                for (int i = 0; i < ((ArrayToken) portToken).length(); i++) {
355                                        // extra step to delete the "" quotation prefixes around the
356                                        // string
357                                        String returnValueStr = (((ArrayToken) portToken)
358                                                        .getElement(i)).toString();
359                                        String suffix = "\"";
360                                        if (returnValueStr.endsWith(suffix)
361                                                        && returnValueStr.startsWith(suffix)) {
362                                                arrayString[i] = returnValueStr.substring(1,
363                                                                (returnValueStr.length()) - 1);
364                                        }
365                                }
366                                return arrayString;
367
368                        } else if (tokenType instanceof DoubleType) {
369
370                                Double arrayDouble[] = new Double[((ArrayToken) portToken)
371                                                .length()];
372                                for (int i = 0; i < ((ArrayToken) portToken).length(); i++) {
373                                        arrayDouble[i] = new Double((((ArrayToken) portToken)
374                                                        .getElement(i)).toString());
375                                }
376                                return arrayDouble;
377
378                        } else if (tokenType instanceof UnsignedByteType) {
379
380                                // ->There is no byte in Ptolemy type sys. cast the byte to INT.
381                                Integer arrayInt[] = new Integer[((ArrayToken) portToken)
382                                                .length()];
383                                for (int i = 0; i < ((ArrayToken) portToken).length(); i++) {
384                                        arrayInt[i] = new Integer((((ArrayToken) portToken)
385                                                        .getElement(i)).toString());
386                                }
387                                return arrayInt;
388
389                        }
390                } else {
391                        _debug("<WARNING>Could not convert the token to appropriate java Object.Setting it to string. </WARNING>");
392                }
393
394                return new String(portToken.toString());
395        } // end of _getTokenConvertedObject
396
397        // ////////////////////////////////////////////////////////////////////////////
398        // // private variables ////
399
400        protected String _confErrorStr = "";
401
402}// end of SoaplabChooseOperation