All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.clawiz.bpm.common.manager.ProcessManager Maven / Gradle / Ivy

/*
 *
 *  * MIT License
 *  *
 *  * Copyright (c) 2018 Clawiz
 *  *
 *  * Permission is hereby granted, free of charge, to any person obtaining a copy
 *  * of this software and associated documentation files (the "Software"), to deal
 *  * in the Software without restriction, including without limitation the rights
 *  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  * copies of the Software, and to permit persons to whom the Software is
 *  * furnished to do so, subject to the following conditions:
 *  *
 *  * The above copyright notice and this permission notice shall be included in all
 *  * copies or substantial portions of the Software.
 *  *
 *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  * SOFTWARE.
 *  *
 *
 */
/*
 *
 *  * MIT License
 *  *
 *  * Copyright (c) 2018 Clawiz
 *  *
 *  * Permission is hereby granted, free of charge, to any person obtaining a copy
 *  * of this software and associated documentation files (the "Software"), to deal
 *  * in the Software without restriction, including without limitation the rights
 *  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  * copies of the Software, and to permit persons to whom the Software is
 *  * furnished to do so, subject to the following conditions:
 *  *
 *  * The above copyright notice and this permission notice shall be included in all
 *  * copies or substantial portions of the Software.
 *  *
 *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  * SOFTWARE.
 *  *
 *
 */

package org.clawiz.bpm.common.manager;

import org.clawiz.bpm.common.metadata.data.process.Process;
import org.clawiz.bpm.common.metadata.data.process.flow.AbstractFlow;
import org.clawiz.bpm.common.metadata.data.process.node.AbstractProcessNode;
import org.clawiz.bpm.common.metadata.data.process.node.event.end.AbstractEndEvent;
import org.clawiz.bpm.common.helper.ProcessHelper;
import org.clawiz.bpm.common.manager.instance.AbstractProcessInstance;
import org.clawiz.bpm.common.manager.instance.ProcessInstanceList;
import org.clawiz.bpm.common.manager.instance.ProcessInstanceParameterList;
import org.clawiz.bpm.common.storage.process.ProcessService;
import org.clawiz.bpm.common.storage.processinstance.ProcessInstanceObject;
import org.clawiz.bpm.common.storage.processinstance.ProcessInstanceService;
import org.clawiz.core.common.system.database.Statement;
import org.clawiz.core.common.system.service.Service;

import java.math.BigDecimal;
import java.util.ArrayList;

public class ProcessManager extends Service {

    ProcessService         processService;
    ProcessInstanceService processInstanceService;
    ProcessHelper          processHelper;

    public void startProcess(AbstractProcessInstance instance) {

        instance.setSession(getSession());

        ProcessInstanceObject instanceObject = processInstanceService.create();

        instanceObject.setProcessId(instance.getProcess().getId());
        instanceObject.setObjectId(instance.getObjectId());
        instanceObject.setActive("T");

        instanceObject.save();
        instance.setId(instanceObject.getId());

        if ( instance.getNodes().size() > 0 ) {
            throwException("Process instance already active");
        }


        for (AbstractProcessNode node : instance.getProcess().getStartNodes() ) {
            executeUpdate("insert into cw_bpm_pinstance_nodes (instance_id, node_id) values (?, ?)", instanceObject.getId(), node.getId());
            instance.getNodes().add(node);
        }

        instance.clearCaches();
        executePossibleFlows(instance, 0);

    }

    public BigDecimal getObjectProcessInstanceId(BigDecimal objectId, BigDecimal processId) {
        Statement statement = executeQuery("select id from cw_bpm_process_instances where object_id = ? and process_id = ? and active=? ", objectId, processId, "T");
        BigDecimal instanceId = null;
        while (statement.next()) {
            if ( instanceId != null ) {
                throwException("Process ? has more then one active instance for object @ /?/", processService.getProcess(processId).getFullName(), objectId, objectId);
            }
            instanceId = statement.getBigDecimal(1);
        }
        statement.close();
        return instanceId;
    }


    public boolean isFlowAllowed(AbstractProcessInstance instance, AbstractFlow flow) {
        return instance.getService().isFlowAllowed(instance, flow);
    }

