org.yawlfoundation.yawl.scheduling.Case.java Source code

Java tutorial

Introduction

Here is the source code for org.yawlfoundation.yawl.scheduling.Case.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.scheduling;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jdom2.Document;
import org.jdom2.Element;
import org.yawlfoundation.yawl.scheduling.resource.ResourceServiceInterface;
import org.yawlfoundation.yawl.scheduling.util.Utils;
import org.yawlfoundation.yawl.scheduling.util.XMLUtils;
import org.yawlfoundation.yawl.util.JDOMUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Represents a YAWL case
 *
 * @author sga, jku
 */
public class Case {

    private static Logger _log = LogManager.getLogger(Case.class);

    private long id; // hibernate pkey

    protected String caseId;
    private List<Element> data = null;
    private Document rup;
    private String caseName;
    private String description;
    private long timestamp;
    private String savedBy;
    private String rupAsString; // for hibernate transport
    private boolean active;

    private Case() {
    } // for hibernate

    public Case(String id) {
        setCaseId(id);
    }

    public Case(String caseId, String caseName, String caseDescription, Document rup) {
        this(caseId);
        this.caseName = caseName;
        description = caseDescription;
        this.rup = rup;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getCaseId() {
        return caseId;
    }

    public void setCaseId(String id) {
        caseId = id;
    }

    public String getCaseName() {
        return caseName;
    }

    public void setCaseName(String name) {
        caseName = name;
    }

    public String getCaseDescription() {
        return description;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String desc) {
        description = desc;
    }

    public Document getRUP() {
        return rup;
    }

    public void setRUP(Document doc) {
        rup = doc;
    }

    public String getSavedBy() {
        return savedBy;
    }

    public void setSavedBy(String saver) {
        savedBy = saver;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public long getTimestamp() {
        if (timestamp == 0)
            timestamp = System.currentTimeMillis();
        return timestamp;
    }

    public void setTimestamp(long time) {
        timestamp = time;
    }

    public String getRupAsString() {
        if ((rupAsString == null) && (rup != null)) {
            rupAsString = JDOMUtil.documentToString(rup);
        }
        return rupAsString;
    }

    public void setRupAsString(String ras) {
        rupAsString = ras;
        if (ras != null) {
            rup = JDOMUtil.stringToDocument(ras);
        }
    }

    public List<Element> getData() {
        if (data == null) {
            data = new ArrayList<Element>();
            readCaseData();
        }
        return data;
    }

    /**
     * Reads case data recursively
     * <p>
     * The problem with case data is the hierarchical order of nets, which leads
     * to multiple sets of variables. For example, if we want to find a patient
     * caseName, we should look for it in the lowest net, since these are the newest
     * ones. If we cannot find a caseName, we can go ahead and look for it in the net
     * above and so on.
     */
    private void readCaseData() {
        String current, prev = "xx";
        current = caseId;
        while (!(current == null || current.equals(prev))) {
            try {
                data.add(Utils.string2Element(readCaseData(current)));
            } catch (IOException e) {
                _log.warn("Cannot get data for case: " + current + ", " + e.getMessage());
            }
            prev = current;
            current = getParentNetId(current);
        }
    }

    /**
     * Read case data from the YAWL work queue
     * 
     * @see Case#readCaseData()
     * @param caseId the case to get the data for
      * @return the net-level data for the case id
     * @throws IOException if the case data can't be retrieved from the engine
     */
    public String readCaseData(String caseId) throws IOException {
        String response = ResourceServiceInterface.getInstance().getCaseData(caseId);
        if (response.isEmpty() || response.startsWith("<failure")) {
            throw new IOException(response);
        }
        return response;
    }

    /**
     * Returns ID of parent net
     * <p>
     * If the Id passed as the argument is a root ID, it will be returned
     * unchanged.
     * 
     * @param id the id of a child net
     * @return the id of its parent
     */
    public String getParentNetId(String id) {
        int pos = id.lastIndexOf('.');
        return pos < 0 ? id : id.substring(0, pos);
    }

    /**
     * Gets the value for an XPath expression for an Element at a specified depth
      * in the case's data
     * 
     * @param depth the depth of the Element to use from the case data
     * @param xPath the XPath expression
     * @return the result of the XPath evaluation, or null if the depth exceeds the
      * depth of the case data's Elements, or if the XPath expression evaluates to null,
      * or if the Element result of the XPath expression contains no text
     */
    public String getText(int depth, String xPath) {
        if (depth < getData().size()) {
            try {
                Element depthElement = getData().get(depth).clone();
                _log.debug("Reading " + xPath + " from " + Utils.element2String(depthElement, true));
                Element xpathResult = XMLUtils.getElement(new Document().setRootElement(depthElement), xPath);
                if (xpathResult != null) {
                    return xpathResult.getText();
                }
            } catch (Exception e) {
                // fall through to return null
            }
        }
        return null;
    }

    /**
     * Traverses case data attempting to find an element that returns a non-null result
      * for an XPath expression
     * 
     * @param xPath the expression to evaluate
     * @return the text matching the XPath evaluation, or null if no match is found
     */
    public String getText(String xPath) {
        for (int i = (getData().size() - 1); i >= 0; i--) {
            String text = getText(i, xPath);
            if (text != null) {
                return text;
            }
        }
        return null;
    }
}