/*
 *
 */
package com.fp.bpmlib.task.client;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.naming.InitialContext;
import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.jbpm.process.instance.event.listeners.TriggerRulesEventListener;
import org.jbpm.services.task.impl.model.CommentImpl;
import org.jbpm.services.task.impl.model.UserImpl;
import org.jbpm.services.task.lifecycle.listeners.BAMTaskEventListener;
import org.jbpm.services.task.lifecycle.listeners.TaskLifeCycleEventListener;
import org.jbpm.services.task.utils.ContentMarshallerHelper;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.manager.RuntimeEngine;
import org.kie.api.runtime.manager.RuntimeManager;
import org.kie.api.task.TaskService;
import org.kie.api.task.model.Content;
import org.kie.api.task.model.Status;
import org.kie.api.task.model.Task;
import org.kie.api.task.model.TaskData;
import org.kie.api.task.model.TaskSummary;
import org.kie.internal.task.api.EventService;
import org.kie.internal.task.api.InternalTaskService;

import com.fp.bpmlib.Common;
import com.fp.bpmlib.ProcessUtil;
import com.fp.bpmlib.ejb.local.JbpmBeanLocal;
import com.fp.bpmlib.query.monitor.FlowActivitySave;
import com.fp.bpmlib.task.MaiaWorkItemHandler;
import com.fp.common.helper.Constant;
import com.fp.common.logger.APPLogger;
import com.fp.persistence.commondb.PersistenceHelper;
import com.fp.persistence.commondb.PersistenceManager;
import com.fp.persistence.pbpm.gene.TbpmGroupsUsers;
import com.fp.simple.dto.TaskInfo;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.jbpm.services.task.impl.model.DeadlinesImpl;
import org.jbpm.services.task.impl.model.DelegationImpl;
import org.jbpm.services.task.impl.model.PeopleAssignmentsImpl;
import org.jbpm.services.task.impl.model.TaskDataImpl;
import org.jbpm.services.task.impl.model.TaskImpl;
import org.kie.internal.task.api.model.AccessType;
import org.kie.internal.task.api.model.AllowedToDelegate;
import org.kie.internal.task.api.model.SubTasksStrategy;

//
/**
 * Class HumanTaskClient encargada de acceder al Servidor de Tareas.
 *
 * @author Jvaca
 * @version 2.1
 */
public class HumanTaskClient {

    /**
     * El valor de language.
     */
    private String language = "en-UK";

    private final TaskService taskService;

    private final KieSession kiesession;

    /**
     * Crea una nueva instancia de human task client.
     *
     * @throws Exception la exception
     */
    public HumanTaskClient() throws Exception {
        JbpmBeanLocal local = (JbpmBeanLocal) new InitialContext().lookup("java:global/maiaear-2.1/bpmlib/jbpmbean");
        RuntimeManager manager = local.getRuntimeManager();
        RuntimeEngine runtime = manager.getRuntimeEngine(null);
        kiesession = runtime.getKieSession();
        taskService = runtime.getTaskService();
        kiesession.addEventListener(new TriggerRulesEventListener(kiesession));
        kiesession.getWorkItemManager().registerWorkItemHandler("Human Task", new MaiaWorkItemHandler());
        this.addListeners(runtime);
    }

    /**
     * Adiciona listener, para el manejo del bam de tareas.
     *
     * @param engine
     */
    @SuppressWarnings("unchecked")
    private void addListeners(RuntimeEngine engine) {
        EventService<TaskLifeCycleEventListener> eventService = (EventService<TaskLifeCycleEventListener>) engine.getTaskService();
        boolean hasBamEventListener = false;
        for (TaskLifeCycleEventListener listener : eventService.getTaskEventListeners()) {
            if (listener instanceof BAMTaskEventListener) {
                hasBamEventListener = true;
                break;
            }
        }
        if (!hasBamEventListener) {
            BAMTaskEventListener bamTaskEventListener = new BAMTaskEventListener();
            eventService.registerTaskEventListener(bamTaskEventListener);
        }
    }

    /**
     * Activate task.
     *
     * @param pTask the task
     * @param pUserId the user id
     * @throws Exception la exception
     */
    public void activateTask(long pTask, String pUserId) throws Exception {
        taskService.activate(pTask, pUserId);

    }

