Package org.jboss.soa.esb.services.jbpm.cmd

Source Code of org.jboss.soa.esb.services.jbpm.cmd.CallbackCommand

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.soa.esb.services.jbpm.cmd;

import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.dom4j.tree.DefaultElement;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.addressing.EPR;
import org.jboss.soa.esb.addressing.PortReference;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.services.jbpm.Constants;
import org.jboss.soa.esb.services.jbpm.JBpmObjectMapper;
import org.jboss.soa.esb.services.jbpm.Mapping;
import org.jboss.soa.esb.services.jbpm.actionhandlers.EsbActionHandler;
import org.jbpm.JbpmContext;
import org.jbpm.command.Command;
import org.jbpm.context.exe.ContextInstance;
import org.jbpm.graph.def.Action;
import org.jbpm.graph.def.Node;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
import org.jbpm.instantiation.Delegation;

/**
* @author kstam
*
*/
public class CallbackCommand implements Command {

    private static final HashMap<Mapping, Object> EMPTY_VARIABLES_MAP = new HashMap<Mapping, Object>();
   
    private static Logger logger = Logger.getLogger(CallbackCommand.class);
    /**
     *
     */
    private static final long serialVersionUID = 1L;
   
    /**
     * The named transition or null if the default is to be used.
     */
    private String transitionName ;
    /**
     * The variable map.
     */
    private Map<Mapping, Object> variables ;
   
    /**
     * The ESB Message object.
     */
    private Message message;
   
    private EPR callbackEpr;
   
    public CallbackCommand() {
        super();
    }
   
    public EPR getCallbackEpr() {
        return callbackEpr;
    }
    public void setCallbackEpr(EPR callbackEpr) {
        this.callbackEpr = callbackEpr;
    }
   
    public void setTransitionName(final String transitionName) {
        this.transitionName = transitionName ;
    }
   
    public void setVariables(final Map<Mapping, Object> variables) {
        this.variables = variables ;
    }
   
    public void setMessage(final Message message)
    {
        this.message = message;
    }
   
   
    public Object execute(JbpmContext jbpmContext)
    {
        final boolean isDebugEnabled = logger.isDebugEnabled() ;
        try {
            PortReference portRef = callbackEpr.getAddr();
            long nodeId  = Long.parseLong(portRef.getExtensionValue(Constants.NODE_ID));
            long tokenId = Long.parseLong(portRef.getExtensionValue(Constants.TOKEN_ID));
            long processInstanceId = Long.parseLong(portRef.getExtensionValue(Constants.PROCESS_INSTANCE_ID));
           
            String counterName = Constants.PROCESS_NODE_VERSION_COUNTER + nodeId + '_' + tokenId;
           
            long processNodeVersion = Long.parseLong(portRef.getExtensionValue(counterName));
           
            if (isDebugEnabled) logger.debug("Expected nodeId=" + nodeId +  ", tokenId=" + tokenId + ", processNodeVersion=" + processNodeVersion);
            //get update on current state of things.
            final Token token = jbpmContext.getToken(tokenId) ;
            if (token == null) {
                throw new CallbackException("Token id " + tokenId + " from process instance " + processInstanceId + " is no longer active") ;
            }
           
            final ProcessInstance instance = token.getProcessInstance() ;
            if (instance == null) {
                throw new CallbackException("Process instance " + processInstanceId + " is no longer active") ;
            }
           
            if (instance.getId() != processInstanceId) {
                throw new CallbackException("Token id " + tokenId + " from process instance " + processInstanceId + " now attached to process instance " + instance.getId()) ;
            }
           
            if (nodeId != token.getNode().getId()) {
                throw new CallbackException("Token id " + tokenId + " from process instance " + processInstanceId + " is no longer on expected node, expected " + nodeId + " but discovered " + token.getNode().getId()) ;
            }
            if (token.hasEnded()) {
                throw new CallbackException("Token id " + tokenId + " from process instance " + processInstanceId + " has already terminated") ;
            }
           
            if (token.isLocked()) {
                throw new CallbackException("Token id " + tokenId + " from process instance " + processInstanceId + " is already locked, another thread is active") ;
            }
           
            final ContextInstance contextInstance = instance.getContextInstance() ;
            final long currentProcessNodeVersion = Long.parseLong(String.valueOf(contextInstance.getVariableLocally(counterName, token)));
            if (isDebugEnabled) logger.debug("ProcessNodeVersion=" + currentProcessNodeVersion);
            if (processNodeVersion!=currentProcessNodeVersion) {
                throw new CallbackException("The current processNodeVersion (id=" + currentProcessNodeVersion + ") is not the expected version (version=" + processNodeVersion + ").");
            }
           
            final String globalProcessScopeVal = portRef.getExtensionValue(Constants.PROCESS_SCOPE_ATTR) ;
            // Default to global scope as that matches the previous functionality
            // N.B. This is different from retrieving variables!!
            final boolean globalProcessScope = (globalProcessScopeVal == null ? true : Boolean.parseBoolean(globalProcessScopeVal));
           
            Map<Mapping, Object> variablesMap = getVariablesMapFromMessage(token.getNode(), message);
            // Try to be backward compatible in case the variable mappings were stored in the epr and set on this CallbackCommand instance.
            if (variables != null)
            {
                variablesMap.putAll(variables);
            }
           
            AsyncProcessSignal.createSignalJob(jbpmContext, token, transitionName, jbpmContext.getActorId(), globalProcessScope, variablesMap) ;
        } catch (CallbackException jbpmCe) {
            //TODO: Why is this only a warning?
            logger.warn(jbpmCe.getMessage());
        }
        return null;
    }
   
