org.yawlfoundation.yawl.worklet.exception.HandlerRunner.java Source code

Java tutorial

Introduction

Here is the source code for org.yawlfoundation.yawl.worklet.exception.HandlerRunner.java

Source

/*
 * Copyright (c) 2004-2012 The YAWL Foundation. All rights reserved.
 * The YAWL Foundation is a collaboration of individuals and
 * organisations who are committed to improving workflow technology.
 *
 * This file is part of YAWL. YAWL 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.
 *
 * YAWL 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 YAWL. If not, see <http://www.gnu.org/licenses/>.
 */

package org.yawlfoundation.yawl.worklet.exception;

import org.apache.log4j.Logger;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.IllegalAddException;
import org.yawlfoundation.yawl.engine.YSpecificationID;
import org.yawlfoundation.yawl.engine.interfce.WorkItemRecord;
import org.yawlfoundation.yawl.util.JDOMUtil;
import org.yawlfoundation.yawl.worklet.rdr.RdrConclusion;
import org.yawlfoundation.yawl.worklet.rdr.RuleType;
import org.yawlfoundation.yawl.worklet.support.Library;
import org.yawlfoundation.yawl.worklet.support.RdrConversionTools;
import org.yawlfoundation.yawl.worklet.support.WorkletRecord;

import java.util.List;

/** The HandlerRunner class manages an exception handling process. An instance
 *  of this class is created for each exception process raised by a case. The CaseMonitor
 *  class maintains the current set of HandlerRunners for a case (amongst other things).
 *  This class also manages a running worklet instance for a 'parent' case
 *  when required.
 *
 *  The key data member is the RdrConclusion _rdrConc, which contains the
 *  sequential set of exception handling primitives for this particular handler.
 *
 *  @author Michael Adams
 *  @version 0.8, 04-09/2006
 */

public class HandlerRunner extends WorkletRecord {

    private RdrConclusion _rdrConc = null; // steps to run for this handler
    private CaseMonitor _parentMonitor = null; // case that generated this instance
    private int _actionIndex = 1; // index to 'primitives' set
    private int _actionCount = 0; // number of primitives in set
    private boolean _isItemSuspended; // has excepted item been suspended?
    private boolean _isCaseSuspended; // has case been suspended?
    private List<WorkItemRecord> _suspendedItems = null; // list of suspended items - can
    // be child items, or for whole case

    private String _rdrConcStr = null; // required for persistence
    private String _caseID = null;
    private int _id;
    private String _suspList = null;

    /**
      * This constructor is used when an exception is raised at the case level
      * @param monitor the CaseMonitor for the case the generated the exception
      * @param rdrConc the RdrConclusion of a rule that represents the handling process
      */
    public HandlerRunner(CaseMonitor monitor, RdrConclusion rdrConc, RuleType xType) {
        super();
        _parentMonitor = monitor;
        _rdrConc = rdrConc;
        _reasonType = xType;
        _actionCount = _rdrConc.getCount();
        _isItemSuspended = false;
        _isCaseSuspended = false;
        _searchPair = rdrConc.getLastPair();
        _log = Logger.getLogger(this.getClass());
        initPersistedData();
    }

    /** This constructor is used when an exception is raised at the workitem level */
    public HandlerRunner(CaseMonitor monitor, WorkItemRecord wir, RdrConclusion rdrConc, RuleType xType) {
        this(monitor, rdrConc, xType);
        _wir = wir;
        _wirStr = wir.toXML();
    }

    /** This one's for persistence */
    private HandlerRunner() {
    }

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

    // GETTERS //

    /** @return the action for the current index from the RdrConclusion */
    public String getNextAction() {
        if (_actionCount < _actionIndex)
            return null;
        return _rdrConc.getAction(_actionIndex);
    }

    /** @return the target for the current index from the RdrConclusion */
    public String getNextTarget() {
        if (_actionCount < _actionIndex)
            return null;
        return _rdrConc.getTarget(_actionIndex);
    }

    /** @return the current index in the set of actions */
    public int getActionIndex() {
        return _actionIndex;
    }

    /** @return the id of the case that raised the exception */
    public String getCaseID() {
        return _parentMonitor.getCaseID();
    }

    /** @return the id of the spec of the case that raised the exception */
    public YSpecificationID getSpecID() {
        return _parentMonitor.getSpecID();
    }