    public ArrayList getAllowedFlows(AbstractProcessInstance instance) {

        ArrayList result = new ArrayList<>();

        for ( AbstractProcessNode node : instance.getNodes() ) {
            for (AbstractFlow flow : node.getOutgoingFlows() ) {
                if ( isFlowAllowed(instance, flow)) {
                    result.add(flow);
                }
            }
        }

        return result;
    }


    public void executeFlow(BigDecimal objectId, String processName, String nodeName, String flowName) {

        BigDecimal processId = processService.fullNameToId(processName);
        if ( processId == null ) {
            throwException("Process '?' not registered in database", processName);
        }
        Process             process = processService.getProcess(processId);
        AbstractProcessNode node   = process.getNodes().get(nodeName);

        if ( node == null ) {
            throwException("Process ? does not contain node '?'", process.getFullName(), node.getName());
        }

        AbstractFlow flow = node.getOutgoingFlows().get(flowName);
        if ( flow == null ) {
            throwException("Process ? node ? does not contain flow '?'", process.getFullName(), node.getName(), flow.getName());
        }

        AbstractProcessInstance foundInstance = null;
        for (AbstractProcessInstance instance : getObjectInstanceList(objectId) ) {
            if ( instance.getProcess().getId().equals(processId) ) {
                if ( foundInstance != null ) {
                    throwException("Object @ /?/ has more than one active instance of process ?", objectId, objectId, process.getFullName());
                }
                foundInstance = instance;
            }
        }
        if (foundInstance == null) {
            throwException("Object @ /?/ has not active instances of process ?", objectId, objectId, process.getFullName());
        }
        executeFlow(foundInstance.getId(), flow);
    }

    public void executeFlow(BigDecimal instanceId, AbstractFlow flow) {
        executeFlow(getInstance(instanceId), flow);
    }

    private void executePossibleFlows(AbstractProcessInstance instance, int nestedLevel) {
        for ( AbstractProcessNode node: instance.getNodes()) {
            if ( ! node.isAutoOut() ) {
                continue;
            }
            for ( AbstractFlow flow : node.getOutgoingFlows() ) {
                if ( instance.getService().isFlowAllowed(instance, flow)) {
                    executeFlow(instance, flow, nestedLevel);
                }
            }
        }
    }

    public void executeFlow(AbstractProcessInstance instance, AbstractFlow flow) {
        executeFlow(instance, flow, 0);
    }

    private void executeFlow(AbstractProcessInstance instance, AbstractFlow flow, int nestedLevel) {

        synchronized (instance) {

//            processHelper.dump(instance);
//            logDebug("Process flow " + flow.getFullName());


            if ( ! instance.getService().isFlowAllowed(instance, flow) ) {
                throwException("Flow ? of process ? not allowed to run for object @ /?/", flow.getName(), instance.getProcess().getFullName(), instance.getObjectId(), instance.getObjectId());
            }

            instance.getNodes().add(flow.getTargetNode());
            instance.getNodes().remove(flow.getSourceNode());

            executeUpdate("delete from cw_bpm_pinstance_nodes where instance_id = ? and node_id = ?", instance.getId(), flow.getSourceNode().getId());
            executeUpdate("insert into cw_bpm_pinstance_nodes (instance_id, node_id) values (?, ?)", instance.getId(), flow.getTargetNode().getId());

            instance.getService().processNode(instance, flow.getTargetNode());
            instance.getObject().save();

            executePossibleFlows(instance, nestedLevel+1);

            instance.clearCaches();

            if (AbstractEndEvent.class.isAssignableFrom(flow.getTargetNode().getClass())) {
                stopProcess(instance);
            }

        }

    }