    /**
     * Claim task.
     *
     * @param pTask the task
     * @param pUserId the user id
     * @throws Exception la exception
     */
    public void claimTask(long pTask, String pUserId) throws Exception {
        taskService.claim(pTask, pUserId);
        FlowActivitySave.actualizarActividadClaim(pTask, pUserId);
    }

    /**
     * Entrega lsita de grupos bpm al que pertenece el usuario.
     *
     * @param pUser Codigo de usuario a buscar los grupos a los que pertenece.
     * @return List<String>
     * @throws Exception la exception
     */
    public static List<String> groupsByUser(String pUser) throws Exception {
        List<TbpmGroupsUsers> groups = TbpmGroupsUsers.findGroupsByUser(PersistenceHelper.getEntityManager(), pUser);
        List<String> data = new ArrayList<String>();
        for (TbpmGroupsUsers tbpmGroupsUsers : groups) {
            data.add(tbpmGroupsUsers.getPk().getGroupcode());
        }
        return data;
    }

    /**
     * Close.
     *
     * @throws Exception la exception
     */
    public void close() throws Exception {
        // No hacer nada con JTA la session se cierra automaticamente.
    }

    /**
     * Complete task.
     *
     * @param pTask the task
     * @param pJournalId the journal id
     * @param data the data
     * @param pResultado the resultado
     * @param pObs the obs
     * @throws Exception la exception
     */
    public String completeTask(long pTask, String pJournalId, Map<String, Object> data, String pResultado, String pObs) throws Exception {
        Task t = this.getTaskById(pTask);
        TaskData td = t.getTaskData();
        this.addComment(pTask, td.getActualOwner().getId(), pObs);
        Map<String, Object> input = this.getInputData(t);
        TaskInfo ti = (TaskInfo) input.get(ProcessUtil.TASK_METADATA);
        ti.setResponse(pResultado);
        ti.setTaskId(pTask);
        ti.setJournalId(pJournalId);
        if (ti.getUserId() == null && t.getTaskData().getActualOwner() != null) {
            ti.setUserId(t.getTaskData().getActualOwner().getId());
        }

        // Las fechas para el monitor se toman de BamTaskSummary
        // ti.setCreated(new Timestamp( td.getCreatedOn().getTime()));
        // ti.setCompleted(FormatDates.getInstance().getDataBaseTimestamp());
        ti.getAditionalData().putAll(data);
        taskService.complete(pTask, td.getActualOwner().getId(), input);
        FlowActivitySave.actualizarActividadComplete(pTask, ti);
        return ti.getTname();
    }

    /**
     * Adiciona un comment.
     *
     * @param pTask the task
     * @param pUserId the user id
     * @param pComment the comment
     * @throws Exception la exception
     */
    public void addComment(long pTask, String pUserId, String pComment) throws Exception {
        InternalTaskService its = (InternalTaskService) taskService;
        CommentImpl comentario = new CommentImpl();
        comentario.setText(pComment);
        comentario.setAddedAt(Common.getInstance().getCurrentDate());
        comentario.setAddedBy(new UserImpl(pUserId));
        its.addComment(pTask, comentario);

    }

    /**
     * Delegate task.
     *
     * @param pTask the task
     * @param pUserId the user id
     * @param pTargetUserId the target user id
     * @throws Exception la exception
     */
    public void delegateTask(long pTask, String pUserId, String pTargetUserId) throws Exception {
        taskService.delegate(pTask, pUserId, pTargetUserId);
        FlowActivitySave.actualizarActividadDelegate(pTask, pTargetUserId);
    }

    /**
     * Obtiene el valor de assigned tasks.
     *
     * @return Valor de assigned tasks
     * @throws Exception la exception
     */
    public List<TaskSummary> getAssignedTasks() throws Exception {
        return taskService.getTasksAssignedAsPotentialOwner(null, language);
    }

    /**
     * Obtiene el valor de assigned tasks.
     *
     * @param pUserId the user id
     * @return Valor de assigned tasks
     * @throws Exception la exception
     */
    public List<TaskSummary> getAssignedTasks(String pUserId) throws Exception {
        // this.client.getTasksAssignedAsPotentialOwner(pUserId, this.language, taskSummaryHandler);
        return taskService.getTasksOwned(pUserId, language);
    }

    /**
     * Obtiene el valor de content by id.
     *
     * @param pId the id
     * @return Valor de content by id
     * @throws Exception la exception
     */
    public Content getContentById(long pId) throws Exception {
        return taskService.getContentById(pId);
    }

