Package de.danet.an.workflow.clients.wfxml

Source Code of de.danet.an.workflow.clients.wfxml.ActivityResponseGenerator

/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2006 Danet GmbH (www.danet.de), BU BTS.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* $Id: ActivityResponseGenerator.java 2331 2007-03-29 11:46:54Z schnelle $
*
* $Log$
* Revision 1.9  2007/02/16 21:00:21  mlipp
* Fixed some null pointer problems.
*
* Revision 1.8  2007/02/01 13:44:44  schnelle
* Using namespace for factory schemas that do not contain '&'.
*
* Revision 1.7  2007/02/01 12:38:36  schnelle
* Use of encoded key for properties.
*
* Revision 1.6  2007/01/31 22:55:36  mlipp
* Some more refactoring and fixes of problems introduced by refactoring.
*
* Revision 1.5  2007/01/31 12:24:05  drmlipp
* Design revisited.
*
* Revision 1.4  2007/01/30 15:07:37  schnelle
* Filtering of all instances for the current factory in a list instances request.
*
* Revision 1.3  2007/01/30 12:47:45  drmlipp
* Added startdate property to response.
*
* Revision 1.2  2007/01/30 11:56:14  drmlipp
* Merged Wf-XML branch.
*
* Revision 1.1.2.19  2007/01/29 15:04:22  schnelle
* Renaming of Observer to ObserverRegistry and URIDecoder to ResourceReference.
*
* Revision 1.1.2.17  2007/01/29 13:40:31  schnelle
* Storing of the sender base in the servlet context.
*
* Revision 1.1.2.16  2007/01/29 13:10:26  drmlipp
* Using utilities method for timestamp convertion.
*
* Revision 1.1.2.15  2007/01/24 11:46:36  schnelle
* Moved wsdl files and xsd files intot resources subdirectory.
*
* Revision 1.1.2.14  2007/01/24 10:56:50  schnelle
* Prepared return of a result for aobservers.
*
* Revision 1.1.2.13  2007/01/19 12:34:56  schnelle
* Moved generation and decoding of the URI that is used as the receiver key to new class URIDecoder.
*
* Revision 1.1.2.12  2007/01/16 11:05:42  schnelle
* Refactoring: Moved subscription handling methods to own class.
*
* Revision 1.1.2.11  2007/01/09 15:53:37  schnelle
* Added implementation of activity set properties.
*
* Revision 1.1.2.10  2007/01/09 12:05:11  schnelle
* Implemented getProperties.
*
* Revision 1.1.2.9  2006/12/20 14:37:59  schnelle
* Implemented Factory GetDefinition.
*
* Revision 1.1.2.8  2006/12/20 13:32:24  schnelle
* Basic implementato of GetProperties for Instance and Activity.
*
* Revision 1.1.2.7  2006/12/18 14:41:03  schnelle
* Preparatation for individual schema definition for each getproperties request.
*
* Revision 1.1.2.6  2006/12/14 08:50:21  schnelle
* Implemented CompleteActivity.
*
* Revision 1.1.2.5  2006/12/13 11:23:48  schnelle
* Implemented instance ListActivities.
*
* Revision 1.1.2.4  2006/12/12 13:24:38  schnelle
* Introduction of ASAPException to provide a detailed mesage.
*
* Revision 1.1.2.3  2006/12/12 09:34:35  schnelle
* Implemented ChangeState for Instance.
*
* Revision 1.1.2.2  2006/12/11 11:05:34  schnelle
* Added template methods for all requests.
*
* Revision 1.1.2.1  2006/11/28 12:20:09  schnelle
* Creation of a separate class to handle the issues for a specific resource.
*
* Revision 1.1.2.2  2006/11/27 15:41:55  schnelle
* Introducing some constants for request and response identification.
*
* Revision 1.1.2.1  2006/11/24 12:19:13  schnelle
* Separtion of response generation into ResponseGenerator class.
*
*/
package de.danet.an.workflow.clients.wfxml;

import java.rmi.RemoteException;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.NoSuchElementException;

import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;