    /** @return the CaseMonitor that is the container for this HandlerRunner */
    public CaseMonitor getOwnerCaseMonitor() {
        return _parentMonitor;
    }

    /** @return the list of currently suspended workitems for this runner */
    public List<WorkItemRecord> getSuspendedList() {
        return _suspendedItems;
    }

    /** @return the data params for the parent workitem/case */
    public Element getDatalist() {
        Element list = super.getDatalist();
        if (list == null)
            list = _parentMonitor.getCaseData();
        return list;
    }

    public Element getUpdatedData() {
        if (_wir != null)
            return _wir.getUpdatedData();
        return _parentMonitor.getCaseData();
    }

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

    // SETTERS //

    /** called when an action suspends the workitem of this HandlerRunner */
    public void setItemSuspended() {
        _isItemSuspended = true;
        persistThis();
    }

    /** called when an action unsuspends the workitem of this HandlerRunner */
    public void unsetItemSuspended() {
        _isItemSuspended = false;
        unsetSuspendedList();
    }

    /** called when an action suspends the case of this HandlerRunner */
    public void setCaseSuspended() {
        _isCaseSuspended = true;
        persistThis();
    }

    /** called when an action unsuspends the case of this HandlerRunner */
    public void unsetCaseSuspended() {
        _isCaseSuspended = false;
        unsetSuspendedList();
    }

    public void setOwnerCaseMonitor(CaseMonitor monitor) {
        _parentMonitor = monitor;
    }

    /** called when an action suspends the item or parent case of this HandlerRunner */
    public void setSuspendedList(List<WorkItemRecord> items) {
        _suspendedItems = items;
        _suspList = RdrConversionTools.WIRListToString(items);
        persistThis();
    }

    /** called when an action unsuspends the item or parent case of this HandlerRunner */
    public void unsetSuspendedList() {
        _suspendedItems = null;
        _suspList = null;
        persistThis();
    }

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

    // PERSISTENCE METHODS //

    private int get_actionIndex() {
        return _actionIndex;
    }

    private int get_actionCount() {
        return _actionCount;
    }

    private boolean get_isItemSuspended() {
        return _isItemSuspended;
    }

    private boolean get_isCaseSuspended() {
        return _isCaseSuspended;
    }

    private String get_rdrConcStr() {
        return _rdrConcStr;
    }

    private String get_caseID() {
        return _caseID;
    }

    private String get_suspList() {
        return _suspList;
    }

    public int get_id() {
        return _id;
    }

    private void set_actionIndex(int i) {
        _actionIndex = i;
    }

    private void set_actionCount(int i) {
        _actionCount = i;
    }

    private void set_isItemSuspended(boolean b) {
        _isItemSuspended = b;
    }

    private void set_isCaseSuspended(boolean b) {
        _isCaseSuspended = b;
    }

    private void set_rdrConcStr(String s) {
        _rdrConcStr = s;
    }

    private void set_caseID(String s) {
        _caseID = s;
    }

    private void set_suspList(String s) {
        _suspList = s;
    }

    public void set_id(int id) {
        _id = id;
    }

    /** Stringifies some data members for persistence purposes */
    private void initPersistedData() {
        _rdrConcStr = JDOMUtil.elementToStringDump(_rdrConc.toElement());
        _caseID = _parentMonitor.getCaseID();
        _id = this.hashCode();
    }

    /** re-converts stringified persisted data back to data members after restore */
    public void initNonPersistedItems() {
        _rdrConc = new RdrConclusion(JDOMUtil.stringToElement(_rdrConcStr));

        if (_wirStr != null) { // if item runner
            _wir = RdrConversionTools.xmlStringtoWIR(_wirStr);
            _datalist = _wir.getWorkItemData();
        }

        // reconstitute the susp items list
        if (_suspList != null) {
            _suspendedItems = RdrConversionTools.xmlToWIRList(_suspList);
        }
    }

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

    // MISC //

    public int incActionIndex() {
        ++_actionIndex;
        persistThis();
        return _actionIndex;
    }

    /** @return true if there is another action to run in the set */
    public boolean hasNextAction() {
        return (_actionIndex <= _actionCount);
    }

    public boolean isItemSuspended() {
        return _isItemSuspended;
    }