    /**
     * Obtiene el valor de input data.
     *
     * @param pTask the task
     * @return Valor de input data
     * @throws Exception la exception
     */
    public Map<String, Object> getInputData(Task pTask) throws Exception {
        Content c = this.getContentById(pTask.getTaskData().getDocumentContentId());
        return HumanTaskClient.getContenido(c);
    }

    /**
     * Obtiene el valor de output data.
     *
     * @param pTask the task
     * @return Valor de output data
     * @throws Exception la exception
     */
    public Map<String, Object> getOutputData(Task pTask) throws Exception {
        Content c = this.getContentById(pTask.getTaskData().getOutputContentId());
        return HumanTaskClient.getContenido(c);
    }

    /**
     * Entrega el contenido asociado al workitem.
     *
     * @param task Datos de la tarea
     * @return Map<String, Object>
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> getContenido(Content content) throws Exception {
        Map<String, Object> maia = new HashMap<String, Object>();
        Object obj = ContentMarshallerHelper.unmarshall(content.getContent(), null);
        if (obj instanceof Map) {
            maia = (Map<String, Object>) obj;
        }
        return maia;
    }

    /**
     * Obtiene el valor de input data.
     *
     * @param pTask the task
     * @return Valor de input data
     * @throws Exception la exception
     */
    @SuppressWarnings(Constant.WARN_UNCHECKED)
    @Deprecated
    public Map<String, Object> getDatos(Content c) throws Exception {
        if (c != null) {
            // Esto funciona con jbm 5.4
            Object obj = ContentMarshallerHelper.unmarshall(c.getContent(), null);
            if (obj != null) {
                ByteArrayOutputStream bos = null;
                ObjectOutputStream out = null;
                try {
                    // return (Map<String, Object>) obj;
                    bos = new ByteArrayOutputStream();
                    out = new ObjectOutputStream(bos);
                    out.writeObject(obj);
                    ObjectInputStream bin = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
                    return (Map<String, Object>) bin.readObject();
                } finally {
                    bos.close();
                    out.close();
                }
            }
        }

        ObjectInputStream bin = new ObjectInputStream(new ByteArrayInputStream(c.getContent()));
        try {
            return (Map<String, Object>) bin.readObject();
        } finally {
            bin.close();
        }
    }

    /**
     * Obtiene el valor de task by id.
     *
     * @param pId the id
     * @return Valor de task by id
     * @throws Exception la exception
     */
    public Task getTaskById(long pId) throws Exception {
        return taskService.getTaskById(pId);
    }

    /**
     * Obtiene el valor de task by work item id.
     *
     * @param pWorkId the work id
     * @return Valor de task by work item id
     * @throws Exception la exception
     */
    public Task getTaskByWorkItemId(long pWorkId) throws Exception {
        return taskService.getTaskByWorkItemId(pWorkId);
    }

    /**
     * Obtiene el valor de task content input.
     *
     * @param taskSum the task sum
     * @return Valor de task content input
     */
    public Object getTaskContentInput(TaskSummary taskSum) {
        ByteArrayInputStream bais = null;
        ObjectInputStream is = null;

        Task task2 = taskService.getTaskById(taskSum.getId());
        TaskData taskData = task2.getTaskData();
        Content content = taskService.getContentById(taskData.getDocumentContentId());

        try {
            bais = new ByteArrayInputStream(content.getContent());
            is = new ObjectInputStream(bais);
            Object obj = null;

            do {
                obj = is.readObject();
                if (obj == null) {
                    break;
                }
                APPLogger.getLogger().debug("OBJECT: " + obj);
                return obj;
            } while (obj != null);
        } catch (Exception e) {
            APPLogger.getLogger().warn(e, e);
            return null;
        } finally {
            try {
                if (bais != null) {
                    bais.close();
                }
            } catch (Exception e2) {
            }
            try {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e2) {
            }
        }
        return null;
    }

    /**
     * Obtiene el valor de task data.
     *
     * @param pTask the task
     * @return Valor de task data
     * @throws Exception la exception
     */
    public TaskData getTaskData(long pTask) throws Exception {
        Task task = this.getTaskById(pTask);
        return task.getTaskData();
    }