    protected void stopProcess(AbstractProcessInstance instance) {

        ProcessInstanceObject instanceObject = processInstanceService.load(instance.getId());
        instanceObject.setActive("F");
        instanceObject.save();

/*
        Statement statement = executeQuery("select source_instance_id from cw_bpm_process_calls where called_instance_id = ?", instance.getId());
        while ( statement.next() ) {
            BigDecimal sourceId = statement.getBigDecimal(1);
            Statement check = executeQuery("select c.called_instance_id\n" +
                    " from cw_bpm_process_calls c\n" +
                    " left join cw_bpm_process_instances i on i.id = c.source_instance_id\n" +
                    " where c.source_instance_id  = ?\n" +
                    "  and  c.called_instance_id != ? \n" +
                    "  and  i.active = ?"
                    , sourceId, instance.getId(), "W");
            if ( ! check.next() ) {
                ProcessInstanceObject sourceInstanceObject = processInstanceService.load(sourceId);
                sourceInstanceObject.setActive("T");
                sourceInstanceObject.save();
                executePossibleFlows(loadInstance(sourceId), 0);
            }

            executeUpdate("delete from cw_bpm_process_calls where source_instance_id = ? and called_instance_id = ?"
                    , sourceId,  instance.getId());
        }
*/

    }

    public void callNestedProcess(AbstractProcessInstance sourceInstance, String processName) {
        ProcessInstanceObject sourceInstanceObject = processInstanceService.load(sourceInstance.getId());
        sourceInstanceObject.setActive("W");
        sourceInstanceObject.save();

        Process                 process  = processService.getProcess(processService.fullNameToId(processName));
        AbstractProcessInstance instance = null;
        try {
            instance = process.getInstanceClass().newInstance();
        } catch (Exception e) {
            throwException("Exception on create process '?' instance ? : ?", process.getFullName(), process.getInstanceClass().getName(), e.getMessage(), e);
        }

        instance.setProcess(process);
        instance.setSession(getSession());
        instance.setObjectId(sourceInstance.getObjectId());

        startProcess(instance);

        executeUpdate("insert into cw_bpm_process_calls (source_instance_id, called_instance_id) values (?,?)"
                , sourceInstance.getId(),  instance.getId());

    }

    public AbstractProcessInstance loadInstance(BigDecimal id) {
        AbstractProcessInstance instance = null;

        Statement statement  = executeQuery("select process_id, object_id from cw_bpm_process_instances where id = ?", id);
        if ( ! statement.next() ) {
            throwException("Process instance with id ? not found", id);
        }
        Process process = processService.getProcess(statement.getBigDecimal(1));

        try {
            instance = process.getInstanceClass().newInstance();
            instance.setSession(getSession());
        } catch (Exception e) {
            throwException("Exception on create process ? instance ? : ?", process.getFullName(), process.getInstanceClass().getName(), e.getMessage(), e);
        }
        instance.setId(id);
        instance.setProcess(process);
        instance.setObjectId(statement.getBigDecimal(2));

        statement.close();

        ProcessInstanceParameterList parameters = new ProcessInstanceParameterList();

        statement  = executeQuery("select name, number_value from cw_bpm_pinstance_parameters where instance_id = ?", id);
        while ( statement.next() ) {
            parameters.setBigDecimal(statement.getString(1), statement.getBigDecimal(2));
        }
        statement.close();
        instance.fromParameterList(parameters);

        statement = executeQuery("select node_id from cw_bpm_pinstance_nodes where instance_id = ?", id);
        while ( statement.next() ) {
            AbstractProcessNode node = process.getNodes().get(statement.getBigDecimal(1));
            if ( node == null ) {
                throwException("Node @ (?) not exists in process ? states", statement.getBigDecimal(1), statement.getBigDecimal(1), process.getFullName());
            }
            instance.getNodes().add(node);
        }
        statement.close();

        return instance;
    }

    public AbstractProcessInstance getInstance(BigDecimal id) {
        if ( id == null ) {
            throwException("Instance id cannot be null");
        }

        return loadInstance(id);
    }


    public ProcessInstanceList loadObjectInstanceList(BigDecimal objectId) {
        ProcessInstanceList result = new ProcessInstanceList();
        Statement statement = executeQuery("select id from cw_bpm_process_instances where object_id = ? and active=?", objectId, "T");
        while ( statement.next() ) {
            result.add(getInstance(statement.getBigDecimal(1)));
        }
        return result;
    }

    public ProcessInstanceList getObjectInstanceList(BigDecimal objectId) {

        if ( objectId == null ) {
            return null;
        }

        try {
            return loadObjectInstanceList(objectId);
        } catch (Exception e) {
            throwException("Exception on get object ? instances : ?", objectId, e.getMessage(), e);
            e.printStackTrace();
        }

        return null;
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy