Package au.edu.qut.yawl.engine

Source Code of au.edu.qut.yawl.engine.YNetRunner

/*
* This file is made available under the terms of the LGPL licence.
* This licence can be retreived from http://www.gnu.org/copyleft/lesser.html.
* The source remains the property of the YAWL Foundation.  The YAWL Foundation is a collaboration of
* individuals and organisations who are commited to improving workflow technology.
*
*/


package au.edu.qut.yawl.engine;

import au.edu.qut.yawl.elements.*;
import au.edu.qut.yawl.elements.state.YIdentifier;
import au.edu.qut.yawl.exceptions.*;
import au.edu.qut.yawl.engine.interfce.interfaceX.InterfaceX_EngineSideClient;
import au.edu.qut.yawl.util.JDOMConversionTools;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;

import java.util.*;

/**
*
*
* @author Lachlan Aldred
*         Date: 16/04/2003
*         Time: 16:08:01
*
*/
public class YNetRunner // extends Thread
{
    private static Logger logger;

    protected YNet _net;
    private Set _enabledTasks = new HashSet();
    private Set _busyTasks = new HashSet();
    private Set _suspTasks = new HashSet();   // added

    private static YWorkItemRepository _workItemRepository = YWorkItemRepository.getInstance();
    private YIdentifier _caseIDForNet;
    private YCompositeTask _containingCompositeTask;
    private YEngine _engine;
    private boolean _cancelling;

    /**
     * **************************
     * INSERTED FOR PERSISTANCE
     * ***************************
     */
    protected String yNetID = null;
    private Set enabledTaskNames = new HashSet();
    private Set busyTaskNames = new HashSet();
    private P_YIdentifier _standin_caseIDForNet;
    private String _caseID = null;
    private String containingTaskID = null;
    private YCaseData casedata = null;
    private YAWLServiceReference _caseObserver;
    private InterfaceX_EngineSideClient _exceptionObserver;

    // inserted to persist observers
    private String _caseObserverStr = null ;
    private String _exceptionObserverStr = null ;

    /*****************************/

    /*************************************/
    /*INSERTED METHODS*/
    /**
     * *********************************
     */

    public void restoreprepare() {
        _workItemRepository.setNetRunnerToCaseIDBinding(this, _caseIDForNet);
        //_net.initialise();
    }

    public void setTask(YCompositeTask task) {
        this._containingCompositeTask = task;
    }

    public String getContainingTaskID() {
        return containingTaskID;
    }

    public void setContainingTaskID(String taskid) {
        containingTaskID = taskid;
    }

    public void setNet(YNet net) {
        _net = net;
        yNetID = net.getSpecification().getID();
        _net.restoreData(casedata);
    }

    public YNet getNet() {
        return _net;
    }

    public void setEngine(YEngine engine) {
        _engine = engine;
    }

    public void setYNetID(String id) {
        this.yNetID = id;
    }

    public String getYNetID() {
        return yNetID;
    }



    public YCaseData getCasedata() {
        return casedata;
    }

    public void setCasedata(YCaseData data) {
        casedata = data;
    }

    //todo Refactor this to use getCaseID()?  signed Lach
    public YIdentifier get_caseIDForNet() {
        return _caseIDForNet;
    }


    public void set_caseIDForNet(YIdentifier id) {
        this._caseIDForNet = id;
        _caseID = _caseIDForNet.toString();
    }

    public P_YIdentifier get_standin_caseIDForNet() {
        return _standin_caseIDForNet;
    }

    public void set_standin_caseIDForNet(P_YIdentifier id) {
        this._standin_caseIDForNet = id;
    }

    public void addBusyTask(YExternalNetElement ext) {
        _busyTasks.add(ext);
    }

    public void addEnabledTask(YExternalNetElement ext) {
        _enabledTasks.add(ext);
    }


    public String get_caseID() {
        return this._caseID;
    }

    public void set_caseID(String ID) {
        this._caseID = ID;
    }

    public Set getEnabledTaskNames() {
        return enabledTaskNames;
    }

    public Set getBusyTaskNames() {
        return busyTaskNames;
    }
    /************************************************/


    /**
     * Needed for hibernate to work.
     */
    private YNetRunner() {
        logger = Logger.getLogger(this.getClass());
        logger.debug("YNetRunner: <init>");
    }


    public YNetRunner(YPersistenceManager pmgr, YNet netPrototype, Element paramsData) throws YDataStateException, YSchemaBuildingException, YPersistenceException {
//        super("NetRunner:" + netPrototype.getID());
        _caseIDForNet = new YIdentifier();
        /*
        INSERTED FOR PERSISTANCE
        */
//        YPersistance.getInstance().storeData(_caseIDForNet);
        if (pmgr != null) {
            pmgr.storeObject(_caseIDForNet);
        }
        _caseID = _caseIDForNet.toString();
        /*****************************/

        _net = (YNet) netPrototype.clone();

        /*
  INSERTED FOR PERSISTANCE
*/
        casedata = new YCaseData();
        casedata.setId(_caseID);
        _net.initializeDataStore(pmgr, casedata);
        /*************************************/

        _engine = YEngine.getInstance();
        /*
          INSERTED FOR PERSISTANCE
         */
        yNetID = netPrototype.getSpecification().getID();
        /*****************************/

        prepare(pmgr);
        if(paramsData != null) {
            _net.setIncomingData(pmgr, paramsData);
        }
    }


    public YNetRunner(YPersistenceManager pmgr, YNet netPrototype, YCompositeTask container, YIdentifier caseIDForNet, Element incomingData) throws YDataStateException, YSchemaBuildingException, YPersistenceException {
//        super("NetRunner:" + netPrototype.getID());
        _caseIDForNet = caseIDForNet;
        _caseID = _caseIDForNet.toString();
        /*****************************/
        _net = (YNet) netPrototype.clone();
        /*
  INSERTED FOR PERSISTANCE
*/
        casedata = new YCaseData();
        casedata.setId(_caseID);
        _net.initializeDataStore(pmgr, casedata);
        /*****************************/
        _containingCompositeTask = container;
        _engine = YEngine.getInstance();

        /*
          INSERTED FOR PERSISTANCE
         */
        yNetID = netPrototype.getSpecification().getID();
        setContainingTaskID(container.getID());
        /******************************/
        prepare(pmgr);
        _net.setIncomingData(pmgr, incomingData);

        if (pmgr != null) {
            pmgr.storeObject(this);
        }
    }


    private void prepare(YPersistenceManager pmgr) throws YPersistenceException {
        _workItemRepository.setNetRunnerToCaseIDBinding(this, _caseIDForNet);
        YInputCondition inputCondition = _net.getInputCondition();
        inputCondition.add(pmgr, _caseIDForNet);
        _net.initialise(pmgr);

        /*
        Uncommented for persistance
        */
        //continueIfPossible();
    }


    /**
     * COPIED INTO KICK METHOD !!!
     */
    /*
    public void run()
    {
        logger = Logger.getLogger(this.getClass());
        logger.debug("--> YNetRunner.run");

        while (continueIfPossible())
        {
            try
            {
                synchronized (this)
                {
                    Logger.getLogger(this.getClass()).debug("THREAD WAITING ...");
                    wait();
                    Logger.getLogger(this.getClass()).debug("THREAD KICKED");
                }
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }

        if (_engine != null)
        {
            Logger.getLogger(this.getClass()).debug("Asking engine to finish case");
            _engine.finishCase(_caseIDForNet);

            if (_caseIDForNet.toString().indexOf(".") == -1)
            {
                try
                {
                    YPersistance.getInstance().clearCase(_caseIDForNet);
                }
                catch (Exception e)
                {
                    //todo So, what shall we do now ????
                }
            }

        }

        _workItemRepository.cancelNet(_caseIDForNet);
        if (!_cancelling && deadLocked())
        {
            notifyDeadLock();
        }
        cancel();

        logger.debug("<-- YNetRunner.run");

    }
    */

    public void start(YPersistenceManager pmgr) throws YPersistenceException {
        kick(pmgr);
    }


