org.efaps.bpm.BPM.java Source code

Java tutorial

Introduction

Here is the source code for org.efaps.bpm.BPM.java

Source

/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * 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.efaps.bpm;

import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.transaction.UserTransaction;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.drools.persistence.jta.JtaTransactionManager;
import org.efaps.admin.EFapsSystemConfiguration;
import org.efaps.admin.KernelSettings;
import org.efaps.admin.common.SystemConfiguration;
import org.efaps.admin.dbproperty.DBProperties;
import org.efaps.admin.event.Parameter;
import org.efaps.admin.event.Parameter.ParameterValues;
import org.efaps.admin.event.Return;
import org.efaps.admin.event.Return.ReturnValues;
import org.efaps.admin.program.esjp.EFapsClassLoader;
import org.efaps.admin.user.AbstractUserObject;
import org.efaps.admin.user.Role;
import org.efaps.bpm.compiler.KnowledgeBuilderFactoryServiceImpl;
import org.efaps.bpm.identity.EntityMapper;
import org.efaps.bpm.identity.UserGroupCallbackImpl;
import org.efaps.bpm.listener.AsyncCalls;
import org.efaps.bpm.listener.IAsyncListener;
import org.efaps.bpm.listener.WorkingMemoryLogListener;
import org.efaps.bpm.process.ProcessAdmin;
import org.efaps.bpm.runtime.ManagerFactoryImpl;
import org.efaps.bpm.runtime.RegisterableItemsFactoryImpl;
import org.efaps.bpm.task.TaskAdminstration;
import org.efaps.bpm.transaction.ConnectionProvider;
import org.efaps.bpm.transaction.TransactionHelper;
import org.efaps.bpm.workitem.ManualTaskItemHandler;
import org.efaps.ci.CIAdminProgram;
import org.efaps.db.Checkout;
import org.efaps.db.Context;
import org.efaps.db.InstanceQuery;
import org.efaps.db.QueryBuilder;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.CacheReloadException;
import org.hibernate.cfg.AvailableSettings;
import org.jbpm.process.audit.JPAAuditLogService;
import org.jbpm.runtime.manager.impl.PerProcessInstanceRuntimeManager;
import org.jbpm.runtime.manager.impl.RuntimeEnvironmentBuilder;
import org.jbpm.services.task.impl.model.I18NTextImpl;
import org.jbpm.services.task.utils.ContentMarshallerHelper;
import org.jbpm.workflow.instance.WorkflowProcessInstance;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.manager.RuntimeEngine;
import org.kie.api.runtime.manager.RuntimeManager;
import org.kie.api.runtime.process.NodeInstance;
import org.kie.api.runtime.process.ProcessInstance;
import org.kie.api.task.TaskService;
import org.kie.api.task.model.Content;
import org.kie.api.task.model.I18NText;
import org.kie.api.task.model.OrganizationalEntity;
import org.kie.api.task.model.Status;
import org.kie.api.task.model.Task;
import org.kie.api.task.model.TaskSummary;
import org.kie.internal.builder.KnowledgeBuilderFactoryService;
import org.kie.internal.io.ResourceFactory;
import org.kie.internal.runtime.manager.Mapper;
import org.kie.internal.runtime.manager.RuntimeEnvironment;
import org.kie.internal.runtime.manager.context.CorrelationKeyContext;
import org.kie.internal.runtime.manager.context.EmptyContext;
import org.kie.internal.runtime.manager.context.ProcessInstanceIdContext;
import org.kie.internal.task.api.InternalTaskService;
import org.kie.internal.task.api.model.InternalTask;
import org.kie.internal.utils.ServiceRegistryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public final class BPM {
    /**
     * Parameter key to be used to pass to the process.
     */
    public static final String OUTPARAMETER4TASKDECISION = "eFapsDecision";

    /**
     * Parameter key to be used to pass delegates to an Human Task.
     */
    public static final String INPUTPARAMETER4DELEGATE = "DelegateIds";

    /**
     * Logging instance used in this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(BPM.class);

    /**
     * SingletonRuntimeManager.
     */
    private static RuntimeManager SMANAGER;

    /**
     * PerProcessInstanceRuntimeManager.
     */
    private static RuntimeManager PMANAGER;

    /**
     * Create Singelton.
     */
    private BPM() {
    }

    /**
     * Initialize BPM.
     *
     * @throws EFapsException on error
     */
    public static void initialize() throws EFapsException {
        final SystemConfiguration config = EFapsSystemConfiguration.get();
        final boolean active = config != null ? config.getAttributeValueAsBoolean(KernelSettings.ACTIVATE_BPM)
                : false;
        if (active) {

            if (BPM.PMANAGER != null) {
                BPM.PMANAGER.close();
                BPM.PMANAGER = null;
            }
            if (BPM.SMANAGER != null) {
                BPM.SMANAGER.close();
                BPM.SMANAGER = null;
            }

            UserTransaction userTrans = null;
            InitialContext context = null;
            try {
                context = new InitialContext();
                userTrans = TransactionHelper.findUserTransaction();
                Object object = null;
                try {
                    object = context.lookup(JtaTransactionManager.DEFAULT_USER_TRANSACTION_NAME);
                } catch (final NamingException ex) {
                    BPM.LOG.info("Checked for JtaTransactionManager");
                }
                if (object == null) {
                    context.bind(JtaTransactionManager.DEFAULT_USER_TRANSACTION_NAME, userTrans);
                    context.bind(JtaTransactionManager.FALLBACK_TRANSACTION_MANAGER_NAMES[0],
                            TransactionHelper.findTransactionManager());
                }
            } catch (final NamingException ex) {
                BPM.LOG.error("Could not initialise JNDI InitialContext", ex);
            }

            // register our own KnowledgeBuilderFactoryService
            ServiceRegistryImpl.getInstance().addDefault(KnowledgeBuilderFactoryService.class,
                    KnowledgeBuilderFactoryServiceImpl.class.getName());

            final RegisterableItemsFactoryImpl itemsFactory = new RegisterableItemsFactoryImpl();
            itemsFactory.addWorkItemHandler("Manual Task", ManualTaskItemHandler.class);
            itemsFactory.addProcessListener(WorkingMemoryLogListener.class);

            final Map<String, String> properties = new HashMap<String, String>();
            properties.put(AvailableSettings.DIALECT, Context.getDbType().getHibernateDialect());
            properties.put(AvailableSettings.SHOW_SQL, String.valueOf(BPM.LOG.isDebugEnabled()));
            properties.put(AvailableSettings.FORMAT_SQL, "true");
            properties.put(AvailableSettings.RELEASE_CONNECTIONS, "after_transaction");
            properties.put(AvailableSettings.CONNECTION_PROVIDER, ConnectionProvider.class.getName());
            properties.put(org.hibernate.jpa.AvailableSettings.NAMING_STRATEGY, NamingStrategy.class.getName());

            final EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.jbpm.persistence.jpa",
                    properties);

            final RuntimeEnvironmentBuilder builder = RuntimeEnvironmentBuilder.getDefault()
                    .classLoader(EFapsClassLoader.getInstance()).userGroupCallback(new UserGroupCallbackImpl())
                    .entityManagerFactory(emf).registerableItemsFactory(itemsFactory).persistence(true)
                    .addEnvironmentEntry("TRANSACTION_LOCK_ENABLED", "false");

            BPM.add2EnvironmentBuilder(builder);

            final RuntimeEnvironment environment = builder.get();
            final ManagerFactoryImpl factory = new ManagerFactoryImpl();

            BPM.PMANAGER = factory.newPerProcessInstanceRuntimeManager(environment);
            BPM.SMANAGER = factory.newSingletonRuntimeManager(environment);
        }
    }

    /**
     * @param _envBuilder RuntimeEnvironmentBuilder
     * @throws EFapsException on error
     */
    private static void add2EnvironmentBuilder(final RuntimeEnvironmentBuilder _envBuilder) throws EFapsException {
        final QueryBuilder queryBldr = new QueryBuilder(CIAdminProgram.BPM);
        final InstanceQuery query = queryBldr.getQuery();
        query.executeWithoutAccessCheck();
        while (query.next()) {
            final Checkout checkout = new Checkout(query.getCurrentValue());
            final InputStream in = checkout.execute();
            _envBuilder.addAsset(ResourceFactory.newInputStreamResource(in), ResourceType.BPMN2);
        }
    }

    /**
     * @param _processId    id of the process to start
     * @param _params       parameter map for the task
     * @return the <code>ProcessInstance</code> that represents the instance of the process that was started
     */
    public static ProcessInstance startProcess(final String _processId, final Map<String, Object> _params) {
        final RuntimeEngine runtimeEngine = BPM.PMANAGER.getRuntimeEngine(CorrelationKeyContext.get());
        final KieSession ksession = runtimeEngine.getKieSession();
        return ksession.startProcess(_processId, _params);
    }

    /**
     * Returns all node instances that are currently active within this container.
     * @param _processInstanceId if of a process Instance
     * @return the list of node instances currently active, empty list if none found
     */
    public static Collection<NodeInstance> getActiveNodes4ProcessId(final long _processInstanceId) {
        ProcessInstance processInstance = null;
        if (BPM.processIsActiv(_processInstanceId)) {
            final RuntimeEngine runtimeEngine = BPM.PMANAGER
                    .getRuntimeEngine(ProcessInstanceIdContext.get(_processInstanceId));
            final KieSession ksession = runtimeEngine.getKieSession();
            processInstance = ksession.getProcessInstance(_processInstanceId);
        }
        return processInstance == null ? Collections.<NodeInstance>emptyList()
                : ((WorkflowProcessInstance) processInstance).getNodeInstances();
    }

    /**
     * Check for the PerProcessInstanceRuntimeManager if the process for the
     * given processInstanceId is still active.
     *
     * @param _processInstanceId processInstanceId to be checked if still activ
     * @return true if activ, else fasle
     */
    public static boolean processIsActiv(final long _processInstanceId) {
        final ProcessInstanceIdContext context = ProcessInstanceIdContext.get(_processInstanceId);
        final Mapper mapper = ((PerProcessInstanceRuntimeManager) BPM.PMANAGER).getMapper();
        return mapper.findMapping(context, null) != null;
    }

    /**
     * @param _processInstanceId id of the processinstanc to be aborted
     */
    public static void abortProcessInstance(final long _processInstanceId) {
        final RuntimeEngine runtimeEngine = BPM.PMANAGER
                .getRuntimeEngine(ProcessInstanceIdContext.get(_processInstanceId));
        runtimeEngine.getKieSession().abortProcessInstance(_processInstanceId);
    }

    /**
     * When the task has a single potential owner, it transitions into the
     * Reserved state, indicating that it is assigned to a single actual owner.
     * Otherwise (i.e., when it has multiple potential owners or is assigned to
     * a work queue), it transitions into the Ready state, indicating that it
     * can be claimed by one of its potential owners. Once a potential owner
     * claims the task, it transitions into the Reserved state, making that
     * potential owner the actual owner.
     *
     * @param _taskSummary task to be claimed
     * @throws EFapsException on error
     */
    public static void claimTask(final TaskSummary _taskSummary) throws EFapsException {
        final RuntimeEngine runtimeEngine = BPM.PMANAGER
                .getRuntimeEngine(ProcessInstanceIdContext.get(_taskSummary.getProcessInstanceId()));
        final TaskService taskService = runtimeEngine.getTaskService();
        // check if must be claimed still
        if (Status.Ready.equals(_taskSummary.getStatus())) {
            taskService.claim(_taskSummary.getId(),
                    EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID()));
        }
    }

    /**
     * Tasks potential owners, actual owner or business administrator can
     * forward an active task to another person or a set of people, replacing
     * himself by those people in the list of potential owners. Potential owners
     * can only forward tasks that are in the Ready state. Forwarding is
     * possible if the task has a set of individually assigned potential owners,
     * not if its potential owners are assigned using one or many groups. If the
     * task is in the Reserved or InProgress state then the task is implicitly
     * released first, that is, the task is transitioned into the Ready state.
     * Business data associated with the task is kept. The user performing the
     * forward is removed from the set of potential owners of the task, and the
     * forwardee is added to the set of potential owners.
     *
     * @param _taskSummary task to be claimed
     * @param _targetEntityId target entity
     * @throws EFapsException on error
     */
    public static void forwardTask(final TaskSummary _taskSummary, final String _targetEntityId)
            throws EFapsException {
        final RuntimeEngine runtimeEngine = BPM.PMANAGER
                .getRuntimeEngine(ProcessInstanceIdContext.get(_taskSummary.getProcessInstanceId()));
        final TaskService taskService = runtimeEngine.getTaskService();
        taskService.forward(_taskSummary.getId(),
                EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID()),
                EntityMapper.getEntityId(_targetEntityId));
    }

    /**
     * Tasks potential owners, actual owner or business administrator can
     * delegate a task to another user, making that user the actual owner of the
     * task, and also adding her to the list of potential owners in case she is
     * not, yet. A task can be delegated when it is in an active state (Ready,
     * Reserved, InProgress), and transitions the task into the Reserved state.
     * Business data associated with the task is kept.
     *
     * @param _taskSummary  TaskSummary
     * @param _targetEntityId   target entity
     * @throws EFapsException on error
     */
    public static void delegateTask(final TaskSummary _taskSummary, final String _targetEntityId)
            throws EFapsException {
        final RuntimeEngine runtimeEngine = BPM.PMANAGER
                .getRuntimeEngine(ProcessInstanceIdContext.get(_taskSummary.getProcessInstanceId()));
        final TaskService taskService = runtimeEngine.getTaskService();
        taskService.delegate(_taskSummary.getId(),
                EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID()),
                EntityMapper.getEntityId(_targetEntityId));
    }

    /**
     * @param _taskSummary taskSummary the Delegate Roles are wanted for.
     * @return List of Roles
     * @throws CacheReloadException on error
     */
    public static List<Role> getDelegates4Task(final TaskSummary _taskSummary) throws CacheReloadException {
        final List<Role> ret = new ArrayList<Role>();
        final Object values = BPM.getTaskData(_taskSummary);
        if (values instanceof Map) {
            final String delegatesStr = (String) ((Map<?, ?>) values).get(BPM.INPUTPARAMETER4DELEGATE);
            if (delegatesStr != null && !delegatesStr.isEmpty()) {
                final String[] delegates = delegatesStr.split(";");
                for (final String delegate : delegates) {
                    final Role role = Role.get(UUID.fromString(delegate));
                    if (role != null) {
                        ret.add(role);
                    }
                }
            }
        }
        return ret;
    }

    /**
     * @param _taskSummary task to be delgate
     * @param _targetUserId userid of the user the task will be delegated to
     * @throws EFapsException on error
     */
    public static void delegateTask4Role(final TaskSummary _taskSummary, final String _targetUserId)
            throws EFapsException {
        final RuntimeEngine runtimeEngine = BPM.PMANAGER.getRuntimeEngine(CorrelationKeyContext.get());
        final TaskService taskService = runtimeEngine.getTaskService();
        // runtimeEngine.getKieSession().execute(new GenericCommand(){})
        // check if must be claimed still
        if (Status.Ready.equals(_taskSummary.getStatus())) {
            boolean add = true;
            final Task task = taskService.getTaskById(_taskSummary.getId());
            final List<OrganizationalEntity> owners = task.getPeopleAssignments().getPotentialOwners();
            for (final OrganizationalEntity org : owners) {
                if (_targetUserId.equals(org.getId())) {
                    add = false;
                }
            }
            if (add) {
                final boolean isRole = Role.get(UUID.fromString(_targetUserId)) != null;
                if (isRole) {
                    //  final List<OperationCommand> commands = taskService.getCommandsForOperation(Operation.Delegate);
                    //                    for (final OperationCommand cmd : commands) {
                    //                        cmd.setExec(Operation.Delegate);
                    //                    }
                }

                taskService.delegate(_taskSummary.getId(),
                        EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID()), _targetUserId);

                final List<I18NText> descr = task.getDescriptions();
                final String txt = DBProperties.getFormatedDBProperty("org.efaps.bpm.BPM.delegateText",
                        new Object[] { Context.getThreadContext().getPerson().getName(),
                                AbstractUserObject.getUserObject(UUID.fromString(_targetUserId)).getName() });
                if (descr.isEmpty()) {
                    final I18NTextImpl i18n = new I18NTextImpl();
                    i18n.setText(txt);
                    i18n.setLanguage("en-UK");
                    descr.add(i18n);
                } else {
                    final String oldTxt = descr.get(0).getText();
                    if (!oldTxt.contains(txt)) {
                        ((I18NTextImpl) descr.get(0)).setText(descr.get(0).getText() + " - " + txt);
                    }
                }

                if (isRole) {
                    //                    final List<OperationCommand> commands = taskService.getCommandsForOperation(Operation.Delegate);
                    //                    for (final OperationCommand cmd : commands) {
                    //                        cmd.setExec(Operation.Claim);
                    //                    }
                }
            }
        }
    }

    /**
     * The current actual owner of a human task may release a task to again make
     * it available for all potential owners. A task can be released from active
     * states that have an actual owner (Reserved, InProgress), transitioning it
     * into the Ready state. Business data associated with the task
     * (intermediate result data, ad-hoc attachments and comments) is kept. A
     * task that is currently InProgress can be stopped by the actual owner,
     * transitioning it into state Reserved. Business data associated with the
     * task as well as its actual owner is kept.
     *
     * @param _taskSummary task to be claimed
     * @throws EFapsException on error
     */
    public static void releaseTask(final TaskSummary _taskSummary) throws EFapsException {
        final RuntimeEngine runtimeEngine = BPM.PMANAGER
                .getRuntimeEngine(ProcessInstanceIdContext.get(_taskSummary.getProcessInstanceId()));
        final TaskService taskService = runtimeEngine.getTaskService();
        // check if must be claimed still
        if (Status.Reserved.equals(_taskSummary.getStatus())) {
            taskService.release(_taskSummary.getId(),
                    EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID()));
        }
    }

    /**
     * Stop a task that is in process.
     *
     * @param _taskSummary task to be claimed
     * @throws EFapsException on error
     */
    public static void stopTask(final TaskSummary _taskSummary) throws EFapsException {
        final RuntimeEngine runtimeEngine = BPM.PMANAGER
                .getRuntimeEngine(ProcessInstanceIdContext.get(_taskSummary.getProcessInstanceId()));
        final TaskService taskService = runtimeEngine.getTaskService();
        taskService.stop(_taskSummary.getId(),
                EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID()));
    }

    /**
     * Stop a task that is in process.
     *
     * @param _taskSummary task to be claimed
     * @throws EFapsException on error
     */
    public static void exitTask(final TaskSummary _taskSummary) throws EFapsException {
        final RuntimeEngine runtimeEngine = BPM.PMANAGER
                .getRuntimeEngine(ProcessInstanceIdContext.get(_taskSummary.getProcessInstanceId()));
        final TaskService taskService = runtimeEngine.getTaskService();
        taskService.exit(_taskSummary.getId(),
                EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID()));
    }

    /**
     * @param _taskSummary TaskSummary
     * @param _decision one of true, false, null
     * @param _values mapping of additional values
     * @throws EFapsException on error
     */
    public static void executeTask(final TaskSummary _taskSummary, final Boolean _decision,
            final Map<String, Object> _values) throws EFapsException {
        final RuntimeEngine runtimeEngine = BPM.PMANAGER
                .getRuntimeEngine(ProcessInstanceIdContext.get(_taskSummary.getProcessInstanceId()));
        final TaskService taskService = runtimeEngine.getTaskService();

        // check if must be claimed still
        if (Status.Ready.equals(_taskSummary.getStatus())) {
            taskService.claim(_taskSummary.getId(),
                    EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID()));
        }
        if (Status.InProgress.equals(_taskSummary.getStatus())) {
            taskService.resume(_taskSummary.getId(),
                    EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID()));
        } else {
            taskService.start(_taskSummary.getId(),
                    EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID()));
        }

        final Parameter parameter = new Parameter();
        parameter.put(ParameterValues.BPM_TASK, _taskSummary);
        parameter.put(ParameterValues.BPM_VALUES, _values);
        parameter.put(ParameterValues.BPM_DECISION, _decision);
        final Map<String, Object> results = new HashMap<String, Object>();
        if (_values != null) {
            results.putAll(_values);
        }
        // exec esjp
        try {
            final Class<?> transformer = Class.forName("org.efaps.esjp.bpm.TaskTransformer", true,
                    EFapsClassLoader.getInstance());
            final Method method = transformer.getMethod("execute", new Class[] { Parameter.class });
            final Return ret = (Return) method.invoke(transformer.newInstance(), parameter);
            if (ret != null) {
                results.put(BPM.OUTPARAMETER4TASKDECISION, ret.get(ReturnValues.VALUES));
            }
        } catch (final ClassNotFoundException e) {
            BPM.LOG.error("Class could not be found.", e);
        } catch (final InstantiationException e) {
            BPM.LOG.error("Class could not be instantiation.", e);
        } catch (final IllegalAccessException e) {
            BPM.LOG.error("Class could not be accessed.", e);
        } catch (final IllegalArgumentException e) {
            BPM.LOG.error("Illegal Argument.", e);
        } catch (final InvocationTargetException e) {
            BPM.LOG.error("Invocation Target.", e);
        } catch (final SecurityException e) {
            BPM.LOG.error("Class could not be found.", e);
        } catch (final NoSuchMethodException e) {
            BPM.LOG.error("Class could not be found.", e);
        }
        taskService.complete(_taskSummary.getId(),
                EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID()), results);

        BPM.invokeAsyncListeners(AsyncCalls.AFTER_EXECUTE, _taskSummary, results);
    }

    /**
     * @param _taskSummary tasksummary the data is wanted for
     * @return the object data
     */
    public static Object getTaskData(final TaskSummary _taskSummary) {
        Object ret = null;
        final RuntimeEngine runtimeEngine = BPM.PMANAGER
                .getRuntimeEngine(ProcessInstanceIdContext.get(_taskSummary.getProcessInstanceId()));
        final TaskService taskService = runtimeEngine.getTaskService();
        final Task task = taskService.getTaskById(_taskSummary.getId());
        final long contentId = task.getTaskData().getDocumentContentId();
        if (contentId != -1) {
            final Content content = taskService.getContentById(contentId);
            ret = ContentMarshallerHelper.unmarshall(content.getContent(),
                    runtimeEngine.getKieSession().getEnvironment(), BPM.class.getClassLoader());
        }
        return ret;
    }

    /**
     * @return list of assigned tasks
     */
    public static List<TaskSummary> getTasksAssignedAsPotentialOwner() {
        final List<TaskSummary> ret = new ArrayList<TaskSummary>();
        final RuntimeEngine runtimeEngine = BPM.SMANAGER.getRuntimeEngine(EmptyContext.get());
        final TaskService taskService = runtimeEngine.getTaskService();
        try {
            if (Context.getThreadContext().getPerson().getUUID() == null) {
                BPM.LOG.error("User '{}' has no UUID assigned.", Context.getThreadContext().getPerson().getName());
            } else {
                final String persId = EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID());
                // final String language = Context.getThreadContext().getLanguage();
                ret.addAll(taskService.getTasksAssignedAsPotentialOwner(persId, "en-UK"));
            }
        } catch (final EFapsException e) {
            BPM.LOG.error("Error on retrieving List of TaskSummaries.");
        }
        return ret;
    }

    /**
     * @return list of assigned tasks
     */
    public static List<TaskSummary> getTasksOwned() {
        final List<TaskSummary> ret = new ArrayList<TaskSummary>();
        final RuntimeEngine runtimeEngine = BPM.SMANAGER.getRuntimeEngine(EmptyContext.get());
        final TaskService taskService = runtimeEngine.getTaskService();
        try {
            if (Context.getThreadContext().getPerson().getUUID() == null) {
                BPM.LOG.error("User '{}' has no UUID assigned.", Context.getThreadContext().getPerson().getName());
            } else {
                final String persId = EntityMapper.getUserId(Context.getThreadContext().getPerson().getUUID());
                // final String language = Context.getThreadContext().getLanguage();
                final List<Status> status = new ArrayList<Status>();
                status.add(Status.InProgress);
                status.add(Status.Reserved);
                status.add(Status.Suspended);
                ret.addAll(taskService.getTasksOwnedByStatus(persId, status, "en-UK"));
            }
        } catch (final EFapsException e) {
            BPM.LOG.error("Error on retrieving List of TaskSummaries.");
        }
        return ret;
    }

    /**
     * @param _processInstanceId ProcessInstance the task are wanted for
     * @param _status status
     * @return list of tasks
     */
    public static List<TaskSummary> getTasksByStatusByProcessId(final long _processInstanceId,
            final List<Status> _status) {
        final List<TaskSummary> ret = new ArrayList<TaskSummary>();
        if (BPM.processIsActiv(_processInstanceId)) {
            final RuntimeEngine runtimeEngine = BPM.PMANAGER
                    .getRuntimeEngine(ProcessInstanceIdContext.get(_processInstanceId));
            final TaskService taskService = runtimeEngine.getTaskService();

            ret.addAll(taskService.getTasksByStatusByProcessInstanceId(_processInstanceId, _status, "en-UK"));
        }
        return ret;
    }

    /**
     * @param _processInstanceId ProcessInstance the task are wanted for
     * @param _status status
     * @param _taskName name of the task wanted
     * @return list of tasks
     */
    public static List<TaskSummary> getTasksByStatusByProcessInstanceIdByTaskName(final long _processInstanceId,
            final List<Status> _status, final String _taskName) {
        final List<TaskSummary> ret = new ArrayList<TaskSummary>();
        if (BPM.processIsActiv(_processInstanceId)) {
            final RuntimeEngine runtimeEngine = BPM.PMANAGER
                    .getRuntimeEngine(ProcessInstanceIdContext.get(_processInstanceId));
            final InternalTaskService taskService = (InternalTaskService) runtimeEngine.getTaskService();
            ret.addAll(taskService.getTasksByStatusByProcessInstanceIdByTaskName(_processInstanceId, _status,
                    _taskName));
        }
        return ret;
    }

    /**
     * @param _taskSummary summary the task is wanted for
     * @return internal task object
     */
    public static InternalTask getTaskById(final TaskSummary _taskSummary) {
        final RuntimeEngine runtimeEngine = BPM.PMANAGER
                .getRuntimeEngine(ProcessInstanceIdContext.get(_taskSummary.getProcessInstanceId()));
        final TaskService taskService = runtimeEngine.getTaskService();
        return (InternalTask) taskService.getTaskById(_taskSummary.getId());
    }

    /**
     * @return the TaskAdmin
     */
    public static TaskAdminstration getTaskAdmin() {
        final RuntimeEngine runtimeEngine = BPM.SMANAGER.getRuntimeEngine(EmptyContext.get());
        final TaskService taskService = runtimeEngine.getTaskService();
        return new TaskAdminstration((InternalTaskService) taskService);
    }

    /**
     * @return the TaskAdmin
     */
    public static ProcessAdmin getProcessAdmin() {
        final RuntimeEngine runtimeEngine = BPM.SMANAGER.getRuntimeEngine(EmptyContext.get());
        return new ProcessAdmin(new JPAAuditLogService(runtimeEngine.getKieSession().getEnvironment()));
    }

    /**
     * Invoke the listener.
     * @param _call call to be executed
     * @param _taskSummary  tasksummary of the task involved
     * @param _values values form eFaps
     */
    private static void invokeAsyncListeners(final AsyncCalls _call, final TaskSummary _taskSummary,
            final Map<String, Object> _values) {
        // exec esjp
        try {
            final Class<?> listenerClass = Class.forName("org.efaps.esjp.bpm.listener.ReviewListener", true,
                    EFapsClassLoader.getInstance());
            final IAsyncListener listener = (IAsyncListener) listenerClass.newInstance();

            final Object taskData = BPM.getTaskData(_taskSummary);

            final String userName = Context.getThreadContext().getPerson().getName();
            final ListenerThread threat = new ListenerThread(userName, listener, _call, _values, taskData);

            final BasicThreadFactory factory = new BasicThreadFactory.Builder()
                    .namingPattern("eFapsBPMListenerThreat-%d").priority(Thread.MIN_PRIORITY).build();
            final ExecutorService exec = Executors.newSingleThreadExecutor(factory);
            exec.submit(threat);
            exec.shutdown();

        } catch (final ClassNotFoundException e) {
            BPM.LOG.error("Class could not be found.", e);
        } catch (final InstantiationException e) {
            BPM.LOG.error("Class could not be instantiation.", e);
        } catch (final IllegalAccessException e) {
            BPM.LOG.error("Class could not be accessed.", e);
        } catch (final IllegalArgumentException e) {
            BPM.LOG.error("Illegal Argument.", e);
        } catch (final SecurityException e) {
            BPM.LOG.error("Class could not be found.", e);
        } catch (final EFapsException e) {
            BPM.LOG.error("EFapsException catched", e);
        }
    }

    /**
     * Threat to execute the listeners.
     */
    private static class ListenerThread implements Runnable {

        /**
         * Listener to be executed.
         */
        private final IAsyncListener listener;

        /**
         * Call to be executed on the listener.
         */
        private final AsyncCalls call;

        /**
         * value mapping.
         */
        private final Map<String, Object> values;

        /**
         * Data from the task.
         */
        private final Object taskData;
        /**
         * UserName the Context will be spanned for.
         */
        private final String userName;

        /**
         * Instantiates a new listener thread.
         *
         * @param _userName userName
         * @param _listener listener
         * @param _call     call
         * @param _values   values
         * @param _taskData taskdata
         */
        ListenerThread(final String _userName, final IAsyncListener _listener, final AsyncCalls _call,
                final Map<String, Object> _values, final Object _taskData) {
            this.userName = _userName;
            this.listener = _listener;
            this.call = _call;
            this.values = _values;
            this.taskData = _taskData;
        }

        /**
         * When an object implementing interface <code>Runnable</code> is used
         * to create a thread, starting the thread causes the object's
         * <code>run</code> method to be called in that separately executing
         * thread.
         * <p>
         * The general contract of the method <code>run</code> is that it may
         * take any action whatsoever.
         *
         * @see     java.lang.Thread#run()
         */
        @Override
        public void run() {
            try {
                if (!Context.isTMActive()) {
                    Context.begin(this.userName, Context.Inheritance.Local);
                }
            } catch (final EFapsException e) {
                BPM.LOG.error("Context problem", e);
            }
            try {
                switch (this.call) {
                case AFTER_EXECUTE:
                    this.listener.onAfterExecute(this.values, this.taskData);
                    break;
                default:
                    break;
                }
            } catch (final EFapsException e) {
                BPM.LOG.error("execution problem", e);
            } finally {
                try {
                    if (!Context.isTMNoTransaction()) {
                        if (Context.isTMActive()) {
                            Context.commit();
                        } else {
                            Context.rollback();
                        }
                    }
                } catch (final EFapsException e) {
                    BPM.LOG.error("Context problem", e);
                }
            }
        }
    }
}