001/*
002 * Copyright (c) 1998-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
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.ObjectToken;
040import ptolemy.data.expr.StringParameter;
041import ptolemy.data.type.BaseType;
042import ptolemy.gui.GraphicalMessageHandler;
043import ptolemy.kernel.CompositeEntity;
044import ptolemy.kernel.util.Attribute;
045import ptolemy.kernel.util.IllegalActionException;
046import ptolemy.kernel.util.NameDuplicationException;
047
048///////////////////////////////////////////////////////////////
049////SoaplabServiceStarter
050/**
051 * The following actor is for creating the soaplab client as well as setting the
052 * client's set_<name> operations with appropriate values.The output is
053 * the soaplab service client itself, forwarded to other others such as
054 * SoaplabAnalysis
055 * 
056 * @author Nandita Mangal
057 * @version $Id: SoaplabServiceStarter.java, v 1.0 2005/19/07
058 * @category.name web
059 * @category.name external execution
060 */
061
062public class SoaplabServiceStarter extends TypedAtomicActor {
063
064        /**
065         * Construct a SoaplabServiceStarter actor with given container and name.
066         * 
067         * @param container
068         *            The container.
069         * @param name
070         *            The name of this actor.
071         * @exception NameDuplicationException
072         *                If the container already has an actor with this name
073         */
074        public SoaplabServiceStarter(CompositeEntity container, String name)
075                        throws NameDuplicationException, IllegalActionException {
076
077                super(container, name);
078
079                wsdlUrl = new StringParameter(this, "wsdlUrl");
080
081                setOperation1 = new TypedIOPort(this, "setOperation1", true, false);
082                setOperation1.setTypeEquals(BaseType.OBJECT);
083
084                output = new TypedIOPort(this, "output", false, true);
085                output.setTypeEquals(BaseType.OBJECT);
086
087                _attachText("_iconDescription", "<svg>\n" + "<rect x=\"0\" y=\"0\" "
088                                + "width=\"60\" height=\"30\" " + "style=\"fill:white\"/>\n"
089                                + "</svg>\n");
090        }
091
092        // ///////////////////////////////////////////////////////////////////
093        // // Ports and Parameters ////
094        /**
095         * The web service URL which is registered at EBI
096         */
097        public StringParameter wsdlUrl = null;
098
099        private StringParameter inputMethods = null;
100
101        /**
102         * Errors encountered while parsing WSDL/setting set_&lt;name&gt; operations
103         */
104        public TypedIOPort clientExecErrors;
105
106        /**
107         * The output is the soaplab service client itself, forwarded to other
108         * others such as SoaplabAnalysis
109         */
110        public TypedIOPort output;
111
112        /**
113         * Setting set_&lt;name&gt; operations with appropriate input values.
114         */
115        public TypedIOPort setOperation1;
116
117        // /////////////////////////////////////////////////////////////////////
118        // // public Methods ////
119
120        /**
121         * Callback for changes in attribute values Get the WSDL from the given URL.
122         * 
123         * @param at
124         *            The attribute that changed.
125         * @exception IllegalActionException
126         */
127
128        public void attributeChanged(Attribute at) throws IllegalActionException {
129                if (at == wsdlUrl) {
130
131                        if (wsdlUrl.getExpression().equals("")) {
132                                // do nothing
133                        } else {
134                                try {
135
136                                        // Create the actual soaplab service client to be used by
137                                        // this
138                                        // as well as forwarded to other soaplab actors in later
139                                        // stages
140                                        // of the workflow
141                                        client = new SoaplabServiceClient(wsdlUrl.getExpression());
142                                        client.setJobId();
143                                } catch (Exception ex) {
144                                        _debug("<EXCEPTION> There was an error while parsing the WSDL. "
145                                                        + ex + ". </EXCEPTION>");
146                                        // GraphicalMessageHandler.message(
147                                        _confErrorStr += "\n"
148                                                        + ex.getMessage()
149                                                        + "There was an error while parsing the WSDL in the actor: "
150                                                        + this.getName();// );
151                                }
152
153                        }
154
155                        if (!(_confErrorStr.equals(""))) {
156                                GraphicalMessageHandler.message(_confErrorStr);
157
158                        }
159
160                }
161
162        } // end of attributeChanged
163
164        /**
165         * For each of the connected input port, retrieve the input Values from the
166         * port ( an object containing the set_&lt;name&gt; operation as well its
167         * respective input Values). Perform the call for setting the above
168         * set_&lt;name&gt; operations with the client.
169         * 
170         * @exception IllegalActionException
171         *                If there is no director.
172         */
173
174        public void fire() throws IllegalActionException {
175
176                super.fire();
177                try {
178
179                        List inPortList = this.inputPortList();
180                        Iterator ports = inPortList.iterator();
181
182                        while (ports.hasNext()) {
183
184                                IOPort p = (IOPort) ports.next();
185                                List connections = p.connectedPortList();
186                                if (!(connections.isEmpty())) {
187                                        if (wsdlUrl.getExpression().equals("")) {
188                                                GraphicalMessageHandler
189                                                                .message("WebService WSDL is empty in actor:"
190                                                                                + this.getName());
191                                        }
192                                        Vector input = (Vector) (((ObjectToken) (p.get(0)))
193                                                        .getValue());
194                                        String setOperationName = (String) (input.lastElement());
195                                        input.removeElementAt(input.size() - 1); // remove
196                                                                                                                                // set_&lt;name&gt;
197                                                                                                                                // from the
198                                                                                                                                // inputValues
199                                        if (input.size() == 1)
200                                                client.doCall(new String(setOperationName),
201                                                                new Object[] { client.getJobId(),
202                                                                                input.elementAt(0) });
203
204                                        else // more than one input value to the set operation
205                                        {
206                                                Object[] params = new Object[input.size() + 1];
207                                                params[0] = (Object) (client.getJobId());
208                                                for (int i = 0; i < input.size(); i++) {
209                                                        params[i + 1] = (Object) (input.elementAt(i));
210                                                }
211                                                client.doCall(new String(setOperationName), params);
212                                        }
213                                }
214
215                        }
216
217                        // forward the client to other states in the workflow
218                        ObjectToken aboveClient = new ObjectToken(client);
219                        output.broadcast(aboveClient);
220
221                } catch (Exception ex) {
222                        _debug("<EXCEPTION> There was an error executing the web service operation "
223                                        + ex + ". </EXCEPTION>");
224                        // GraphicalMessageHandler.message(
225                        _confErrorStr += "\n" + ex.getMessage()
226                                        + "There was an error executing the web service operation"
227                                        + this.getName();// );
228                }
229
230                if (!(_confErrorStr.equals(""))) {
231                        GraphicalMessageHandler.message(_confErrorStr);
232
233                }
234
235        } // end of fire
236
237        /**
238         * Before executing the actor, delete any unconnected input ports to the
239         * actor done in order to prevent possible SDF disconnected graphs problem
240         * for users.
241         */
242        public boolean prefire() throws IllegalActionException {
243
244                List inPortList = this.inputPortList();
245                Iterator ports = inPortList.iterator();
246
247                while (ports.hasNext()) {
248
249                        IOPort p = (IOPort) ports.next();
250                        List connections = p.connectedPortList();
251                        if (connections.isEmpty()) {
252                                // delete the empty/unconnected port
253                                try {
254                                        p.setContainer(null);
255                                } catch (Exception ex) {
256                                        // Exceptions: IllegalAction or NameDuplicationException
257                                        _debug("<EXCEPTION> There was an error while attempting to delete unused ports "
258                                                        + ex + ". </EXCEPTION>");
259                                        _confErrorStr += "\n"
260                                                        + ex.getMessage()
261                                                        + "There was an error while deleting the unused input ports of the actor."
262                                                        + this.getName();// );
263                                }
264                        }
265                }
266
267                return super.prefire();
268
269        } // end of prefire
270
271        // ////////////////////////////////////////////////////////////////////
272        // // private methods ////
273
274        private SoaplabServiceClient client;
275        protected String _confErrorStr = "";
276
277} // end of SoaplabServiceStarter