    public boolean isAlive() {
        if (_cancelling) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * Assumption: this will only get called AFTER a workitem has been progressed?
     * Because if it is called any other time then it will cause the case to stop.
     * @param pmgr
     * @throws YPersistenceException
     */
    public void kick(YPersistenceManager pmgr) throws YPersistenceException {
        logger = Logger.getLogger(this.getClass());
        logger.debug("--> YNetRunner.kick");

        boolean progressed = continueIfPossible(pmgr);

        if (!progressed) {
            logger.debug("YNetRunner not able to continue");
            if (_engine != null) {
                //case completion
                if (_caseObserver != null) {
                    _engine.announceCaseCompletionToEnvironment(_caseObserver,
                                      _caseIDForNet, _net.getOutputData());
                }

                // notify exception checkpoint to service if available (post's for case end)
                if (_exceptionObserver != null) {
                    Document data = _net.getInternalDataDocument();
                    _engine.announceCheckCaseConstraints(_exceptionObserver, null, _caseID,
                                       JDOMConversionTools.documentToString(data), false);
                }

                Logger.getLogger(this.getClass()).debug("Asking engine to finish case");
                _engine.finishCase(pmgr, _caseIDForNet);

                if (isRootNet()) {
                    try {
                        _engine.clearCase(pmgr, _caseIDForNet);
                    } catch (Exception e) {
                        //todo So, what shall we do now ????
                    }
                }
            }
            if (!_cancelling && deadLocked()) {
                notifyDeadLock(pmgr);
            }
            cancel(pmgr);
        }
        logger.debug("<-- YNetRunner.kick");
    }

    private boolean isRootNet() {
        return _caseIDForNet.getParent() == null;
    }


    private void notifyDeadLock(YPersistenceManager pmgr) throws YPersistenceException {
        List locations = _caseIDForNet.getLocations();
        for (int i = 0; i < locations.size(); i++) {
            YNetElement element = (YNetElement) locations.get(i);
            if (_net.getNetElements().values().contains(element)) {
                if (element instanceof YTask) {
                    createDeadlockItem(pmgr, (YTask) element);
                }
                Set postset = ((YExternalNetElement) element).getPostsetElements();
                if (postset.size() > 0) {
                    for (Iterator iterator = postset.iterator(); iterator.hasNext();) {
                        YExternalNetElement postsetElement = (YExternalNetElement) iterator.next();
                        createDeadlockItem(pmgr, postsetElement);
                    }
                }
            }
        }
    }


    private void createDeadlockItem(YPersistenceManager pmgr, YExternalNetElement netElement) throws YPersistenceException {
        String specificationID = _net.getSpecification().getID();
        boolean allowsNewInstances = false;
        boolean isDeadlocked = true;
        YWorkItemID deadlockWorkItemID = new YWorkItemID(_caseIDForNet,
                netElement.getID());
        new YWorkItem(pmgr, specificationID,
                deadlockWorkItemID,
                allowsNewInstances,
                isDeadlocked);
        //Log to Problems table of database.
        YProblemEvent event  = new YProblemEvent(_net, "Deadlocked", YProblemEvent.RuntimeError);
        event.logProblem(pmgr);
    }


    /**
     * Assumption: there are no enabled tasks
     * @return if deadlocked
     */
    private boolean deadLocked() {
        List locations = _caseIDForNet.getLocations();
        for (int i = 0; i < locations.size(); i++) {
            Object o = locations.get(i);
            if(o instanceof YExternalNetElement) {
                YExternalNetElement element = (YExternalNetElement) o;
                if (element.getPostsetElements().size() > 0) {
                    return true;
                }
            }
        }
        return false;
    }


    private synchronized void processCompletedSubnet(YPersistenceManager pmgr, YIdentifier caseIDForSubnet, YCompositeTask busyCompositeTask,
                                                     Document rawSubnetData)
            throws YDataStateException, YStateException, YQueryException, YSchemaBuildingException, YPersistenceException {
        Logger.getLogger(this.getClass()).debug("--> processCompletedSubnet");

        if (caseIDForSubnet == null) {
            throw new RuntimeException();
        }
        boolean compositeTaskExited = busyCompositeTask.t_complete(pmgr, caseIDForSubnet, rawSubnetData);
        if (compositeTaskExited) {
            _busyTasks.remove(busyCompositeTask);

            /******************
             INSERTED FOR PERSISTANCE
             */
//            YPersistance.getInstance().updateData(this);
            if (pmgr != null) {
                pmgr.updateObject(this);
            }
            /***************************/

            Logger.getLogger(this.getClass()).debug("NOTIFYING RUNNER");
//            notify();
            kick(pmgr);

//            String caseIDStr = caseIDForSubnet.toString();
//            String taskIDStr = busyCompositeTask.getID();
//            YWorkItem item = _workItemRepository.getEngineStoredWorkItem(
//                    caseIDStr,
//                    taskIDStr);
//            _workItemRepository.removeWorkItemFamily(item);
//            YWorkItem item = YLocalWorklist.getEngineStoredWorkItem(caseIDForSubnet.toString(), busyCompositeTask.getURI());
//            YLocalWorklist.removeWorkItemFamily(item);
        }

        Logger.getLogger(this.getClass()).debug("<-- processCompletedSubnet");

    }


    public List attemptToFireAtomicTask(YPersistenceManager pmgr, String taskID)
            throws YDataStateException, YStateException, YQueryException, YPersistenceException {
        YAtomicTask task = (YAtomicTask) _net.getNetElement(taskID);
        if (task.t_enabled(_caseIDForNet)) {
            List newChildIdentifiers = task.t_fire(pmgr);
            _enabledTasks.remove(task);

            //todo AJH - Why persist twice here ??????
            /*
             INSERTED FOR PERSISTANCE
            */
            enabledTaskNames.remove(task.getID());
//            YPersistance.getInstance().updateData(this);
            if (pmgr != null) {
                pmgr.updateObject(this);
            }

            /**********************/
            _busyTasks.add(task);
            /*
  INSERTED FOR PERSISTANCE
*/
            busyTaskNames.add(task.getID());
//            YPersistance.getInstance().updateData(this);
            if (pmgr != null) {
                pmgr.updateObject(this);
            }

            /******************************/
            synchronized (this) {
                Logger.getLogger(this.getClass()).debug("NOTIFYING RUNNER");
//                notify();
                kick(pmgr);
            }
            return newChildIdentifiers;
        }
        return null;
    }


    public synchronized YIdentifier addNewInstance(YPersistenceManager pmgr, String taskID, YIdentifier aSiblingInstance, Element newInstanceData)
            throws YDataStateException, YStateException, YQueryException, YSchemaBuildingException, YPersistenceException {
        YAtomicTask task = (YAtomicTask) _net.getNetElement(taskID);
        if (task.t_isBusy()) {
            return task.t_add(pmgr, aSiblingInstance, newInstanceData);
        }
        return null;
    }


    public synchronized void startWorkItemInTask(YPersistenceManager pmgr, YIdentifier caseID, String taskID) throws YDataStateException, YSchemaBuildingException, YPersistenceException {
        YAtomicTask task = (YAtomicTask) _net.getNetElement(taskID);
        task.t_start(pmgr, caseID);
    }


    public synchronized boolean completeWorkItemInTask(YPersistenceManager pmgr, YWorkItem workItem, YIdentifier caseID, String taskID, Document outputData)
            throws YDataStateException, YStateException, YQueryException, YSchemaBuildingException, YPersistenceException {
        logger.debug("--> completeWorkItemInTask");
        YAtomicTask task = (YAtomicTask) _net.getNetElement(taskID);
        try {
            boolean success = completeTask(pmgr, workItem, task, caseID, outputData);

            // notify exception checkpoint to service if available
            if (_exceptionObserver != null)
                _engine.announceCheckWorkItemConstraints(_exceptionObserver, workItem, outputData, false);

            logger.debug("<-- completeWorkItemInTask");
            return success;
        } catch (YDataStateException e) {
            YProblemEvent ev = new YProblemEvent(task,
                    e.getMessage(),
                    YProblemEvent.RuntimeError);
            ev.logProblem(pmgr);
            throw e;
        }
    }


    public synchronized boolean continueIfPossible(YPersistenceManager pmgr) throws YPersistenceException {
        Logger.getLogger(this.getClass()).debug("--> continueIfPossible");
        List tasks = new ArrayList(_net.getNetElements().values());

        Iterator tasksIter = tasks.iterator();
        while (tasksIter.hasNext()) {
            YExternalNetElement netElement = (YExternalNetElement) tasksIter.next();
            if (netElement instanceof YTask) {
                YTask task = (YTask) netElement;

                if (task.t_enabled(_caseIDForNet)) {
                    boolean taskRecordedAsEnabled = _enabledTasks.contains(task);

                    boolean taskRecordedAsBusy = _busyTasks.contains(task);

                    if (!taskRecordedAsEnabled && !taskRecordedAsBusy) {

                        if (task instanceof YAtomicTask) {
                            YAtomicTask atomicTask = (YAtomicTask) task;
                            YAWLServiceGateway wsgw = (YAWLServiceGateway) atomicTask.getDecompositionPrototype();
                            //if its not an empty task
                            if (wsgw != null) {
                                createEnabledWorkItem(pmgr, _caseIDForNet, atomicTask);
                                YAWLServiceReference ys = wsgw.getYawlService();
                                YWorkItem item = _workItemRepository.getWorkItem(_caseIDForNet.toString(), atomicTask.getID());
                                if (ys != null) {
                                    _engine.announceEnabledTask(ys, item);
                                }
                                if (_exceptionObserver != null)
                                    _engine.announceCheckWorkItemConstraints(_exceptionObserver, item, _net.getInternalDataDocument(), true);

                                _enabledTasks.add(task);

                                /*************************/
                                /* INSERTED FOR PERSISTANCE*/
                                enabledTaskNames.add(task.getID());
//                                YPersistance.getInstance().updateData(this);
                                if (pmgr != null) {
                                    pmgr.updateObject(this);
                                }

                                /***********************/
                            } else {
                                //fire the empty atomic task
                                YIdentifier id = null;
                                try {
                                    id = (YIdentifier) atomicTask.t_fire(pmgr).iterator().next();
                                    atomicTask.t_start(pmgr, id);
                                    completeTask(pmgr, null, atomicTask, id, null);//atomicTask.t_complete(id);
                                } catch (YAWLException e) {
                                    YProblemEvent pe =
                                            new YProblemEvent(atomicTask,
                                                    e.getMessage(),
                                                    YProblemEvent.RuntimeError);
                                    pe.logProblem(pmgr);
                                }
                            }
                        } else {
                            //fire the composite task
                            _busyTasks.add(task);

                            /*************************/
                            /* INSERTED FOR PERSISTANCE*/
                            busyTaskNames.add(task.getID());
//                            YPersistance.getInstance().updateData(this);
                            if (pmgr != null) {
                                pmgr.updateObject(this);
                            }
                            /****************************/

                            Iterator caseIDs = null;
                            try {
                                caseIDs = task.t_fire(pmgr).iterator();
                            } catch (YAWLException e) {
                                e.printStackTrace();
                                YProblemEvent pe =
                                        new YProblemEvent(task,
                                                e.getMessage(),
                                                YProblemEvent.RuntimeError);
                                pe.logProblem(pmgr);
                            }
                            while (caseIDs.hasNext()) {
                                YIdentifier id = (YIdentifier) caseIDs.next();
                                try {
                                    task.t_start(pmgr, id);
                                } catch (YSchemaBuildingException e) {
                                    YProblemEvent f = new YProblemEvent(task,
                                            e.getMessage(),
                                            YProblemEvent.RuntimeError);
                                    f.logProblem(pmgr);
                                    e.printStackTrace();
                                } catch (YDataStateException e) {
                                    YProblemEvent f = new YProblemEvent(task,
                                            e.getMessage(),
                                            YProblemEvent.RuntimeError);
                                    f.logProblem(pmgr);
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                } else /*if (!task.t_enabled(_caseIDForNet))*/ {

                    if (_enabledTasks.contains(task)) {
//                        YLocalWorklist.announceToWorklistsNoLongerEnabled(_caseIDForNet, task.getID());
                        _enabledTasks.remove(task);
                        /*************************/
                        /* INSERTED FOR PERSISTANCE*/
                        enabledTaskNames.remove(task.getID());

                        /**
                         * AJH: Bugfix: We need to remove from persistence the cancelled task
                         */
                        YWorkItem wItem = _workItemRepository.getWorkItem(_caseID, task.getID());
                        if (pmgr != null)
                        {
                            pmgr.deleteObject(wItem);
                        }                       
//                        YPersistance.getInstance().updateData(this);
                        if (pmgr != null) {
                            pmgr.updateObject(this);
                        }

                        /******************/
                    }

                }
                if (task.t_isBusy() && !_busyTasks.contains(task)) {
                    logger.error("Throwing RTE for lists out of sync");
                    throw new RuntimeException("busy task list out of synch with a busy task: " + task.getID() + " busy tasks: " + _busyTasks);
                }
            }
        }
        _busyTasks = _net.getBusyTasks();

        Logger.getLogger(this.getClass()).debug("<-- continueIfPossible");
        return _enabledTasks.size() > 0 || _busyTasks.size() > 0;
    }


    /**
     * Creates an enabled work item.
     *
     * @param caseIDForNet the caseid for the net
     * @param atomicTask   the atomic task that contains it.
     */
    private void createEnabledWorkItem(YPersistenceManager pmgr, YIdentifier caseIDForNet, YAtomicTask atomicTask) throws YPersistenceException {
        Logger.getLogger(this.getClass()).debug("--> createEnabledWorkItem: Case=" + caseIDForNet.get_idString() + " Task=" + atomicTask.getID());

        boolean allowDynamicCreation =
                atomicTask.getMultiInstanceAttributes() == null ? false :
                YMultiInstanceAttributes._creationModeDynamic.equals(atomicTask.getMultiInstanceAttributes().getCreationMode());

        //creating a new work item puts it into the work item
        //repository automatically.
        YWorkItem workItem = new YWorkItem(pmgr, atomicTask.getNet().getSpecification().getID(),
                new YWorkItemID(caseIDForNet, atomicTask.getID()),
                allowDynamicCreation, false);
        if (atomicTask.getDataMappingsForEnablement().size() > 0) {
            Element data = null;
            try {
                data = atomicTask.prepareEnablementData();
            } catch (YQueryException e) {
                e.printStackTrace();
            } catch (YSchemaBuildingException e) {
                e.printStackTrace();
            } catch (YDataStateException e) {
                //todo log this exception for admin, because the data did not pass schema validation.
                e.printStackTrace();
            } catch (YStateException e) {
                e.printStackTrace();
            }
            workItem.setData(pmgr, data);
        }
    }


    /**
     * Completes a work item inside an atomic task.
     *
     * @param workItem The work item. If null is supplied, this work item cannot be removed from the work items repository (hack)
     * @param atomicTask the atomic task
     * @param identifier the identifier of the work item
     * @param outputData the document containing output data
     * @return whether or not the task exited
     * @throws YDataStateException
     */
    private boolean completeTask(YPersistenceManager pmgr, YWorkItem workItem, YAtomicTask atomicTask, YIdentifier identifier, Document outputData)
            throws YDataStateException, YStateException, YQueryException, YSchemaBuildingException, YPersistenceException {
       // logger.debug("--> completeTask");

        boolean taskExited;

        taskExited = atomicTask.t_complete(pmgr, identifier, outputData);
        if (taskExited) {
            //todo AJH New code here - Relocated from YEngine.completeWorkItem
            if (workItem != null) {
                _engine.getWorkItemRepository().removeWorkItemFamily(workItem);
            }

            //here are check to see if completing this task resulted in completing the net.
            if (this.isCompleted() && _net.getOutputCondition().getIdentifiers().size() == 1) {
                //so now we know the net is complete we check if this net is a subnet.
                if (_containingCompositeTask != null) {
                    YNetRunner parentRunner = _workItemRepository.getNetRunner(_caseIDForNet.getParent());
                    if (parentRunner != null) {
                        synchronized (parentRunner) {
                            if (_containingCompositeTask.t_isBusy()) {

                                if (_net.usesSimpleRootData()) {
                                    parentRunner.processCompletedSubnet(pmgr,
                                            _caseIDForNet,
                                            _containingCompositeTask,
                                            _net.getInternalDataDocument());
                                } else {//version is Beta 4 or greater
                                    parentRunner.processCompletedSubnet(pmgr,
                                            _caseIDForNet,
                                            _containingCompositeTask,
                                            _net.getOutputData());
                                }
                                if (_caseIDForNet == null) {
                                    System.out.println("YNetRunner::completeTask() finished local task: " +
                                            atomicTask + " composite task: " +
                                            _containingCompositeTask +
                                            " caseid for decomposed net: " +
                                            _caseIDForNet);
                                }
                            }
                        }
                    }
                } else if (_engine != null && _containingCompositeTask != null) {
                    _engine.finishCase(pmgr, _caseIDForNet);
                }
            }

            continueIfPossible(pmgr);
            _busyTasks.remove(atomicTask);
            /*
              INSERTED FOR PERSISTANCE
             */
            busyTaskNames.remove(atomicTask.getID());
//            YPersistance.getInstance().updateData(this);

            if (pmgr != null) {
                ArrayList liveCases = (ArrayList) _engine.getRunningCaseIDs();
                if (liveCases.indexOf(_caseIDForNet) > -1) {
                    pmgr.updateObject(this);
                }
            }

            /**************************/
            Logger.getLogger(this.getClass()).debug("NOTIFYING RUNNER");
            //todo Removing this causes sequence problems when going cyclic
            kick(pmgr);
        }
        logger.debug("<-- completeTask: Exited=" + taskExited);
        return taskExited;
    }


    public synchronized void cancel(YPersistenceManager pmgr) throws YPersistenceException {
        logger.debug("--> NetRunner cancel " + this.getCaseID().get_idString());

        _cancelling = true;
        Collection netElements = _net.getNetElements().values();
        Iterator iterator = netElements.iterator();
        while (iterator.hasNext()) {
            YExternalNetElement netElement = (YExternalNetElement) iterator.next();
            if (netElement instanceof YTask) {
                YTask task = ((YTask) netElement);
                if (task.t_isBusy()) {
                    task.cancel(pmgr);
                }
            } else if (((YCondition) netElement).containsIdentifier()) {
                ((YCondition) netElement).removeAll(pmgr);
            }
        }
        _workItemRepository.cancelNet(_caseIDForNet);
        _enabledTasks = new HashSet();
        _busyTasks = new HashSet();

//        _cancelling = false;
    }


    public synchronized boolean rollbackWorkItem(YPersistenceManager pmgr, YIdentifier caseID, String taskID) throws YPersistenceException {
        YAtomicTask task = (YAtomicTask) _net.getNetElement(taskID);
        return task.t_rollBackToFired(pmgr, caseID);
    }


    //###############################################################################
    //                              accessors
    //###############################################################################
    public YExternalNetElement getNetElement(String id) {
        return _net.getNetElement(id);
    }


    public YIdentifier getCaseID() {
        return _caseIDForNet;
    }


    public boolean isCompleted() {
        if (_net.getOutputCondition().containsIdentifier()) {
            return true;
        } else {
            return isEmpty();
        }
    }


    public boolean isEmpty() {
        Iterator elements = _net.getNetElements().values().iterator();
        while (elements.hasNext()) {
            YExternalNetElement element = (YExternalNetElement) elements.next();
            if (element instanceof YCondition) {
                if (((YCondition) element).containsIdentifier()) {
                    return false;
                }
            } else {
                if (((YTask) element).t_isBusy()) {
                    return false;
                }
            }
        }
        return true;
    }


    protected Set getBusyTasks() {
        return _busyTasks;
    }


    protected Set getEnabledTasks() {
        return _enabledTasks;
    }


    public boolean isAddEnabled(String taskID, YIdentifier childID) {
        YAtomicTask task = (YAtomicTask) _net.getNetElement(taskID);
        return task.t_addEnabled(childID);
    }

    public void setObserver(YAWLServiceReference observer) {
        _caseObserver = observer;
        _caseObserverStr = observer.getURI();                       // for persistence
    }


    /***************************************************************************/
    /** The following methods have been added to support the exception service */

    /** sets the IX observer to the specified IX client */
    public void setExceptionObserver(InterfaceX_EngineSideClient observer){
        _exceptionObserver = observer;
        _exceptionObserverStr = observer.getURI();                  // for persistence
     }


    /** restores the IB and IX observers on session startup (via persistence) */
    public void restoreObservers() {
        if(_caseObserverStr != null) {
            YAWLServiceReference caseObserver =
                                    _engine.getRegisteredYawlService(_caseObserverStr);
            if (caseObserver != null) setObserver(caseObserver);
        }
        if (_exceptionObserverStr != null) {
            InterfaceX_EngineSideClient exObserver =
                                new InterfaceX_EngineSideClient(_exceptionObserverStr);
            setExceptionObserver(exObserver);
            _engine.setExceptionObserver(_exceptionObserverStr);
        }
    }


   /** these four methods are here to support persistence of the IB and IX Observers */
    private String get_caseObserverStr() { return _caseObserverStr ; }

    private String get_exceptionObserverStr() { return _exceptionObserverStr ; }

    private void set_caseObserverStr(String obStr) { _caseObserverStr = obStr ; }

    private void set_exceptionObserverStr(String obStr) { _exceptionObserverStr = obStr ; }


    /** cancels the specified task */
    public void cancelTask(YPersistenceManager pmgr, String taskID) {
        YAtomicTask task = (YAtomicTask) getNetElement(taskID);

        try {
            task.cancel(pmgr);
            _busyTasks.remove(task);
            busyTaskNames.remove(task.getID());
        }
        catch (YPersistenceException ype) {
            logger.fatal("Failure whilst cancelling task: " + taskID, ype);

        }
    }


    /** returns true if the specified workitem is registered with the Time Service */
    public boolean isTimeServiceTask(YWorkItem item) {
        YTask task = (YTask) getNetElement(item.getTaskID());
        if ((task != null) && (task instanceof YAtomicTask)) {
            YAWLServiceGateway wsgw = (YAWLServiceGateway) task.getDecompositionPrototype();
            if (wsgw != null) {
                YAWLServiceReference ys = wsgw.getYawlService();
                if (ys != null)
                   return ys.get_yawlServiceID().indexOf("timeService") > -1 ;
            }
        }
        return false ;
    }


    /** returns a list of all workitems executing in parallel to the time-out
        workitem passed (the list includes the time-out task) */
    public List getTimeOutTaskSet(YWorkItem item) {
        YTask timeOutTask = (YTask) getNetElement(item.getTaskID());
        String nextTaskID = getFlowsIntoTaskID(timeOutTask);
        ArrayList result = new ArrayList() ;

        if (nextTaskID != null) {
            List netTasks = new ArrayList(getNet().getNetElements().values());
            Iterator itr = netTasks.iterator();
            while (itr.hasNext()){
               YNetElement yne = (YNetElement) itr.next();
               if (yne instanceof YTask) {
                   YTask task = (YTask) yne;
                   String nextTask = getFlowsIntoTaskID(task);
                   if (nextTask != null) {
                       if (nextTask.equals(nextTaskID))
                          result.add(task.getID());
                   }
               }
            }
        }
        if (result.isEmpty()) result = null ;
        return result;
    }


    /** returns the task id of the task that the specifiedtasks flows into
        In other words, gets the id of the next task in the process flow */
    private String getFlowsIntoTaskID(YTask task) {
        if ((task != null) && (task instanceof YAtomicTask)) {
            Element eTask = JDOMConversionTools.stringToElement(task.toXML());
            return eTask.getChild("flowsInto").getChild("nextElementRef").getAttributeValue("id");
        }
        return null ;
    }
}

TOP

Related Classes of au.edu.qut.yawl.engine.YNetRunner

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.