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

Source Code of org.jboss.soa.esb.services.jbpm.cmd.CommandExecutor$AsyncStartProcessInstanceCommand

/*
* 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 java.util.List;

import org.apache.log4j.Logger;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.addressing.EPR;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.mapping.ObjectMapper;
import org.jboss.soa.esb.message.mapping.ObjectMappingException;
import org.jboss.soa.esb.services.jbpm.Constants;
import org.jboss.soa.esb.services.jbpm.Mapping;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
import org.jbpm.command.*;
import org.jbpm.command.impl.CommandServiceImpl;
import org.jbpm.graph.exe.ProcessInstance;

/**
* Executes jBPM commands.
*
* @author <a href="mailto:schifest@heuristica.com.ar">schifest@heuristica.com.ar</a>
* @author <a href="mailto:kurt.stam@jboss.com">Kurt Stam</a>
*
*/
public class CommandExecutor
{
    private static CommandExecutor commandExecutor = new CommandExecutor();
   
    private static Logger logger = Logger.getLogger(CommandExecutor.class);
    private static JbpmConfiguration jbpmConfig;
    private static CommandService   jbpmService;
 
    public static CommandExecutor getInstance()
    {
        return commandExecutor;
    }
   
  public Command getCommand(String commandString) throws ConfigurationException
  {
    Constants.OpCode opCode = Constants.OpCode.valueOf(commandString);
    Command command = _values.get(opCode);
    if (null==command)
      throw new ConfigurationException(opCode.toString()+" not implemented,");
    return command;
  }
   
  protected static final Command CANCEL_PROCESS_INSTANCE_EXECUTOR = new Command()
  {
    public void execute(Message message) throws JbpmException
    {
      long processId = MessageHelper.getLongValue(message,Constants.PROCESS_INSTANCE_ID);
            logger.debug("Cancel Process Instance Command for ProcessId=" + processId);
      executeJbpmCommand(new CancelProcessInstanceCommand(processId));
    }
  };

  protected static final Command SIGNAL_EXECUTOR=new Command()
  {
    public void execute(Message message) throws JbpmException
    {
      SignalCommand command = new SignalCommand();
      Long tokenId = MessageHelper.getLongValue(message,Constants.TOKEN_ID);   
      if (null== tokenId)
      {
                Long processInstanceId = MessageHelper.getLongValue(message,Constants.PROCESS_INSTANCE_ID);
                logger.debug("TokenId was not found, so try to obtain the root token from this process definition, " +
                        " with ProcessId=" + processInstanceId);
        // now try with the process id (use root token)
        if (processInstanceId==null) {
          throw new JbpmException("Either <"+Constants.TOKEN_ID+"> or <"+Constants.PROCESS_INSTANCE_ID
            +"> object must be specified in Message body to know who to signal");
                }
        ProcessInstance inst = (ProcessInstance)getJbpmCommandService()
            .execute(new GetProcessInstanceCommand(processInstanceId));
        tokenId  = inst.getRootToken().getId();
      }
      command.setTokenId(tokenId);
     
      String transition = MessageHelper.getStringValue(message, Constants.TRANSITION_NAME);
      if (null!=transition)
        command.setTransitionName(transition);
           
      //TODO allow for precise setting
      Map map = (Map)MessageHelper.getObjectValue(message, Constants.VARIABLE_VALUES);
      if (null!=map) command.setVariables(map);
     
            logger.debug("Signaling Process with TokenId=" + tokenId + ", Transition=" + transition + ", VariableMap=" + map);
      executeJbpmCommand(command);
    }
  };
   
    protected static final Command CALLBACK_EXECUTOR=new Command()
    {
        public void execute(Message message) throws JbpmException
        {
            CallbackCommand command = new CallbackCommand();
            EPR toEpr = message.getHeader().getCall().getTo();
            command.setCallbackEpr(toEpr);
            command.setMessage(message);
               
            String transition = (toEpr.getAddr().getExtensionValue(Constants.TRANSITION_NAME));
            //The transition can be overriden if needed, by setting the following variable.
            String overriddenTransition = MessageHelper.getStringValue(message, Constants.TRANSITION_NAME);
            if (overriddenTransition!=null) {
                if (transition!=null) logger.debug("Overriding the transition to " + overriddenTransition);
                transition = overriddenTransition;
            }
            if (null!=transition) command.setTransitionName(transition);
            logger.debug("Signaling Process with Transition=" + transition);
            executeJbpmCommand(command);
        }
    };

