Package de.danet.an.workflow.clients.mgmtportlets.process

Source Code of de.danet.an.workflow.clients.mgmtportlets.process.ActivityWrapper

/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2005 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: ActivityWrapper.java 2326 2007-03-27 21:59:44Z mlipp $
*
* $Log$
* Revision 1.26  2007/02/09 10:03:50  mlipp
* Improved exception handling.
*
* Revision 1.25  2007/02/02 08:48:35  drmlipp
* Fixed sorting, added column in assignments view.
*
* Revision 1.24  2006/12/04 14:18:42  drmlipp
* Added navigation between invoking and subprocess and fixed multiple deletes.
*
* Revision 1.23  2006/11/22 12:49:47  drmlipp
* Improved error handling.
*
* Revision 1.22  2006/11/21 18:38:29  drmlipp
* Improving exception handling.
*
* Revision 1.21  2006/11/17 10:52:23  drmlipp
* Added display of keys.
*
* Revision 1.20  2006/10/26 13:24:53  drmlipp
* Extended exception handling.
*
* Revision 1.19  2006/09/29 12:32:11  drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.18  2006/09/15 11:43:04  drmlipp
* Minor improvements
*
* Revision 1.17  2006/09/14 08:05:14  drmlipp
* Use Activity.Info for storing attributes.
*
* Revision 1.15  2006/09/13 13:55:16  drmlipp
* Proceeding with assignments display.
*
* Revision 1.14  2006/09/06 09:31:06  drmlipp
* Cleaned up event display.
*
* Revision 1.13  2005/11/07 14:36:11  drmlipp
* Adapted to revised request attribute handling.
*
* Revision 1.12  2005/11/03 20:50:17  mlipp
* Simplified a bit.
*
* Revision 1.11  2005/10/31 16:38:02  drmlipp
* Implementation of debug features continued.
*
* Revision 1.10  2005/10/28 11:00:29  drmlipp
* Continued exception display implementation.
*
* Revision 1.9  2005/10/27 15:10:11  drmlipp
* Started exception display.
*
* Revision 1.8  2005/10/25 11:36:31  drmlipp
* Using extended column tag.
*
* Revision 1.7  2005/10/24 15:30:49  drmlipp
* Implemented context data change display.
*
* Revision 1.6  2005/10/21 15:05:51  drmlipp
* Continued audit event display and cleaned up some things.
*
* Revision 1.5  2005/10/17 15:26:17  drmlipp
* Added activity state actions.
*
* Revision 1.4  2005/10/14 12:45:35  drmlipp
* Added information.
*
* Revision 1.3  2005/10/02 21:04:03  mlipp
* Added activity list sorting.
*
* Revision 1.2  2005/10/01 20:53:55  mlipp
* Improved status display.
*
* Revision 1.1  2005/09/30 21:48:58  mlipp
* Basic process detail display working.
*
*/
package de.danet.an.workflow.clients.mgmtportlets.process;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.model.ArrayDataModel;
import javax.faces.model.DataModel;

import de.danet.an.util.jsf.JSFUtil;
import de.danet.an.workflow.api.Activity;
import de.danet.an.workflow.api.InvalidKeyException;
import de.danet.an.workflow.api.MethodInvocationBatch;
import de.danet.an.workflow.api.ProcessDefinition;
import de.danet.an.workflow.api.WorkflowService;
import de.danet.an.workflow.clients.mgmtportlets.WorkflowServiceConnection;
import de.danet.an.workflow.omgcore.InvalidControlOperationException;
import de.danet.an.workflow.omgcore.InvalidStateException;
import de.danet.an.workflow.omgcore.TransitionNotAllowedException;
import de.danet.an.workflow.omgcore.WfAssignment;

/**
* A wrapper class that makes activities look like JavaBeans.
* @author mnl
*/
public class ActivityWrapper implements Serializable {

    private static final org.apache.commons.logging.Log logger
        = org.apache.commons.logging.LogFactory.getLog (ActivityWrapper.class);

