Package org.apache.airavata.xbaya.modifier

Source Code of org.apache.airavata.xbaya.modifier.WorkflowModifier

/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/

package org.apache.airavata.xbaya.modifier;

import java.awt.Color;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.airavata.common.exception.UtilsException;
import org.apache.airavata.common.utils.WSDLUtil;
import org.apache.airavata.xbaya.XBayaRuntimeException;
import org.apache.airavata.xbaya.component.system.InputComponent;
import org.apache.airavata.xbaya.component.ws.WSComponent;
import org.apache.airavata.xbaya.graph.GraphException;
import org.apache.airavata.xbaya.graph.Node;
import org.apache.airavata.xbaya.graph.Port;
import org.apache.airavata.xbaya.graph.impl.PortImpl;
import org.apache.airavata.xbaya.graph.system.InputNode;
import org.apache.airavata.xbaya.graph.util.GraphUtil;
import org.apache.airavata.xbaya.graph.ws.WSGraph;
import org.apache.airavata.xbaya.graph.ws.WSNode;
import org.apache.airavata.xbaya.graph.ws.WSPort;
import org.apache.airavata.xbaya.monitor.MonitorEvent;
import org.apache.airavata.xbaya.monitor.MonitorEventData;
import org.apache.airavata.xbaya.monitor.MonitorException;
import org.apache.airavata.xbaya.monitor.MonitorUtil;
import org.apache.airavata.xbaya.monitor.MonitorUtil.EventType;
import org.apache.airavata.xbaya.monitor.gui.MonitorEventHandler.NodeState;
import org.apache.airavata.xbaya.wf.Workflow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmlpull.infoset.XmlElement;

import xsul.XmlConstants;
import xsul5.wsdl.WsdlPortTypeOperation;

public class WorkflowModifier {

    private static final Logger logger = LoggerFactory.getLogger(WorkflowModifier.class);

    private Workflow modifiedWorkflow;

    private MonitorEventData eventData;

    /**
     * Constructs a WorkflowModifier.
     *
     * @param modifiedWorkflow
     * @param eventData
     */
    public WorkflowModifier(Workflow modifiedWorkflow, MonitorEventData eventData) {
        this.modifiedWorkflow = modifiedWorkflow;
        this.eventData = eventData;
    }

    /**
     * @return The workflow that needs to be executed.
     * @throws GraphException
     * @throws MonitorException
     */
    public Workflow createDifference() throws GraphException, MonitorException {
        WSGraph originalGraph = this.modifiedWorkflow.getGraph();
        Workflow workflow = this.modifiedWorkflow.clone();
        String name = workflow.getName();
        name += " (diff)";
        workflow.setName(name);
        WSGraph graph = workflow.getGraph();

        // Remove the finished node.
        removeFinishedNodes(originalGraph, graph);

        Set<WSPort> originalFromPorts = getFinalOutputPorts(originalGraph, graph);

        // Create input nodes for unconnected input ports.
        createInputNodes(graph, originalFromPorts);

        // Set default values.
        for (WSPort originalFromPort : originalFromPorts) {
            // TODO handle the case that node is not WSNode.
            Node originalFromNode = originalFromPort.getNode();
            String fromNodeID = originalFromNode.getID();
            String output;
            if (originalFromNode instanceof InputNode) {
                // notification that includes the input of the workflow.
                output = getWorkflowInput(fromNodeID);
            } else if (originalFromNode instanceof WSNode) {
                // Retrieve input value from notification.
                WSComponent component = ((WSNode) originalFromNode).getComponent();
                String messageName = component.getOutputTypeName();
                String parameterName = originalFromPort.getComponentPort().getName();
                output = getOutput(fromNodeID, messageName, parameterName);
            } else {
                // This should not happen.
                throw new XBayaRuntimeException(originalFromNode.getClass().getName());
            }
            Port originalToPort = originalFromPort.getToPorts().get(0);
            PortImpl toPort = graph.getPort(originalToPort.getID());
            InputNode inputNode = (InputNode) toPort.getFromNode();
            inputNode.setDefaultValue(output);
        }

        return workflow;
    }

    /**
     * @param originalGraph
     * @param graph
     * @throws GraphException
     */
    private void removeFinishedNodes(WSGraph originalGraph, WSGraph graph) throws GraphException {
        ArrayList<Node> finishedNodes = new ArrayList<Node>();
        for (Node node : originalGraph.getNodes()) {
            Color color = node.getGUI().getBodyColor();
            if (NodeState.FINISHED.color.equals(color)) {
                finishedNodes.add(node);
            }
        }
        for (Node finishedNode : finishedNodes) {
            Node node = graph.getNode(finishedNode.getID());
            graph.removeNode(node);
        }
    }