  protected static final Map<Constants.OpCode,Command> _values = new HashMap<Constants.OpCode,Command>()
  static
  {
        _values.put(Constants.OpCode.CallbackCommand             ,CALLBACK_EXECUTOR);
    _values.put(Constants.OpCode.CancelProcessInstanceCommand,CANCEL_PROCESS_INSTANCE_EXECUTOR);
    _values.put(Constants.OpCode.NewProcessInstanceCommand 
        ,new CommandExecutor.NewProcessInstancePerformer(false));
    _values.put(Constants.OpCode.StartProcessInstanceCommand
        ,new CommandExecutor.NewProcessInstancePerformer(true));
        _values.put(Constants.OpCode.GetProcessInstanceVariablesCommand, new GetProcessVariablesPerformer());
  }
 
  // this class is used both for NewProcessInstance and for StartProcessInstance
  protected static final class NewProcessInstancePerformer implements Command
  {
    private boolean _start;
    public NewProcessInstancePerformer(boolean start) { _start = start; }
       
    public void execute(Message request) throws JbpmException
    {
      perform(request,_start);
    }
   
    private void perform(Message esbMessage, boolean start)
    {
            ObjectMapper objectMapper = new ObjectMapper();
            final NewProcessInstanceCommand command ;
            if (start) {
                final String transition = MessageHelper.getStringValue(esbMessage, Constants.TRANSITION_NAME);
                command = new AsyncStartProcessInstanceCommand(transition);
            } else {
                command = new NewProcessInstanceCommand();
            }
      Long processDefId = MessageHelper.getLongValue(esbMessage,Constants.PROCESS_DEFINITION_ID);
            if (null!=processDefId) {
                command.setProcessId(processDefId);
            } else {
               String processName  = MessageHelper.getStringValue(esbMessage,Constants.PROCESS_DEFINITION_NAME);
               if (null!=processName) {
                   command.setProcessName(processName);
               } else {
                   throw new JbpmException("At least one of "+Constants.PROCESS_DEFINITION_NAME
            +" or "+Constants.PROCESS_DEFINITION_ID+" must have a valid value");
               }
            }
            String keyPath = MessageHelper.getStringValue(esbMessage, Constants.KEYPATH);
            if (keyPath!=null) {
                try {
                    String key = String.valueOf(objectMapper.getObjectFromMessage(esbMessage, keyPath));
                    command.setKey(key);
                } catch (ObjectMappingException e) {
                    logger.error("Could not locate key " + e.getMessage(), e);
                }
            }
      String actorId=MessageHelper.getStringValue(esbMessage, Constants.ACTOR_ID);
      if (null!=actorId) command.setActorId(actorId);
      Boolean createStartTask = MessageHelper.getBooleanValue(esbMessage, Constants.CREATE_START_TASK);
      if (null!=createStartTask) command.setCreateStartTask(createStartTask);
     
      Map<String, Object> variables = MessageHelper.getVariablesMap(esbMessage, Constants.VARIABLE_VALUES);
     
      final String replyTo = MessageHelper.getStringValue(esbMessage, Constants.REPLY_TO) ;
      final String faultTo = MessageHelper.getStringValue(esbMessage, Constants.FAULT_TO) ;
     
      if ((replyTo != null) || (faultTo != null)) {
        final Map<String, Object> newVariables = (variables == null ? new HashMap<String, Object>() : new HashMap<String, Object>(variables)) ;
        if (replyTo != null) {
          newVariables.put(Constants.REPLY_TO, replyTo) ;
        }
        if (faultTo != null) {
          newVariables.put(Constants.FAULT_TO, faultTo) ;
        }
          newVariables.put(Constants.ESB_MESSAGE_ID, esbMessage.getHeader().getCall().getMessageID());
         
        variables = newVariables ;
      }
      if (null!=variables) command.setVariables(variables);
           
            logger.debug("New process instance with command=" + command);
            Object result = executeJbpmCommand(command);

            if(result instanceof ProcessInstance) {
                ProcessInstance processInstance = (ProcessInstance) result;

                MessageHelper.setLongValue(esbMessage, Constants.PROCESS_INSTANCE_ID, processInstance.getId());
            }
        }
  }