import de.danet.an.util.XMLUtil;
import de.danet.an.workflow.api.Activity;
import de.danet.an.workflow.api.ActivityUniqueKey;
import de.danet.an.workflow.api.InvalidKeyException;
import de.danet.an.workflow.api.Process;
import de.danet.an.workflow.api.ProcessDirectory;
import de.danet.an.workflow.api.WorkflowService;
import de.danet.an.workflow.apix.ExtActivity;
import de.danet.an.workflow.omgcore.CannotCompleteException;
import de.danet.an.workflow.omgcore.NotRunningException;

/**
* This class provides the methods of an {@link AbstractResponseGenerator}
* that are relevant for the activity.
*
* <p>
* The <em>Activity</em> resource is an extension of ASAP for Wf-XML. The
* process instance will at any point in time be waiting for what it considers
* to be an external action to be completed. The activity represents this
* wait-point within the process. The process may be waiting for a human to
* interact with it, or it may be waiting for the result of an automated step in
* the process. The activity presents information about what the process is
* waiting for, such as the assignee, and possibly detail about how long it has
* been waiting, and how long it is willing to wait. One way of invoking an
* external action is through the use of ASAP or Wf-XML. In this case, the
* activity is acting as an observer of that remote process. The activity can
* provide the URL of the remote process instance that it is waiting on.
* </p>
*
* @author Dirk Schnelle
*
*/
class ActivityResponseGenerator extends AbstractResponseGenerator {
    /** Logger instance. */
    private static final org.apache.commons.logging.Log logger
        = org.apache.commons.logging.LogFactory.getLog
                (ActivityResponseGenerator.class);   

    /**
     * Constructs a new object.
     *
     * @param observerRegistry the observer registry
     * @param wfs Reference to the workflow engine.
     * @param decoder the URI decoder.
     */
    public ActivityResponseGenerator(ObserverRegistry observerRegistry,
            WorkflowService wfs, ResourceReference decoder){
        super(observerRegistry, wfs, decoder);
    }
   
