Package org.apache.agila.engine

Source Code of org.apache.agila.engine.MessageProcessor

/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed 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.agila.engine;

import org.apache.agila.impl.EngineMessageImpl;
import org.apache.agila.impl.NodeContextImpl;
import org.apache.agila.model.BusinessProcess;
import org.apache.agila.model.Connection;
import org.apache.agila.model.Node;
import org.apache.agila.services.BusinessProcessService;
import org.apache.agila.services.InstanceService;
import org.apache.agila.services.log.LogService;
import org.apache.agila.services.notification.NotificationService;
import org.apache.agila.services.QueueService;
import org.apache.agila.services.task.TaskService;
import org.apache.agila.services.TimerService;
import org.apache.agila.services.TokenService;


/**
*  Core class to process messages.  Messages are the mechanism through which
*  state is advanced for each instance.
*
*  Each engine message contains a command, currently either 'advance' or 'halt'
*  and information required to perform the action, including token id.
*
*
* @author <a href="mailto:geir@gluecode.com">Geir Magnusson Jr.</a>
* @version $Id: MessageProcessor.java 38 2005-06-01 19:39:54Z chirino $
*/
public class MessageProcessor {

    private TokenService tokenService = null;
    private BusinessProcessService wm = null;
    private InstanceService eiSvc = null;
    private TimerService timerService;
    private TaskService taskService = null;
    private QueueService queue = null;
    private NotificationService notificationService = null;

    private LogService logger = null;

    public void setLogService(LogService l) {
        this.logger = l;
    }

    public void setQueueService(QueueService qs) {
        this.queue = qs;
    }

    public void setTokenService(TokenService tokenService) {
        this.tokenService = tokenService;
    }

    public void setBusinessProcessService(BusinessProcessService wm) {
        this.wm = wm;
    }

    public void setExecutionInstanceService(InstanceService eiSvc) {
        this.eiSvc = eiSvc;
    }

    public void setTimerService(TimerService timerService) {
        this.timerService = timerService;
    }

    public void setTaskService(TaskService taskService) {
        this.taskService = taskService;
    }

    public void setNotificationService(NotificationService notificationService) {
        this.notificationService = notificationService;
    }

    /**
     *  Message processing routine.  This method is called by the QueueService.
     *
     * @param msg
     */
    public boolean processMessage(EngineMessage msg) {

        if (msg == null) {
            logger.error("Received null EngineMessage");
            return false;
        }

        /*
         * get the current token
         */

        Token tk = tokenService.getTokenByID(msg.getCurrentTokenID());

        if (tk == null) {
            logger.error("Received null token for msg = " + msg);
            return false;
        }

        Instance ei = eiSvc.getInstanceByID(tk.getInstanceID());

        logger.debug("processMessage : " + msg + " for procid="
                + ei.getBusinessProcessID()
                + " instanceid = " + ei.getInstanceID());

        /*
         * safety check
         */

        if (!tk.isActive()) {

            logger.error("error!  out of synch for instance id = "
                    + tk.getInstanceID() + " instance no longer active");
            return false;
        }

        /*
         *   // TODO - handle 'verb' in message
         */

        BusinessProcess graph = wm.getGraphByID(
                eiSvc.getInstanceByID(tk.getInstanceID()).getBusinessProcessID());

        Node n = graph.getNode(tk.getCurrentNodeID());

        NodeContextImpl nc = new NodeContextImpl(n, ei, timerService,
                taskService, notificationService);

        nc.setAppData(msg.getAppData());

        /*
         * now examine the state of this token and process accordingly.
         */

        switch(tk.getCurrentState()) {

            /*
             *  in 'pre start' state for this node.  Setup, call the doStart()
             *  method, and then based on the return from doStart(), either
             *  create and fling another message back into the queue, or stop
             *  and wait for response from outside
             */

            case Token.PRE : {

                logger.debug("processMessage : Current state = PRE for " + tk);

                /**
                 *  must send new token b/c it can be used as the current token...
                 */

                Token newToken = tokenService.newToken(tk.getInstanceID(),
                                                      tk.getCurrentNodeID(),
                                                      Token.MID);

                nc.setCurrentExecutionToken(tk);
                nc.setNextExecutionToken(newToken);

                boolean ret = n.doStart(nc);

                if (ret == true) {

                    EngineMessage newMsg = new EngineMessageImpl();

                    newMsg.setCurrentTokenID(newToken.getTokenID());

                    queue.enqueue(newMsg);
                }

                break;
            }

            /*
             *  this state is 'between' doStart() and doEnd().  So prepare
             *  context and call doEnd()
             */

            case Token.MID : {

                logger.debug("processMessage : Current state = MID for " + tk);

                nc.setCurrentExecutionToken(tk);

                /*
                 *  call doEnd() and get the set of conenctions that we need
                 *  to traverse, or null if we are to stop
                 */
                Connection[] c = n.doEnd(nc);

                if (c != null && c.length > 0) {

                    Token[] newTokens = tokenService.nextToken(c, tk);

                    for(int i = 0; i < c.length; i++) {

                        EngineMessage newMsg = new EngineMessageImpl();
                        newMsg.setCurrentTokenID(newTokens[i].getTokenID());
                        queue.enqueue(newMsg);
                    }
                }
                else {
                    // all done

                    ei.setStatus(Instance.STATUS_COMPLETE);

                    logger.debug("no connection - done");
                }
                break;
            }

            default :
                break;
        };

        /*
         *  now set the old token status to inactive
         *
         *  TODO - think about this...  we want to make sure that we always have
         *  an active token for any given execution thread to be sure that joins
         *  don't get fooled
         */

        tk.setActive(false);

        return true;
    }
}
TOP

Related Classes of org.apache.agila.engine.MessageProcessor

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.