    private static class GetProcessVariablesPerformer implements Command {
       
        public void execute(Message message) throws JbpmException {
            Long processInstanceId = MessageHelper.getLongValue(message,Constants.PROCESS_INSTANCE_ID);

            if (processInstanceId == null) {
                throw new JbpmException("'" + Constants.PROCESS_INSTANCE_ID + "' must be specified in Message body.  Cannot retrieve process variables.");
            }

            ProcessInstance processInstance = (ProcessInstance)getJbpmCommandService().execute(new GetProcessInstanceCommand(processInstanceId));
            if(processInstance == null) {
                throw new JbpmException("Unknown jBPM process instance ID '" + processInstanceId + "'.");
            }

            VariablesCommand command = new HungryVariablesCommand();

            command.setTokenId(processInstance.getRootToken().getId());
            Object result = getJbpmCommandService().execute(command);
            if(result instanceof Map) {
                Map processVariables = (Map) result;
                List<Mapping> variableMappings = GetProcessVariablesFacade.getMappings(message);

                for (Mapping mapping : variableMappings) {
                    Object value = processVariables.get(mapping.getBpm());
                    ObjectMapper mapper = new ObjectMapper();

                    try {
                        if(value != null) {
                            mapper.setObjectOnMessage(message, mapping.getEsb(), value);
                        } else {
                            mapper.setObjectOnMessage(message, mapping.getEsb(), mapping.getDefaultValue());
                        }
                    } catch (ObjectMappingException e) {
                        throw new JbpmException("Failed to apply jBPM->ESB mapping for process instance ID '" + processInstanceId + "' (root token ID '" + processInstance.getRootToken().getId() + "'). Mapping: " + mapping);
                    }
                }
            } else if(result == null) {
                throw new JbpmException("Invalid 'null' jBPM VariablesCommand result for process instance ID '" + processInstanceId + "' (root token ID '" + processInstance.getRootToken().getId() + "').");
            } else {
                throw new JbpmException("Invalid jBPM VariablesCommand result type '" + result.getClass().getName() + "' for process instance ID '" + processInstanceId + "' (root token ID '" + processInstance.getRootToken().getId() + "')..  Expected instanceof '" + Map.class.getName() + "'.");
            }
        }
    }

    private static Object executeJbpmCommand(org.jbpm.command.Command command)
    {
        if (logger.isDebugEnabled()) {
            logger.debug(command);
        }

        return getJbpmCommandService().execute(command);
    }
   
    /**
     * Encapsulate obtention of jBPM CommandService.
     * @return CommandService
     */
    public static CommandService getJbpmCommandService()
    {
        if (null== jbpmService) {
                jbpmConfig = JbpmConfiguration.getInstance();
                jbpmService = new CommandServiceImpl(jbpmConfig);
        }
        return jbpmService;
    }
   
    /**
     * Command responsible for creating a process instance and firing an asynchronous signal to the root node.
     *
     * @author <a href='kevin.conner@jboss.com'>Kevin Conner</a>
     */
    private static class AsyncStartProcessInstanceCommand extends NewProcessInstanceCommand
    {
        /**
         * The serial version UID for this class.
         */
        private static final long serialVersionUID = 7917063133912138584L;
       
        /**
         * The name of the transition to signal.
         */
        private final String transitionName ;
       
        /**
         * Create the asynchronous process instance command with the specified transition.
         * @param transitionName The transition to signal or null if the default transition should be used.
         */
        AsyncStartProcessInstanceCommand(final String transitionName)
        {
            this.transitionName = transitionName ;
        }
       
        /**
         * Execute the command.
         * @param jbpmContext The current jBPM context.
         * @throws Exception for any errors.
         */
        @Override
        public Object execute(final JbpmContext jbpmContext)
            throws Exception
        {
            final Object result = super.execute(jbpmContext) ;
            if (result instanceof ProcessInstance)
            {
                final ProcessInstance processInstance = (ProcessInstance)result ;
                AsyncProcessSignal.createSignalJob(jbpmContext, processInstance.getRootToken(), transitionName, getActorId(), false, null) ;
            }
            return result ;
        }
    }
}
TOP

Related Classes of org.jboss.soa.esb.services.jbpm.cmd.CommandExecutor$AsyncStartProcessInstanceCommand

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.