    public boolean isCaseSuspended() {
        return _isCaseSuspended;
    }

    public String toString() {
        StringBuilder s = new StringBuilder("HandlerRunner record:");
        s.append(Library.newline);
        s.append(super.toString());

        String conc = (_rdrConc == null) ? "null" : _rdrConc.toString();
        String parent = (_parentMonitor == null) ? "null"
                : _parentMonitor.getSpecID() + ": " + _parentMonitor.getCaseID();
        String index = String.valueOf(_actionIndex);
        String count = String.valueOf(_actionCount);
        String itemSusp = String.valueOf(_isItemSuspended);
        String caseSusp = String.valueOf(_isCaseSuspended);
        String wirs = "";
        if (_suspendedItems != null) {
            for (WorkItemRecord wir : _suspendedItems) {
                wirs += wir.toXML() + Library.newline;
            }
        }

        s = Library.appendLine(s, "RDRConclusion", conc);
        s = Library.appendLine(s, "Parent Monitor", parent);
        s = Library.appendLine(s, "Action Index", index);
        s = Library.appendLine(s, "Action Count", count);
        s = Library.appendLine(s, "Item Suspended?", itemSusp);
        s = Library.appendLine(s, "Case Suspended?", caseSusp);
        s = Library.appendLine(s, "Suspended Items", wirs);

        return s.toString();
    }

    /**
    * writes the node id's for the nodes returned from the rdr search
    * and the data for the current workitem, to a file for later
    * input into the 'add rule' process, if required
    */
    public void saveSearchResults() {

        // create the required components for the output file
        Document doc = new Document(new Element("searchResult"));
        Element eLastNode = new Element("lastNode");
        Element eSatisfied = new Element("satisfied");
        Element eTested = new Element("tested");
        Element eId = new Element("id");
        Element eSpecid = new Element("specid");
        Element eSpecVersion = new Element("specversion");
        Element eSpecURI = new Element("specuri");
        Element eTaskid = new Element("taskid");
        Element eCaseid = new Element("caseid");
        Element eCaseData = new Element("casedata");
        Element eReason = new Element("extype");
        Element eWorklets = new Element("worklets");

        try {
            // transfer the workitem's data items to the file
            for (Element e : getDatalist().getChildren()) {
                eCaseData.addContent(e.clone());
            }

            // set values for case identifiers
            eSpecid.setText(_parentMonitor.getSpecID().getIdentifier());
            eSpecVersion.setText(_parentMonitor.getSpecID().getVersionAsString());
            eSpecURI.setText(_parentMonitor.getSpecID().getUri());
            eCaseid.setText(_parentMonitor.getCaseID());

            if (_wir != null) {
                // set values for the workitem identifiers (item-level exception)
                eId.setText(_wir.getID());
                eTaskid.setText(Library.getTaskNameFromId(_wir.getTaskID()));
            }

            // add the worklet names and case ids
            for (String wName : _runners.getAllWorkletNames()) {
                Element eWorkletName = new Element("workletName");
                Element eRunningCaseId = new Element("runningcaseid");
                Element eWorklet = new Element("worklet");
                eWorkletName.setText(wName);
                eRunningCaseId.setText(_runners.getCaseID(wName));
                eWorklet.addContent(eWorkletName);
                eWorklet.addContent(eRunningCaseId);
                eWorklets.addContent(eWorklet);
            }

            eReason.setText(String.valueOf(_reasonType));

            // add the nodeids to the relevent elements
            eSatisfied.setText(_searchPair.getLastTrueNode().getNodeIdAsString());
            eTested.setText(_searchPair.getLastEvaluatedNode().getNodeIdAsString());
            eLastNode.addContent(eSatisfied);
            eLastNode.addContent(eTested);

            // add the elements to the document
            Element root = doc.getRootElement();
            root.addContent(eId);
            root.addContent(eSpecid);
            root.addContent(eSpecVersion);
            root.addContent(eSpecURI);
            root.addContent(eTaskid);
            root.addContent(eCaseid);
            root.addContent(eWorklets);
            root.addContent(eReason);
            root.addContent(eLastNode);
            root.addContent(eCaseData);

            // create the output file
            saveDocument(createFileName(), doc);
        } catch (IllegalAddException iae) {
            _log.error("Exception when adding content", iae);
        }
    }

} // end HandlerRunner class