    private static String L10N_MSGS
        = "de.danet.an.workflow.clients.mgmtportlets.process.L10n";

    private Activity.Info info;
    private String uniqueDispKey;
    private String state;
    private List assignees;
    private String executor;
    private boolean executorIsSubprocess = false;
    private String invokedManagerName;
    private String invokedKey;
    private Collection validStates;
    private Map validStatesMap;
    private Activity.DeadlineInfo[] deadlineInfos;
    private Map deadlineInfosByException;
    private boolean debugEnabled;
    private Date lastStateTime;
    private String[] handledExceptions;
    private transient DataModel handledExceptionsModel = null;
   
    /**
     * Create a new instance for the given activity.
     * @param wfs the workflow service
     * @param act the activity
     */
    public ActivityWrapper (WorkflowService wfs, Activity act)
        throws RemoteException {
        MethodInvocationBatch mib = new MethodInvocationBatch ();
        mib.addInvocation(act, "activityInfo", null, null);
        mib.addInvocation(act, "state", null, null);
        mib.addInvocation(act, "assignments", null, null);
        mib.addInvocation(act, "executor", null, null);
        mib.addInvocation(act, "validStates", null, null);
        mib.addInvocation(act, "handledExceptions", null, null);
        mib.addInvocation(act, "deadlines", null, null);
        mib.addInvocation(act, "debugEnabled", null, null);
        mib.addInvocation(act, "lastStateTime", null, null);
        MethodInvocationBatch.Result mir = null;
        try {
            mir = (MethodInvocationBatch.Result)wfs.executeBatch(mib);
        } catch (InvocationTargetException e) {
            throw (IllegalStateException)
                (new IllegalStateException (e.getMessage())).initCause(e);
        }
        if (mir.hasExceptions ()) {
            Exception e = mir.firstException ();
            if (e instanceof RemoteException) {
                throw (RemoteException)e;
            }
            throw (IllegalStateException)
                (new IllegalStateException(e.getMessage())).initCause(e);
        }
        info = (Activity.Info)mir.result(0);
        uniqueDispKey = info.uniqueKey().managerName() + "/" + info.name();
        state = mir.resultAsString(1);
        Collection assignments = (Collection)mir.result(2);
        assignees = new ArrayList ();
        for (Iterator i = assignments.iterator(); i.hasNext ();) {
            WfAssignment a = (WfAssignment)i.next();
            assignees.add (new ResourceWrapper(a.assignee()));
        }
        Activity.Implementation executing
            = (Activity.Implementation)mir.result(3);
        if (executing == null) {
            executor = null;
        }
        if (executing instanceof Activity.ToolImplementation) {
            executor = ((Activity.ToolImplementation)executing).id();
        } else if (executing instanceof Activity.SubFlowImplementation) {
            try {
                ProcessDefinition procDef
                    = wfs.processDefinitionDirectory().lookupProcessDefinition
                    (((Activity.SubFlowImplementation)executing).packageId(),
                     ((Activity.SubFlowImplementation)executing).processId());
                invokedManagerName = procDef.mgrName();
                invokedKey
                    = ((Activity.SubFlowImplementation)executing).processKey();
                executor = wfs.processDirectory()
                    .lookupProcess(invokedManagerName, invokedKey).name();
                executorIsSubprocess = true;
                if (executor == null) {
                    executor = invokedManagerName;
                }
            } catch (InvalidKeyException e) {
                // Probably no longer exists
                executor
                    = ((Activity.SubFlowImplementation)executing).packageId()
                    + "/"
                    + ((Activity.SubFlowImplementation)executing).processId();
            }
        }
        validStates = (Collection)mir.result(4);
        validStatesMap = new HashMap ();
        for (Iterator i = validStates.iterator(); i.hasNext();) {
            String state = (String)i.next();
            validStatesMap.put(state, Boolean.TRUE);
        }
        handledExceptions = (String[])mir.result(5);
        deadlineInfos = (Activity.DeadlineInfo[])mir.result(6);
        deadlineInfosByException = new HashMap ();
        for (int i = 0; i < deadlineInfos.length; i++) {
            deadlineInfosByException.put
                (deadlineInfos[i].getExceptionName(), deadlineInfos[i]);
        }
        debugEnabled = ((Boolean)mir.result(7)).booleanValue();
        lastStateTime = mir.resultAsDate(8);
    }