    /**
     * Obtiene el listado de tareas Asignadas.
     *
     * @param pUserCri the user cri
     * @param pCriteria the criteria
     * @param pPage the page
     * @param pRecords the records
     * @return Listado de tareas asignadas
     * @throws Exception la exception
     */
    public List<Object[]> getAsignedTasks(String pUserCri) throws Exception {
        List<Status> lestatus = new ArrayList<>();
        List<Object[]> lresp = new ArrayList<>();
        lestatus.add(Status.Reserved);
        lestatus.add(Status.InProgress);
        List<TaskSummary> list;
        try {
            list = taskService.getTasksOwnedByStatus(pUserCri, lestatus, "en-UK");
            for (TaskSummary obj : list) {
                Object o[] = new Object[2];
                Task task = this.getTaskById(obj.getId());
                Content c = this.getContentById(task.getTaskData().getDocumentContentId());
                o[0] = task;
                o[1] = c;
                lresp.add(o);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return lresp;
    }

    /**
     * Obtiene el valor de unfinished tasks.
     *
     * @param pUserId the user id
     * @param pCri the cri
     * @return Valor de unfinished tasks
     * @throws Exception la exception
     */
    public List<Object[]> getUnfinishedTasksByUser(String pUserId) throws Exception {
        List<Status> lestatus = new ArrayList<>();
        List<Object[]> lresp = new ArrayList<>();
        lestatus.add(Status.Reserved);
        lestatus.add(Status.InProgress);
        List<TaskSummary> list = taskService.getTasksOwnedByStatus(pUserId, lestatus, "en-UK");
        try {
            list = taskService.getTasksOwnedByStatus(pUserId, lestatus, "en-UK");
            for (TaskSummary obj : list) {
                Object o[] = new Object[2];
                Task task = this.getTaskById(obj.getId());
                Content c = this.getContentById(task.getTaskData().getDocumentContentId());
                o[0] = task;
                o[1] = c;
                lresp.add(o);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return lresp;

    }

    /**
     * JPQL JPQL_TASK_NOT_COMPLETEBYGROUP
     */
//    private static final String TAREAS_GRUPO = "select t, potentialOwners.id from TaskImpl t, OrganizationalEntityImpl potentialOwners "
//            + "where potentialOwners.id in (:groupIds) and potentialOwners in elements ( t.peopleAssignments.potentialOwners ) and t.archived = 0 "
//            + "and t.taskData.actualOwner = null and t.taskData.status in ('Created', 'Ready', 'Reserved', 'InProgress', 'Suspended')";
    private static final String TAREAS_GRUPO = "SELECT t.id as taskId, t.archived , t.allowedtodelegate , t.description , t.formname , t.NAME , t.taskinitiator_id , "
            + "t.priority , t.subtaskstrategy , t.subject , t.activationtime , t.actualowner_id , t.createdby_id , t.createdon , t.deploymentid , "
            + "t.documentaccesstype , t.documentcontentid , t.documenttype , t.expirationtime , t.faultaccesstype , t.faultcontentid , t.faultname , "
            + "t.faulttype , t.outputaccesstype , t.outputcontentid , t.outputtype , t.parentid , t.previousstatus , t.processid , t.processinstanceid , "
            + "t.processsessionid , t.skipable , t.status , t.workitemid , t.tasktype , t.optlock , o.id as orgId "
            + "FROM jbpm6.task t "
            + "CROSS JOIN jbpm6.organizationalentity o "
            + "INNER JOIN jbpm6.peopleassignments_potowners po ON po.task_id = t.id AND po.entity_id = o.id "
            + "WHERE(o.id IN (:groupIds)) AND t.archived = 0 AND (t.actualowner_id IS NULL) AND (t.status IN ( 'Created', 'Ready', 'Reserved', 'InProgress','Suspended')) order by t.id";

    /**
     * Obtiene el valor de unfinished tasks por Grupo.
     *
     * @param pGroupId the user id
     * @param pCri the cri
     * @return Valor de unfinished tasks
     * @throws Exception la exception
     */
    @SuppressWarnings(Constant.WARN_UNCHECKED)
    public List<Object[]> getTasksByGroup(String pGroupId, String pCri) throws Exception {
        List<Object[]> ldatos = new ArrayList<Object[]>();
        TaskImpl t;
        TaskDataImpl td;

        EntityManager em = null;
        try {
            em = PersistenceManager.getInstance().getEntityManagerFactoryAuxiliar("org.jbpm.domain").createEntityManager();
//            Query qry = em.createQuery(HumanTaskClient.TAREAS_GRUPO);
            Query qry = em.createNativeQuery(HumanTaskClient.TAREAS_GRUPO);
            qry.setParameter("groupIds", pGroupId);
            List<Fila> data = ejecutarConsultaNativaList(qry);

            for (Fila row : data) {
                ldatos.add(new Object[]{mapTask(row), row.get(36)});
            }
        } catch (Exception e) {
            e.printStackTrace(System.err);
        } finally {
            if (em.isOpen()) {
                em.close();
            }
        }
        return ldatos;
    }

    /**
     *
     * @param query
     * @param consulta
     * @return
     */
    public List<Fila> ejecutarConsultaNativaList(Query query) {
        List<Fila> resultado = new ArrayList<>();
        List datos = query.getResultList();
        if (datos == null || datos.isEmpty()) {
            return resultado;
        }

        for (Object row : datos) {
            Fila fila = new Fila();
            if (row.getClass().isArray()) {
                Object[] orow = (Object[]) row;
                for (Object val : orow) {
                    fila.add(val);
                }
            } else {
                fila.add(row);
            }
            resultado.add(fila);
        }
        return resultado;
    }

    public TaskImpl mapTask(Fila row) {
        TaskImpl ti = new TaskImpl();
        PeopleAssignmentsImpl pa = new PeopleAssignmentsImpl();
        DelegationImpl di = new DelegationImpl();
        TaskDataImpl tdi = new TaskDataImpl();
        DeadlinesImpl dli = new DeadlinesImpl();
        ti.setId(evalLong(row.get(0)));
        ti.setArchived(evalInt(row.get(1)) == 1);
        di.setAllowed(evaluateATD(row.get(2)));
        ti.setDescription((String) row.get(3));
        ti.setFormName((String) row.get(4));
        ti.setName((String) row.get(5));
        pa.setTaskInitiator(new UserImpl((String) row.get(6)));
        ti.setPriority(evalInt(row.get(7)));
        ti.setSubTaskStrategy(evaluateSub(row.get(8)));
        ti.setSubject((String) row.get(9));
        tdi.setActivationTime(evaluateDate(row.get(10)));
        tdi.setActualOwner(new UserImpl((String) row.get(11)));
        tdi.setCreatedBy(new UserImpl((String) row.get(12)));
        tdi.setCreatedOn(evaluateDate(row.get(13)));
        tdi.setDeploymentId((String) row.get(14));
        tdi.setDocumentAccessType(evaluateAT(row.get(15)));
        tdi.setDocumentContentId(evalLong(row.get(16)));
        tdi.setDocumentType((String) row.get(17));
        tdi.setExpirationTime(evaluateDate(row.get(18)));
        tdi.setFaultAccessType(evaluateAT(row.get(19)));
        tdi.setFaultContentId(evalLong(row.get(20)));
        tdi.setFaultName((String) row.get(21));
        tdi.setFaultType((String) row.get(22));
        tdi.setOutputAccessType(evaluateAT(row.get(23)));
        tdi.setOutputContentId(evalLong(row.get(24)));
        tdi.setOutputType((String) row.get(25));
        tdi.setParentId(evalLong(row.get(26)));
        tdi.setPreviousStatus(evaluateStatus(row.get(27)));
        tdi.setProcessId((String) row.get(28));
        tdi.setProcessInstanceId(evalLong(row.get(29)));
        tdi.setProcessSessionId(evalInt(row.get(30)));
        tdi.setSkipable((Boolean)row.get(31));
        tdi.setStatus(evaluateStatus(row.get(32)));
        tdi.setWorkItemId(evalLong(row.get(33)));
        ti.setTaskType((String) row.get(34));

        ti.setPeopleAssignments(pa);
        ti.setDelegation(di);
        ti.setTaskData(tdi);
        ti.setDeadlines(dli);
        return ti;
    }

    public Integer evalInt(Object data) {
        Integer result = null;
        if (data != null) {
            result = ((BigDecimal) data).intValue();
        }
        return result;
    }

    public Long evalLong(Object data) {
        Long result = null;
        if (data != null) {
            result = ((BigDecimal) data).longValue();
        }
        return result;
    }

    public static Status evaluateStatus(Object data) {
        Status at = null;
        if (data != null) {
            if (data instanceof Status) {
                at = (Status) data;
            } else {
                try {
                    at = Status.valueOf(data.toString());
                } catch (RuntimeException ex) {
                    at = null;
                }
            }
        }
        return at;
    }

    public static AccessType evaluateAT(Object data) {
        AccessType at = null;
        if (data != null) {
            if (data instanceof AccessType) {
                at = (AccessType) data;
            } else {
                try {
                    at = AccessType.valueOf(data.toString());
                } catch (RuntimeException ex) {
                    at = null;
                }
            }
        }
        return at;
    }

    public static SubTasksStrategy evaluateSub(Object data) {
        SubTasksStrategy st = null;
        if (data != null) {
            if (data instanceof SubTasksStrategy) {
                st = (SubTasksStrategy) data;
            } else {
                try {
                    st = SubTasksStrategy.valueOf(data.toString());
                } catch (RuntimeException ex) {
                    st = null;
                }
            }
        }
        return st;
    }

    public static AllowedToDelegate evaluateATD(Object data) {
        AllowedToDelegate del = null;
        if (data != null) {
            if (data instanceof AllowedToDelegate) {
                del = (AllowedToDelegate) data;
            } else {
                try {
                    del = AllowedToDelegate.valueOf(data.toString());
                } catch (RuntimeException ex) {
                    del = null;
                }
            }
        }
        return del;
    }

    public static Date evaluateDate(Object date) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date fecha = null;
        if (date != null) {
            if (date instanceof Date) {
                fecha = (Date) date;
            } else {
                try {
                    fecha = df.parse(date.toString());
                } catch (ParseException ex) {
                    fecha = null;
                }
            }
        }
        return fecha;
    }

    /**
     * Release task.
     *
     * @param pTask the task
     * @param pUserId the user id
     * @throws Exception la exception
     */
    public void releaseTask(long pTask, String pUserId) throws Exception {
        taskService.release(pTask, pUserId);
    }

    /**
     * Resume task.
     *
     * @param pTask the task
     * @param pUserId the user id
     * @throws Exception la exception
     */
    public void resumeTask(long pTask, String pUserId) throws Exception {
        taskService.resume(pTask, pUserId);
    }

    /**
     * Start task.
     *
     * @param pTask the task
     * @throws Exception la exception
     */
    public void startTask(long pTask) throws Exception {
        Task task = this.getTaskById(pTask);
        APPLogger.getLogger().debug("Starting task " + pTask);
        Map<String, Object> input = this.getInputData(task);
        // com.fp.bpmlib.Process p = this.findProcess(task.getTaskData(), snapshot);
        // TaskInfo ti = (TaskInfo) input.get(ProcessUtil.TASK_METADATA);
        // ti.setTaskId(pTask);
        // ti.setStarted(FormatDates.getInstance().getDataBaseTimestamp());
        // ti.setCreated(new Timestamp(task.getTaskData().getCreatedOn().getTime()));

        // ProcessInstance processInstance = kiesession.getProcessInstance(task.getTaskData().getProcessInstanceId());
        // RuleFlowProcessInstance rfpi = (RuleFlowProcessInstance) processInstance;
        // rfpi.setVariable(ProcessUtil.TASK_METADATA, ti); //actualiza datos en el contexto.
        // InternalTaskService its = ((InternalTaskService) taskService);
        // Elimina el content anterior y remplaza por un nuevo content.
        // its.deleteContent(pTask, task.getTaskData().getDocumentContentId());
        // its.addContent(pTask, input);
        // ***** LA FECHA DE CREACION E INICIO SE TOMA DE LA BAMTASKSUMMARY PARA PRESENTAR EN EL MONITOR.
        taskService.start(pTask, task.getTaskData().getActualOwner().getId());
        FlowActivitySave.actualizarActividadStart(pTask);
        APPLogger.getLogger().debug("Started task " + pTask);
    }

    /**
     * Stop task.
     *
     * @param pTask the task
     * @param pUserId the user id
     * @throws Exception la exception
     */
    public void stopTask(long pTask, String pUserId) throws Exception {
        taskService.stop(pTask, pUserId);
    }

    /**
     * Suspend task.
     *
     * @param pTask the task
     * @param pUserId the user id
     * @throws Exception la exception
     */
    public void suspendTask(long pTask, String pUserId) throws Exception {
        taskService.suspend(pTask, pUserId);
    }

    class Fila extends ArrayList<Object> {

    }

}