    /**
     * @param originalGraph
     * @param graph
     * @return The final output ports.
     */
    private Set<WSPort> getFinalOutputPorts(WSGraph originalGraph, WSGraph graph) {
        Collection<Port> inputPorts = GraphUtil.getPorts(graph, Port.Kind.DATA_IN);
        Set<WSPort> originalFromPorts = new HashSet<WSPort>();
        for (Port inputPort : inputPorts) {
            Port fromPort = inputPort.getFromPort();
            if (fromPort == null) {
                // This input port is not connected.
                String inputPortID = inputPort.getID();
                logger.info("id: " + inputPortID);
                Port originalInputPort = originalGraph.getPort(inputPortID);
                // No duplicate in set.
                Port originalFromPort = originalInputPort.getFromPort();
                originalFromPorts.add((WSPort) originalFromPort);
            }
        }
        return originalFromPorts;
    }

    /**
     * @param graph
     * @param originalFromPorts
     * @throws GraphException
     */
    private void createInputNodes(WSGraph graph, Set<WSPort> originalFromPorts) throws GraphException {
        InputComponent inputComponent = new InputComponent();
        for (WSPort originalFromPort : originalFromPorts) {
            InputNode inputNode = inputComponent.createNode(graph);
            List<Port> originalToPorts = originalFromPort.getToPorts();
            boolean first = true;
            for (Port originalToPort : originalToPorts) {
                String toPortID = originalToPort.getID();
                Port toPort = graph.getPort(toPortID);
                graph.addEdge(inputNode.getPort(), toPort);
                if (first) {
                    first = false;
                    Point position = originalToPort.getGUI().getPosition();
                    Point inputNodePosition = new Point(0, position.y);
                    inputNode.setPosition(inputNodePosition);
                }
            }
        }
    }

    private String getWorkflowInput(String nodeID) throws MonitorException {
        logger.debug("Node:" + nodeID);
        List<MonitorEvent> events = this.eventData.getEvents();
        for (MonitorEvent event : events) {
            EventType type = event.getType();
            // TODO change this to read from the notification from GPEL.
            if (type != EventType.INVOKING_SERVICE) {
                continue;
            }
            String id = event.getNodeID();
            if (!"".equals(id)) {
                continue;
            }
            // TODO null check
            XmlElement eventElement = event.getEvent();
            XmlElement result = eventElement.element(MonitorUtil.REQUEST);
            XmlElement body = result.element(MonitorUtil.BODY);
            XmlElement soapBody = body.element(XmlConstants.S_BODY);
            WsdlPortTypeOperation wsdlPortTypeOperation;
            try {
                wsdlPortTypeOperation = WSDLUtil.getFirstOperation(this.modifiedWorkflow.getWorkflowWSDL());
            } catch (UtilsException e) {
                throw new MonitorException(e);
            }
            XmlElement part = soapBody.element(wsdlPortTypeOperation.getName());
            XmlElement parameter = part.element(nodeID);
            // TODO support complex type.
            String value = parameter.requiredText();
            return value;
        }
        // TODO
        String message = "Couldn't find a notification of about the input with nodeID, " + nodeID;
        throw new MonitorException(message);
    }

    private String getOutput(String nodeID, String messageName, String parameterName) throws MonitorException {
        List<MonitorEvent> events = this.eventData.getEvents();
        for (MonitorEvent event : events) {
            // We need to find the notification that contains the output of the
            // service invocation.
            EventType type = event.getType();
            if (!(type == EventType.SENDING_RESULT || type == EventType.RECEIVED_RESULT)) {
                continue;
            }
            String id = event.getNodeID();
            if (!nodeID.equals(id)) {
                continue;
            }
            // TODO null check
            XmlElement eventElement = event.getEvent();
            XmlElement result = eventElement.element(MonitorUtil.RESULT);
            XmlElement body = result.element(MonitorUtil.BODY);
            XmlElement soapBody = body.element(XmlConstants.S_BODY);
            XmlElement part = soapBody.element(messageName);
            XmlElement parameter = part.element(parameterName);
            // TODO support complex type.
            String value = parameter.requiredText();
            return value;
        }
        // TODO
        String message = "Couldn't find a notification of the output from the service with nodeID, " + nodeID;
        throw new MonitorException(message);
    }

}
TOP

Related Classes of org.apache.airavata.xbaya.modifier.WorkflowModifier

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.