    private Activity activity() throws RemoteException, InvalidKeyException {
        FacesContext fc = FacesContext.getCurrentInstance();
        Activity act = (Activity)fc.getExternalContext()
            .getRequestMap().get(uniqueDispKey);
        if (act == null) {
            WorkflowService wfs = WorkflowServiceConnection
                .instance("workflowServiceConnection").getWorkflowService();
            act = wfs.processDirectory().lookupActivity(info.uniqueKey());
            fc.getExternalContext().getRequestMap().put(uniqueDispKey, act);       
        }
        return act;
    }

    /**
     * Show the associated process.
     */
    public String showProcess () {
        FacesContext fc = FacesContext.getCurrentInstance();
        fc.getExternalContext().getSessionMap().put
            ("processSelection",
             new ProcessSelection
                 (info.uniqueKey().managerName(),
                  info.uniqueKey().processKey()));
        return "showProcessDetail";
    }
   
    /**
     * Show the associated process.
     */
    public String showInvokedProcess () {
        FacesContext fc = FacesContext.getCurrentInstance();
        fc.getExternalContext().getSessionMap().put
            ("processSelection",
             new ProcessSelection (invokedManagerName, invokedKey));
        return "showProcessDetail";
    }
   
    /**
     * @return Returns the activityKey.
     */
    public String getProcessKey() {
        return info.uniqueKey().processKey();
    }

    /**
     * @return Returns the activityKey.
     */
    public String getActivityKey() {
        return info.uniqueKey().activityKey();
    }

    /**
     * @return Returns the uniqueKey.
     */
    public String getUniqueKey() {
        return uniqueDispKey;
    }

    /**
     * @return Returns the process name.
     */
    public String getProcessName() {
        return info.processName();
    }

    /**
     * @return Returns the process name and key.
     */
    public String getProcessNameAndKey() {
        return info.processName() + "/" + info.uniqueKey().processKey();
    }

    /**
     * @return Returns the activityName.
     */
    public String getActivityName() {
        return info.name();
    }

    /**
     * @return Returns the priority.
     */
    public int getPriority() {
        return info.priority();
    }

    /**
     * @return Returns the lastStateTime.
     */
    public Date getLastStateTime() {
        return lastStateTime;
    }

    /**
     * @return Returns the state name.
     */
    public String getState() {
        return state;
    }

    /**
     * Check if activity is running.
     * @return result
     */
    public boolean isRunning() {
        return state.startsWith("open.running");
    }
   
    /**
     * Checks if activity is being debugged.
     * @return result
     */
    public boolean isInDebugMode () {
        return debugEnabled;
    }
   
    /**
     * @return Returns the state name.
     */
    public String getStateName() {
        return StateNameMapper.mapState(state);
    }

    /**
     * @return URL of state icon or null
     */
    public String getStateIconUrl () {
        return StateNameMapper.stateIconUrl (state);
    }
   
    /**
     * @return Returns the executor.
     */
    public String getExecutor() {
        return executor;
    }

    /**
     * @return if executor is subprocess
     */
    public boolean isExecutorSubprocess() {
        return executorIsSubprocess;
    }
   
    /**
     * @return the current assignee
     */
    public List getAssignees () {
        return assignees;
    }
   
    /**
     * Check if the given state is valid (i.e. may be used in setState).
     * @param state the checkState
     */
    public Map getValidStatesMap () {
        return validStatesMap;
    }

    /**
     * Suspend the activity
     */
    public String suspend () throws RemoteException {
        try {
            activity().suspend();
        } catch (InvalidKeyException e) {
            logger.debug ("Referenced activity does not exist (ignored):"
                          + e.getMessage());
        } catch (InvalidControlOperationException e) {
            JSFUtil.addMessage (FacesMessage.SEVERITY_ERROR, L10N_MSGS,
                    "cannotChangeState", null, e);
        }
        return null;
    }
   