    /**
     * This method uses the information located in the jBPM nodes action definition to find out
     * which variables have been defined there.
     * <p/>
     * The variables that are specified in the element 'esbToBpmVars' will be extracted from the
     * ESB Message object and put into the retured map.
     *
     * For example:
     * <pre>{@code
     * <node name="node1">
     *    <action name="first action" class="org.jboss.soa.esb.services.jbpm.actionhandlers.EsbActionHandler">
     *       <esbCategoryName>MockCategory</esbCategoryName>
     *       <esbServiceName>MockService</esbServiceName>
     *       <esbToBpmVars>
     *          <mapping esb="BODY_CONTENT" bpm="theBody" process-scope="false"/>
     *       </esbToBpmVars>
     *    </action>
     * </node>
     * }</pre>
     *
     * @param node          The jBPM node.
     * @param esbMessage    The ESB Message object
     * @return Map          A Map with the 'esbToBpmVars' mapping as the key and the object/value of
     *                      that mapping which was extracted from the ESB Message object.
     * @throws CallbackException
     */
    HashMap<Mapping, Object> getVariablesMapFromMessage(final Node node, final Message esbMessage) throws CallbackException
    {
        final Action jbpmAction = node.getAction();
        if (jbpmAction != null && esbMessage != null)
        {
            final Delegation actionDelegation = jbpmAction.getActionDelegation();
            if (actionDelegation != null)
            {
                final Object delegate = actionDelegation.getInstance();
                if (delegate instanceof EsbActionHandler)
                {
                    final EsbActionHandler handler = (EsbActionHandler)delegate;
                    final DefaultElement esbToBpmVars = handler.esbToBpmVars;
                    if (esbToBpmVars != null)
                    {
                        try
                        {
                            return  new JBpmObjectMapper().mapFromEsbMessageToJBpmMapping(esbMessage, esbToBpmVars.asXML());
                        }
                        catch (final ConfigurationException e)
                        {
                            throw new CallbackException(e.getMessage(), e);
                        }
                    }
                }
            }
        }
        return EMPTY_VARIABLES_MAP;
    }
   
}
TOP

Related Classes of org.jboss.soa.esb.services.jbpm.cmd.CallbackCommand

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.