    /* (non-Javadoc)
     * @see de.danet.an.workflow.clients.wfxml.AbstractResponseGenerator#evaluate(javax.xml.soap.SOAPMessage, javax.xml.soap.SOAPMessage)
     */
    public void evaluate(SOAPMessage reqMsg, SOAPMessage respMsg)
        throws SOAPException, RemoteException {
        SOAPBodyElement actionElement = getActionElement(reqMsg);
       
        String actName = actionElement.getElementName().getLocalName();

        if (actName.equals (Consts.GET_PROPERTIES_REQUEST)) {
            getActivityProperties(reqMsg, respMsg);
        } else if (actName.equals (Consts.SET_PROPERTIES_REQUEST)) {
            setActivityProperties(actionElement, reqMsg, respMsg);
        } else if (actName.equals (Consts.COMPLETE_ACTIVITY_REQUEST)) {
            completeActivity(reqMsg, respMsg);
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("unknown action '" + actName + "'");
            }

            FaultUtils.setFault(respMsg,
                    ASAPException.ASAP_INVALID_OPERATION_SPECIFICATION,
                    getResourceName() + ": Unknown action \"" + actName
                    + "\".");
        }
    }

    /* (non-Javadoc)
     * @see de.danet.an.workflow.clients.wfxml.AbstractResponseGenerator#getSender()
     */
    protected String getResourceName() {
        return RESOURCE_ACTIVITY;
    }

    /**
     * Creates a response that contains properties of the activity.
     *
     * <p>
     * This method produces XML that fails validation, since the WFXML
     * schema definition defines a group to return theses properties, but
     * which is never referenced, so that it must not be a part of
     * a <code>GetpropertiesRs</code> message.
     * </p>

     * @param reqMsg the request message.
     * @param respMsg the response message
     * @throws SOAPException
     *         error evaluating the request or constructing the response.
     * @throws RemoteException
     *         error accessing the workflow engine.
     */
    private void getActivityProperties(SOAPMessage reqMsg, SOAPMessage respMsg)
        throws SOAPException, RemoteException {
        if (logger.isDebugEnabled()) {
            logger.debug("get activity properties...");
        }
       
        String receiverKey = getHeaderValue(reqMsg, Consts.RECEIVER_KEY);

        Activity activity = null;
        try {
            activity = getActivity(receiverKey);
        } catch (InvalidKeyException e) {
            FaultUtils.setFault(respMsg,
                    ASAPException.ASAP_INVALID_INSTANCE_KEY, e.getMessage());
           
            return;
        } catch (NoSuchElementException e) {
            FaultUtils.setFault(respMsg,
                    ASAPException.ASAP_INVALID_INSTANCE_KEY, e.getMessage());
           
            return;
        }
       
        SOAPBodyElement propsNode
            = createWfxmlResponseNode(respMsg, Consts.GET_PROPERTIES_RESPONSE);
       
        appendActivityProperties(respMsg, receiverKey, propsNode, activity);
    }
   
    /**
     * Sets properties for the activity.
     *
     * @param action the action element.
     * @param reqMsg the request message.
     * @param respMsg the response message
     * @throws SOAPException
     *         error evaluating the request or constructing the response.
     * @throws RemoteException
     *         error accessing the workflow engine.
     */
    private void setActivityProperties(SOAPElement action, SOAPMessage reqMsg,
            SOAPMessage respMsg)
        throws SOAPException, RemoteException {
        if (logger.isDebugEnabled()) {
            logger.debug("set activity properties...");
        }
       
        String receiverKey = getHeaderValue(reqMsg, Consts.RECEIVER_KEY);

        Activity activity = null;
        try {
            activity = getActivity(receiverKey);
        } catch (InvalidKeyException e) {
            FaultUtils.setFault(respMsg,
                    ASAPException.ASAP_INVALID_INSTANCE_KEY, e.getMessage());
           
            return;
        } catch (NoSuchElementException e) {
            FaultUtils.setFault(respMsg,
                    ASAPException.ASAP_INVALID_INSTANCE_KEY, e.getMessage());
           
            return;
        }

        String name = getChildsTextContent(action, "Name");
        if (name != null) {
            activity.setName(name);
        }
        String description = getChildsTextContent(action, "Description");
        if (description != null) {
            activity.setDescription(description);
        }
       
        SOAPBodyElement propsNode
            = createWfxmlResponseNode(respMsg, Consts.SET_PROPERTIES_RESPONSE);

        appendActivityProperties(respMsg, receiverKey, propsNode, activity);
    }

    /**
     * Reads the properties from the activity and appends them to the parent.
     * @param respMsg the response message.
     * @param receiverKey this activity instance
     * @param parent the parent node of the response message.
     * @param activity the activity
     * @throws SOAPException
     *         error appending to the parent node
     * @throws RemoteException
     *         error accessing the activity
     */
    private void appendActivityProperties(SOAPMessage respMsg,
            String receiverKey, SOAPElement parent, Activity activity)
        throws SOAPException, RemoteException {

        SOAPElement keyNode
            = parent.addChildElement("Key", Consts.WFXML_PREFIX);
        keyNode.addTextNode (getResourceReference().getResourceKey());
        String activityState = activity.state();
        SOAPElement state
            = parent.addChildElement("State", Consts.WFXML_PREFIX);
        state.addTextNode(StateMapper.omg2asapState(activityState));
        SOAPElement nameNode
            = parent.addChildElement("Name", Consts.WFXML_PREFIX);
        nameNode.addTextNode(activity.name());
        SOAPElement descNode
            = parent.addChildElement("Description", Consts.WFXML_PREFIX);
        if (activity.description() != null) {
            descNode.addTextNode(activity.description());
        }
        Collection states = activity.validStates();
        Iterator stateIterator = states.iterator();
        while (stateIterator.hasNext()) {
            String validState = (String) stateIterator.next();
            SOAPElement stateElement
                = parent.addChildElement("ValidState", Consts.WFXML_PREFIX);
            stateElement.addTextNode(StateMapper.omg2asapState(validState));
        }
       
        SOAPElement instanceKey
            = parent.addChildElement("InstanceKey", Consts.WFXML_PREFIX);
        ResourceReference procResRef = new ResourceReference
            (getResourceReference().getBaseUrl(),
                    (Process)activity.container());
        instanceKey.addTextNode (procResRef.getResourceKey());
        SOAPElement remoteInstance
            = parent.addChildElement("RemoteInstance", Consts.WFXML_PREFIX);
        // TODO: Clarify the meaning of RemoteInstance.
        try {
            Date  startTime = ((ExtActivity)activity).startTime();
            SOAPElement started
                = parent.addChildElement("StartedDate", Consts.WFXML_PREFIX);
            started.addTextNode (XMLUtil.toXsdGMTDateTime(startTime));
        } catch (NotRunningException e) {
            // should not happen, only started activities are delivered
            // to clients anyway.
        }
        SOAPElement due
            = parent.addChildElement("DueDate", Consts.WFXML_PREFIX);
        Date dueDate = new Date(Long.MAX_VALUE);
        // TODO: This has to be adapted to the real deadline.
        // Currently the deadline may consist of multiple conditions which
        // may be independent of a date.
        due.addTextNode(XMLUtil.toXsdGMTDateTime(dueDate));
        SOAPElement lastmodified
            = parent.addChildElement("LastModified", Consts.WFXML_PREFIX);
        Activity.Info info = activity.activityInfo();
        Date lastModifiedDate = info.lastStateTime();
        lastmodified.addTextNode(XMLUtil.toXsdGMTDateTime(lastModifiedDate));
    }
   
    /**
     * Completes the specified activity.
     * @param reqMsg the request message.
     * @param respMsg the response message
     * @throws SOAPException
     *         error evaluating the request or constructing the response.
     * @throws RemoteException
     *         error accessing the workflow engine.
     */
    private void completeActivity(SOAPMessage reqMsg, SOAPMessage respMsg)
        throws SOAPException, RemoteException {
        String receiverKey = getHeaderValue(reqMsg, Consts.RECEIVER_KEY);
       
        Activity activity = null;
        try {
            activity = getActivity(receiverKey);
        } catch (InvalidKeyException e) {
            FaultUtils.setFault(respMsg,
                    ASAPException.ASAP_INVALID_INSTANCE_KEY, e.getMessage());
           
            return;
        } catch (NoSuchElementException e) {
            FaultUtils.setFault(respMsg,
                    ASAPException.ASAP_INVALID_INSTANCE_KEY, e.getMessage());
           
            return;
        }
       
        try {
            activity.complete();
        } catch (CannotCompleteException e) {
            FaultUtils.setFault(respMsg,
                    ASAPException.ASAP_INVALID_STATE_TRANSITION,
                    e.getMessage());
           
            return;
        }

        createAsapResponseNode(respMsg, Consts.COMPLETE_ACTIVITY_RESPONSE);
       
        if (logger.isDebugEnabled()) {
            logger.debug("completed activity " + activity.toString());
        }
    }

    /**
     * Gets the activity that that can handle the package id and the
     * process id that are encoded in the given uri.
     * @param uri the uri with package and process id.
     * @return process manager.
     * @throws RemoteException
     *         error accessing the workflow engine
     * @throws InvalidKeyException
     *         process manager or process does not exist
     */
    private Activity getActivity(String uri)
        throws RemoteException, InvalidKeyException {
        String packageId = getResourceReference().getPackageId();
        String processId = getResourceReference().getProcessId();
        String processKey = getResourceReference().getProcessKey();
        String activityKey = getResourceReference().getActivityKey();
           
        if (logger.isDebugEnabled()) {
            logger.debug("finding activity definition'" + packageId + "/"
                    + processId + "/" + processKey + "/" + activityKey
                    + "'...");
        }
       
        ActivityUniqueKey uniqueKey = new ActivityUniqueKey(packageId + "/"
                + processId, processKey, activityKey);
       
        ProcessDirectory pd = getWorkflowService().processDirectory();
       
        return pd.lookupActivity(uniqueKey);
    }
}
TOP

Related Classes of de.danet.an.workflow.clients.wfxml.ActivityResponseGenerator

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.