    /**
     * Resume the activity
     */
    public String resume () throws RemoteException {
        try {
            activity().resume();
        } catch (InvalidKeyException e) {
            logger.debug ("Referenced activity does not exist (ignored):"
                          + e.getMessage());
        } catch (InvalidControlOperationException e) {
            JSFUtil.addMessage (FacesMessage.SEVERITY_ERROR, L10N_MSGS,
                    "cannotChangeState", null, e);
        }
        return null;
    }

    /**
     * Resume the activity
     */
    public String clearExceptionAndResume () throws RemoteException {
        try {
            activity().changeState("open.not_running.suspended.clearing_exception");
            activity().resume();
        } catch (InvalidKeyException e) {
            logger.debug ("Referenced activity does not exist (ignored):"
                          + e.getMessage());
        } catch (InvalidStateException e) {
            logger.debug ("Invalid state:" + e.getMessage());
        } catch (TransitionNotAllowedException e) {
            JSFUtil.addMessage (FacesMessage.SEVERITY_ERROR, L10N_MSGS,
                    "cannotChangeState", null, e);
        } catch (InvalidControlOperationException e) {
            JSFUtil.addMessage (FacesMessage.SEVERITY_ERROR, L10N_MSGS,
                    "cannotChangeState", null, e);
        }
        return null;
    }

    /**
     * Terminate the activity
     */
    public String terminate () throws RemoteException {
        try {
            activity().terminate();
        } catch (InvalidKeyException e) {
            logger.debug ("Referenced activity does not exist (ignored):"
                          + e.getMessage());
        } catch (InvalidControlOperationException e) {
            JSFUtil.addMessage (FacesMessage.SEVERITY_ERROR, L10N_MSGS,
                    "cannotChangeState", null, e);
        }
        return null;
    }

    /**
     * Abort the activity
     */
    public String abort () throws RemoteException {
        try {
            activity().abort();
        } catch (InvalidKeyException e) {
            logger.debug ("Referenced activity does not exist (ignored):"
                          + e.getMessage());
        } catch (InvalidControlOperationException e) {
            JSFUtil.addMessage (FacesMessage.SEVERITY_ERROR, L10N_MSGS,
                    "cannotChangeState", null, e);
        }
        return null;
    }

    /**
     * Continue the activity
     */
    public String continueExecution () throws RemoteException {
        try {
            activity().changeState("open.running");
        } catch (InvalidKeyException e) {
            logger.debug ("Referenced activity does not exist (ignored):"
                          + e.getMessage());
        } catch (InvalidStateException e) {
            // cannot happen, state name hard-coded
        } catch (TransitionNotAllowedException e) {
            JSFUtil.addMessage (FacesMessage.SEVERITY_ERROR, L10N_MSGS,
                    "cannotChangeState", null, e);
        }
        return null;
    }

    /**
     * Continue the activity
     */
    public String skip () throws RemoteException {
        try {
            activity().changeState("open.running.debug.skipping");
        } catch (InvalidKeyException e) {
            logger.debug ("Referenced activity does not exist (ignored):"
                          + e.getMessage());
        } catch (InvalidStateException e) {
            // cannot happen, state name hard-coded
        } catch (TransitionNotAllowedException e) {
            JSFUtil.addMessage (FacesMessage.SEVERITY_ERROR, L10N_MSGS,
                    "cannotChangeState", null, e);
        }
        return null;
    }
   
    /**
     * Send an exception.
     */
    public String sendException () throws RemoteException {
        Activity.DeadlineInfo dl = null;
        DataModel he = getHandledExceptions();
        if (he == null) {
            return null;
        }
        String exception = ((String[])he.getWrappedData())[he.getRowIndex()];
        for (int i = 0; i < deadlineInfos.length; i++) {
            if (deadlineInfos[i].getExceptionName().equals(exception)) {
                dl = deadlineInfos[i];
                break;
            }
        }
        Activity activity = null;
        try {
            activity = activity();
        } catch (InvalidKeyException e) {
            // TODO:
        }
        MethodInvocationBatch mib = new MethodInvocationBatch(true);
        if (dl == null
                || (dl.getExecutionMode() == Activity.DeadlineInfo.SYNCHR)) {
            // not an asynchronous deadline, abandon if not aborted
            if (!state.startsWith("open.running.debug.abandoning")) {
                mib.addInvocation(activity, "abandon",
                        new String[] { "java.lang.String" },
                        new Object[] { exception });
            }
            mib.addInvocation(activity, "changeState",
                    new String[] { "java.lang.String" },
                    new Object[] { "open.running.debug.awaiting_exception" });
            mib.addInvocation(activity, "abandon",
                    new String[] { "java.lang.String" },
                    new Object[] { exception });
        } else {
            // asynchronous deadline, simply have it sent
            mib.addInvocation(activity, "changeState",
                    new String[] { "java.lang.String" },
                    new Object[] { "open.running.debug.forwarding_exception" });
            mib.addInvocation(activity, "abandon",
                    new String[] { "java.lang.String" },
                    new Object[] { exception });
        }
        try {
            MethodInvocationBatch.Result mir = (MethodInvocationBatch.Result)
                WorkflowServiceConnection.instance("workflowServiceConnection")
                .getWorkflowService().executeBatch(mib);
            if (mir.hasExceptions()) {
                JSFUtil.addMessage(FacesMessage.SEVERITY_ERROR, L10N_MSGS,
                        "cannotSendException", null, mir.firstException());
            }
        } catch (InvocationTargetException e) {
            logger.error
                ("Unexpected exception: " + e.getCause().getMessage(), e);
            JSFUtil.addMessage(FacesMessage.SEVERITY_ERROR, L10N_MSGS,
                    "resourceCurrentlyUnavailable", null);
        }
        return null;
    }
   
    /**
     * The show events action for the activity events
     *
     * @return outcome
     */
    public String showEvents () {
        FacesContext fc = FacesContext.getCurrentInstance();
        ((ProcessSelection)fc.getExternalContext().getSessionMap()
                .get("processSelection")).setEventSelection(getActivityKey());
        return "showAuditEvents";       
    }
   
    /**
     * Return the map for storing the expanded state.
     * @return result
     */
    private Map expandedActivities() {
        FacesContext fc = FacesContext.getCurrentInstance();
        Map xm = (Map)fc.getExternalContext()
            .getSessionMap().get("expandedActs");
        if (xm == null) {
            xm = new HashMap ();
            fc.getExternalContext().getSessionMap().put ("expandedActs", xm);
        }
        return xm;
    }

    /**
     * Check if the display can be expanded.
     * @return result
     */
    public boolean isDisplayExpandable () {
        return getHandledExceptions() != null
            && getHandledExceptions().getRowCount() > 0;
    }
   
    /**
     * Check if activity is to be displayed as expanded.
     * @return result
     */
    public boolean isDisplayExpanded () {
        return expandedActivities().containsKey(getUniqueKey());
    }
   
    /**
     * Toggle the display expanded state.
     */
    public String toggleDisplayExpanded () {
        if (isDisplayExpanded()) {
            expandedActivities().remove(getUniqueKey());
        } else {
            expandedActivities().put(getUniqueKey(), Boolean.TRUE);
        }
        return null;
    }
   
    /**
     * Return the list of handled exceptions.
     * @return the result
     */
    public DataModel getHandledExceptions() {
        if (handledExceptionsModel == null) {
            handledExceptionsModel = new ArrayDataModel(handledExceptions);
        }
        return handledExceptionsModel;
    }
   
    /**
     * Return the deadline infos.
     * @return the result
     */
    public Map getDeadlineInfos() {
        return deadlineInfosByException;
    }

}
TOP

Related Classes of de.danet.an.workflow.clients.mgmtportlets.process.ActivityWrapper

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.