Java tutorial
/* * Copyright (C) 2016 Singular Studios (a.k.a Atom Tecnologia) - www.opensingular.com * * 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.opensingular.flow.core; import com.google.common.collect.Lists; import org.apache.commons.lang3.StringUtils; import org.opensingular.flow.core.entity.IEntityCategory; import org.opensingular.flow.core.entity.IEntityProcessDefinition; import org.opensingular.flow.core.entity.IEntityProcessInstance; import org.opensingular.flow.core.entity.IEntityProcessVersion; import org.opensingular.flow.core.entity.IEntityRoleDefinition; import org.opensingular.flow.core.entity.IEntityRoleInstance; import org.opensingular.flow.core.entity.IEntityTaskDefinition; import org.opensingular.flow.core.entity.IEntityTaskInstance; import org.opensingular.flow.core.entity.IEntityTaskVersion; import org.opensingular.flow.core.entity.IEntityVariableInstance; import org.opensingular.flow.core.service.IPersistenceService; import org.opensingular.flow.core.variable.VarInstanceMap; import org.opensingular.lib.commons.base.SingularException; import org.opensingular.lib.commons.net.Lnk; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.Serializable; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; /** * <p> * Esta a classe responsvel por manter os dados de instncia de um * determinado processo. * </p> * * @author Daniel Bordin */ @SuppressWarnings({ "serial", "unchecked" }) public class ProcessInstance implements Serializable { private RefProcessDefinition processDefinitionRef; private Integer codEntity; private transient IEntityProcessInstance entity; private transient STask<?> estadoAtual; private transient ExecutionContext executionContext; private transient VarInstanceMap<?, ?> variables; final void setProcessDefinition(ProcessDefinition<?> processDefinition) { if (processDefinitionRef != null) { throw SingularException.rethrow("Erro Interno"); } processDefinitionRef = RefProcessDefinition.of(processDefinition); } /** * <p> * Retorna a definio de processo desta instncia. * </p> * * @param <K> o tipo da definio de processo. * @return a definio de processo desta instncia. */ @Nonnull public <K extends ProcessDefinition<?>> K getProcessDefinition() { if (processDefinitionRef == null) { throw SingularException.rethrow( "A instncia no foi inicializada corretamente, pois no tem uma referncia a ProcessDefinition! Tente chamar o mtodo newPreStartInstance() a partir da definio do processo."); } return (K) processDefinitionRef.get(); } /** * Inicia esta instncia de processo. * * @return A tarefa atual da instncia depois da inicializao. */ @Deprecated public TaskInstance start() { getPersistedDescription(); // Fora a gerao da descrio return FlowEngine.start(this, getVariables()); } /** * Realiza a montagem necessria para execuo da transio default da tarefa atual desta instncia. * Seno for encontrada uma tarefa atual ou a tarefa no possui um transao default, dispara exception. */ @Nonnull public TransitionCall prepareTransition() { return getCurrentTaskOrException().prepareTransition(); } /** * Realiza a montagem necessria para execuo da transio especificada a partir da tarefa atual desta instncia. * Seno for encontrada uma tarefa atual ou transio correspodente ao nome informado, dispara exception. * * @param transitionName a transio especificada. * @see TaskInstance#prepareTransition(String) */ @Nonnull public TransitionCall prepareTransition(String transitionName) { return getCurrentTaskOrException().prepareTransition(transitionName); } final @Nonnull IEntityProcessInstance getInternalEntity() { if (entity == null) { if (codEntity != null) { IEntityProcessInstance newfromDB = getPersistenceService() .retrieveProcessInstanceByCodOrException(codEntity); IEntityProcessDefinition entityProcessDefinition = getProcessDefinition() .getEntityProcessDefinition(); if (!entityProcessDefinition.equals(newfromDB.getProcessVersion().getProcessDefinition())) { throw SingularException.rethrow(getProcessDefinition().getName() + " id=" + codEntity + " se refere a definio de processo " + newfromDB.getProcessVersion().getProcessDefinition().getKey() + " mas era esperado que referenciasse " + entityProcessDefinition); } entity = newfromDB; } if (entity == null) { throw SingularException.rethrow(getClass().getName() + " is not binded to a new and neither to a existing database intance process entity."); } } return entity; } final void setInternalEntity(IEntityProcessInstance entity) { Objects.requireNonNull(entity); this.entity = entity; this.codEntity = entity.getCod(); } /** * <p> * Configura a instncia "pai" desta instncia de processo. * </p> * * @param pai a instncia "pai". */ public void setParent(ProcessInstance pai) { getPersistenceService().setProcessInstanceParent(getInternalEntity(), pai.getInternalEntity()); } /** * <p> * Retorna a tarefa "pai" desta instncia de processo. * </p> * * @return a tarefa "pai". */ public TaskInstance getParentTask() { IEntityTaskInstance dbTaskInstance = getInternalEntity().getParentTask(); return dbTaskInstance == null ? null : Flow.getTaskInstance(dbTaskInstance); } /** * Retorna o tipo da tarefa corrente desta instncia de processo. Pode no encotrar se a tarefa em banco no * tiver correspondncia com o fluxo do processo em memria (tarefa legada). */ public Optional<STask<?>> getState() { if (estadoAtual == null) { Optional<TaskInstance> current = getCurrentTask(); if (current.isPresent()) { estadoAtual = getProcessDefinition().getFlowMap() .getTaskByAbbreviation(current.get().getAbbreviation()).orElse(null); } else if (isFinished()) { current = getTaskNewer(); if (current.isPresent() && current.get().isFinished()) { estadoAtual = getProcessDefinition().getFlowMap() .getTaskByAbbreviation(current.get().getAbbreviation()).orElse(null); } else { throw new SingularFlowException(createErrorMsg( "incossitencia: o estado final est null, mas deveria ter um estado do tipo final por " + "estar finalizado"), this); } } else { throw new SingularFlowException( createErrorMsg("getState() no pode ser invocado para essa instncia"), this); } } return Optional.ofNullable(estadoAtual); } /** * <p> * Verifica se esta instncia est encerrada. * </p> * * @return {@code true} caso esta instncia est encerrada; {@code false} * caso contrrio. */ public boolean isFinished() { return getEndDate() != null; } /** * <p> * Retornar o nome da definio de processo desta instncia. * </p> * * @return o nome da definio de processo. */ public String getProcessName() { return getProcessDefinition().getName(); } /** * Retorna o nome da tarefa atual desta instncia de processo. * * @return o nome da tarefa atual; ou {@code null} caso no haja uma tarefa atual. */ @Nonnull public Optional<String> getCurrentTaskName() { Optional<String> name = getState().map(STask::getName); if (!name.isPresent()) { name = getCurrentTask().map(TaskInstance::getName); } return name; } /** * <p> * Retorna o <i>link resolver</i> padro desta instncia de processo. * </p> * * @return o <i>link resolver</i> padro. */ public final Lnk getDefaultHref() { return Flow.getDefaultHrefFor(this); } /** * <p> * Retorna os cdigos de usurios com direito de execuo da tarefa humana * definida para o processo correspondente a esta instncia. * </p> * * @param nomeTarefa o nome da tarefa humana a ser inspecionada. * @return os cdigos de usurios com direitos de execuo. */ public Set<Integer> getFirstLevelUsersCodWithAccess(String nomeTarefa) { return getProcessDefinition().getFlowMap().getPeopleTaskByAbbreviationOrException(nomeTarefa) .getAccessStrategy().getFirstLevelUsersCodWithAccess(this); } /** * <p> * Verifica de o usurio especificado pode executar a tarefa corrente desta * instncia de processo. * </p> * * @param user o usurio especificado. * @return {@code true} caso o usurio possa executar a tarefa corrente; * {@code false} caso contrrio. */ public final boolean canExecuteTask(SUser user) { Optional<STask<?>> currentState = getState(); if (!currentState.isPresent()) { return false; } IEntityTaskType tt = currentState.get().getTaskType(); if (tt.isPeople() || tt.isWait()) { if (isAllocated(user.getCod())) { return true; } Optional<TaskAccessStrategy<ProcessInstance>> strategy = getAccessStrategy(); return strategy.isPresent() && strategy.get().canExecute(this, user); } return false; } /** * Verifica de o usurio especificado pode visualizar a tarefa corrente * desta instncia de processo. * * @param user o usurio especificado. * @return {@code true} caso o usurio possa visualizar a tarefa corrente; * {@code false} caso contrrio. */ public boolean canVisualize(@Nonnull SUser user) { Objects.requireNonNull(user); Optional<STask<?>> tt = getLatestTaskOrException().getFlowTask(); if (tt.isPresent()) { if ((tt.get().isPeople() || tt.get().isWait()) && hasAllocatedUser() && isAllocated(user.getCod())) { return true; } } Optional<TaskAccessStrategy<ProcessInstance>> strategey = getAccessStrategy(); return strategey.isPresent() && strategey.get().canVisualize(this, user); } /** * Retorna os cdigos de usurios com direito de execuo da tarefa corrente * desta instncia de processo. * * @return os cdigos de usurios com direitos de execuo. */ public Set<Integer> getFirstLevelUsersCodWithAccess() { return getAccessStrategy().map(strategy -> strategy.getFirstLevelUsersCodWithAccess(this)) .orElse(Collections.emptySet()); } /** * Retorna os usurios com direito de execuo da tarefa corrente desta * instncia de processo. * * @return os usurios com direitos de execuo. */ public List<SUser> listAllocableUsers() { return getAccessStrategy().map(strategy -> (List<SUser>) strategy.listAllocableUsers(this)) .orElse(Collections.emptyList()); } /** * <p> * Formata uma mensagem de erro. * </p> * <p> * A formatao da mensagem segue o seguinte padro: * </p> * * <pre> * getClass().getName() + " - " + getFullId() + " : " + message * </pre> * * @param message a mensagem a ser formatada. * @return a mensagem formatada. * @see #getFullId() */ public final String createErrorMsg(String message) { return getClass().getName() + " - " + getFullId() + " : " + message; } @SuppressWarnings("rawtypes") private Optional<TaskAccessStrategy<ProcessInstance>> getAccessStrategy() { return getState().map(task -> task.getAccessStrategy()); } /** * Apenas para uso interno da engine de processo e da persistencia. */ public final void refreshEntity() { getPersistenceService().refreshModel(getInternalEntity()); } /** * Recupera a entidade persistente correspondente a esta instncia de * processo. */ public final IEntityProcessInstance getEntity() { if (codEntity == null && getInternalEntity().getCod() == null) { return saveEntity(); } entity = getPersistenceService().retrieveProcessInstanceByCodOrException(codEntity); return entity; } /** * <p> * Retorna o usurio desta instncia de processo atribudo ao papel * especificado. * </p> * * @param roleAbbreviation a sigla do papel especificado. * @return o usurio atribudo ao papel. */ public final SUser getUserWithRole(String roleAbbreviation) { final IEntityRoleInstance entityRole = getEntity().getRoleUserByAbbreviation(roleAbbreviation); if (entityRole != null) { return entityRole.getUser(); } return null; } /** * Recupera a lista de papeis da entidade persistente correspondente a esta * instncia. */ // TODO Daniel deveria retornar um objeto que isolasse da persistncia final List<? extends IEntityRoleInstance> getUserRoles() { return getEntity().getRoles(); } /** * Recupera a lista de papeis com a sigla especificada da entidade * persistente correspondente a esta instncia. * * @param roleAbbreviation a sigla especificada. */ public final IEntityRoleInstance getRoleUserByAbbreviation(String roleAbbreviation) { return getEntity().getRoleUserByAbbreviation(roleAbbreviation); } /** * Verifica se h papeis definidos. * * @return {@code true} caso haja pelo menos um papel definido; * {@code false} caso contrrio. */ public final boolean hasUserRoles() { return !getEntity().getRoles().isEmpty(); } /** * Retorna o usurio que criou esta instncia de processo. */ public final SUser getUserCreator() { return getInternalEntity().getUserCreator(); } /** * Altera a descrio desta instncia de processo. * <p> * A descrio ser truncada para um tamanho mximo de 250 caracteres. * </p> * * @param descricao a nova descrio. */ public final void setDescription(String descricao) { getInternalEntity().setDescription(StringUtils.left(descricao, 250)); } /** * Persiste esta instncia de processo. * * @param <K> o tipo da entidade desta instncia. * @return a entidade persistida. */ public final <K extends IEntityProcessInstance> K saveEntity() { setInternalEntity(getPersistenceService().saveProcessInstance(getInternalEntity())); return (K) getInternalEntity(); } /** * Realiza uma transio manual da tarefa atual para a tarefa especificada. * * @param task a tarefa especificada. */ public final void forceStateUpdate(@Nonnull STask<?> task) { Objects.requireNonNull(task); final TaskInstance tarefaOrigem = getLatestTaskOrException(); List<SUser> pessoasAnteriores = getDirectlyResponsibles(); final Date agora = new Date(); TaskInstance tarefaNova = updateState(tarefaOrigem, null, task, agora); tarefaOrigem.log("Alterao Manual de Estado", "de '" + tarefaOrigem.getName() + "' para '" + task.getName() + "'", null, Flow.getUserIfAvailable(), agora).sendEmail(pessoasAnteriores); FlowEngine.initTask(this, task, tarefaNova); ExecutionContext execucaoMTask = new ExecutionContext(this, tarefaNova, null); TaskInstance taskNew2 = getTaskNewer(task) .orElseThrow(() -> new SingularFlowException("Erro Interno", this)); task.notifyTaskStart(taskNew2, execucaoMTask); if (task.isImmediateExecution()) { prepareTransition().go(); } } /** * <p> * Realiza uma transio da tarefa de origiem para a tarefa alvo * especificadas. * </p> * * @param originTaskInstance a tarefa de origem. * @param transicaoOrigem a transio disparada. * @param task a tarefa alvo. * @param agora o momento da transio. * @return a tarefa corrente depois da transio. */ protected final TaskInstance updateState(TaskInstance originTaskInstance, STransition transicaoOrigem, @Nonnull STask<?> task, Date agora) { synchronized (this) { if (originTaskInstance != null) { originTaskInstance.endLastAllocation(); String transitionName = null; if (transicaoOrigem != null) { transitionName = transicaoOrigem.getAbbreviation(); } getPersistenceService().completeTask(originTaskInstance.getEntityTaskInstance(), transitionName, Flow.getUserIfAvailable()); } IEntityTaskVersion situacaoNova = getProcessDefinition().getEntityTaskVersion(task); IEntityTaskInstance tarefa = getPersistenceService().addTask(getEntity(), situacaoNova); TaskInstance tarefaNova = getTaskInstance(tarefa); estadoAtual = task; Flow.notifyListeners(n -> n.notifyStateUpdate(ProcessInstance.this)); return tarefaNova; } } /** * Retorna a data inicial desta instncia. * * @return nunca null. */ public Date getBeginDate() { return getInternalEntity().getBeginDate(); } /** * <p> * Retorna a data de encerramento desta instncia. * </p> * * @return a data de encerramento. */ public final Date getEndDate() { return getInternalEntity().getEndDate(); } /** * <p> * Retorna o cdigo desta instncia. * </p> * * @return o cdigo. */ public final Integer getEntityCod() { return codEntity; } /** * <p> * Retorna o cdigo desta instncia como uma {@link String}. * </p> * * @return o cdigo. */ public final String getId() { return getEntityCod().toString(); } /** * <p> * Retorna um novo <b>ID</b> autogerado para esta instncia. * </p> * * @return o <b>ID</b> autogerado. */ public final String getFullId() { return Flow.generateID(this); } @Nonnull private TaskInstance getTaskInstance(@Nonnull IEntityTaskInstance tarefa) { return new TaskInstance(this, Objects.requireNonNull(tarefa)); } /** * <p> * O mesmo que {@link #getCompleteDescription()}. * </p> * * @return a descrio completa. */ public String getDescription() { return getCompleteDescription(); } /** * <p> * Retorna o nome do processo seguido da descrio completa. * * @return o nome do processo seguido da descrio completa. */ public final String getExtendedDescription() { String descricao = getDescription(); if (descricao == null) { return getProcessName(); } return getProcessName() + " - " + descricao; } /** * <p> * Retorna a descrio atual desta instncia. * </p> * * @return a descrio atual. */ protected final String getPersistedDescription() { String descricao = getInternalEntity().getDescription(); if (descricao == null) { descricao = generateInitialDescription(); if (!StringUtils.isBlank(descricao)) { setDescription(descricao); } } return descricao; } /** * <p> * Cria a descrio que vai gravada no banco de dados. Deve ser sobreescrito * para ter efeito. * </p> * * @return a descrio criada. */ protected String generateInitialDescription() { return null; } /** * <p> * Sobrescreve a descrio da demanda a partir do mtodo * {@link #generateInitialDescription()}. * </p> * * @return {@code true} caso tenha sido alterada a descrio; {@code false} * caso contrrio. */ public final boolean regenerateInitialDescription() { String descricao = generateInitialDescription(); if (!StringUtils.isBlank(descricao) && !descricao.equalsIgnoreCase(getInternalEntity().getDescription())) { setDescription(descricao); return true; } return false; } /** * <p> * Cria verso extendida da descrio em relao ao campo descrio no BD. * </p> * <p> * Geralmente so adicionadas informaes que no precisam ter cache feito * em banco de dados. * </p> * * @return a descrio atual desta instncia. */ protected String getCompleteDescription() { return getPersistedDescription(); } /** * Retorna a lista de usurio diretamente responsveis pela tarefa atual (se existir tarefa atual). Pode retorna * uma lista vazia se no houver tarefa taual ou se a tarefa no tive nenhum responsavel direto ou se nao fizer * sentido ter responsvel direto (ex.: task Java). */ @Nonnull public List<SUser> getDirectlyResponsibles() { return getCurrentTask().map(TaskInstance::getDirectlyResponsibles).orElse(Collections.emptyList()); } private void addUserRole(SProcessRole sProcessRole, SUser user) { if (getUserWithRole(sProcessRole.getAbbreviation()) == null) { getPersistenceService().setInstanceUserRole(getEntity(), getProcessDefinition().getEntityProcessDefinition().getRole(sProcessRole.getAbbreviation()), user); } } /** * <p> * Atribui ou substitui o usurio para o papel especificado. * </p> * * @param roleAbbreviation o papel especificado. * @param newUser o novo usurio atribudo ao papel. */ public final void addOrReplaceUserRole(final String roleAbbreviation, SUser newUser) { SProcessRole sProcessRole = getProcessDefinition().getFlowMap().getRoleWithAbbreviation(roleAbbreviation); if (sProcessRole == null) { throw new SingularFlowException("No foi possvel encontrar a role: " + roleAbbreviation, this); } SUser previousUser = getUserWithRole(sProcessRole.getAbbreviation()); if (previousUser == null) { if (newUser != null) { addUserRole(sProcessRole, newUser); getProcessDefinition().getFlowMap().notifyRoleChange(this, sProcessRole, null, newUser); Optional<TaskInstance> latestTask = getTaskNewer(); if (latestTask.isPresent()) { latestTask.get().log("Papel definido", String.format("%s: %s", sProcessRole.getName(), newUser.getSimpleName())); } } } else if (newUser == null || !previousUser.equals(newUser)) { IEntityProcessInstance entityTmp = getEntity(); getPersistenceService().removeInstanceUserRole(entityTmp, entityTmp.getRoleUserByAbbreviation(sProcessRole.getAbbreviation())); if (newUser != null) { addUserRole(sProcessRole, newUser); } getProcessDefinition().getFlowMap().notifyRoleChange(this, sProcessRole, previousUser, newUser); Optional<TaskInstance> latestTask = getTaskNewer(); if (latestTask.isPresent()) { if (newUser != null) { latestTask.get().log("Papel alterado", String.format("%s: %s", sProcessRole.getName(), newUser.getSimpleName())); } else { latestTask.get().log("Papel removido", sProcessRole.getName()); } } } } /** * <p> * Configura o valor varivel especificada. * </p> * * @param variableName o nome da varivel especificada. * @param value o valor a ser configurado. */ public void setVariable(String variableName, Object value) { getVariables().setValue(variableName, value); } /** * <p> * Retorna o valor da varivel do tipo {@link Boolean} especificada. * </p> * * @param variableName o nome da varivel especificada. * @return o valor da varivel. */ public final Boolean getVariableValueBoolean(String variableName) { return getVariables().getValueBoolean(variableName); } /** * <p> * Retorna o valor da varivel do tipo {@link String} especificada. * </p> * * @param variableName o nome da varivel especificada. * @return o valor da varivel. */ public String getVariableValueString(String variableName) { return getVariables().getValueString(variableName); } /** * <p> * Retorna o valor da varivel do tipo {@link Integer} especificada. * </p> * * @param variableName o nome da varivel especificada. * @return o valor da varivel. */ public final Integer getVariableValueInteger(String variableName) { return getVariables().getValueInteger(variableName); } /** * <p> * Retorna o valor da varivel especificada. * </p> * * @param <T> o tipo da varivel especificada. * @param variableName o nome da varivel especificada. * @return o valor da varivel. */ public <T> T getVariableValue(String variableName) { return getVariables().getValue(variableName); } /** * <p> * Retorna o mapa das variveis desta instncia de processo. * </p> * * @return o mapa das variveis. */ public final VarInstanceMap<?, ?> getVariables() { if (variables == null) { variables = new VarInstanceTableProcess(this); } return variables; } /** * <p> * Verifica se h usurio alocado em alguma tarefa desta instncia de * processo. * </p> * * @return {@code true} caso haja algum usurio alocado; {@code false} caso * contrrio. */ public boolean hasAllocatedUser() { return getEntity().getTasks().stream() .anyMatch(tarefa -> tarefa.isActive() && tarefa.getAllocatedUser() != null); } /** * <p> * Retorna os usurios alocados nas tarefas ativas * </p> * * @return a lista de usurios (<i>null safe</i>). */ public Set<SUser> getAllocatedUsers() { return getEntity().getTasks().stream() .filter(tarefa -> tarefa.isActive() && tarefa.getAllocatedUser() != null) .map(tarefa -> tarefa.getAllocatedUser()).collect(Collectors.toSet()); } /** * <p> * Verifica se o usurio especificado est alocado em alguma tarefa desta * instncia de processo. * </p> * * @param codPessoa o cdigo usurio especificado. * @return {@code true} caso o usurio esteja alocado; {@code false} caso * contrrio. */ public boolean isAllocated(Integer codPessoa) { return getEntity().getTasks().stream().anyMatch(tarefa -> tarefa.isActive() && tarefa.getAllocatedUser() != null && tarefa.getAllocatedUser().getCod().equals(codPessoa)); } /** Retorna a lista de todas as tarefas ordenadas da mais antiga para a mais nova. */ @Nonnull public List<TaskInstance> getTasksOlderFirst() { return getTasksOlderFirstAsStream().collect(Collectors.toList()); } /** Retorna a lista de todas as tarefas ordenadas da mais antiga para a mais nova. */ @Nonnull public Stream<TaskInstance> getTasksOlderFirstAsStream() { IEntityProcessInstance demanda = getEntity(); return demanda.getTasks().stream().map(this::getTaskInstance); } /** Retorna a lista de todas as tarefas ordenadas da mais nova para a mais antiga. */ public Stream<TaskInstance> getTasksNewerFirstAsStream() { IEntityProcessInstance demanda = getEntity(); return Lists.reverse(demanda.getTasks()).stream().map(this::getTaskInstance); } public Stream<TaskInstance> getTasksNewerFirstAsStream(ITaskDefinition... tasksTypes) { return getTasksNewerFirstAsStream().filter(TaskPredicates.simpleTaskType(tasksTypes)); } public Stream<TaskInstance> getTasksNewerFirstAsStream(List<ITaskDefinition> tasksTypes) { return getTasksNewerFirstAsStream().filter(TaskPredicates.simpleTaskType(tasksTypes)); } /** * Retorna a mais nova tarefa que atende a condio informada. * @param condicao a condio informada. */ @Nonnull public Optional<TaskInstance> getTaskNewer(@Nonnull Predicate<TaskInstance> condicao) { Objects.requireNonNull(condicao); List<? extends IEntityTaskInstance> lista = getEntity().getTasks(); for (int i = lista.size() - 1; i != -1; i--) { TaskInstance task = getTaskInstance(lista.get(i)); if (condicao.test(task)) { return Optional.of(task); } } return Optional.empty(); } /** Retorna a tarefa atual (tarefa ativa). */ @Nonnull public Optional<TaskInstance> getCurrentTask() { return getTaskNewer(t -> t.isActive()); } /** Retorna a tarefa atual (tarefa ativa) ou dispara exception seno existir. */ @Nonnull public TaskInstance getCurrentTaskOrException() { return getCurrentTask().orElseThrow(() -> new SingularFlowException( createErrorMsg("No h tarefa atual para essa instancia de processo"), this)); } /** * Retorna a mais nova tarefa encerrada ou ativa. */ @Nonnull public Optional<TaskInstance> getTaskNewer() { return getTaskNewer(t -> true); } /** Retorna a mais nova tarefa encerrada ou ativa. */ @Nonnull public TaskInstance getLatestTaskOrException() { return getTaskNewer().orElseThrow( () -> new SingularFlowException(createErrorMsg("No h nenhuma tarefa no processo"), this)); } /** * Encontra a mais nova tarefa encerrada ou ativa com a sigla da referncia. * @param taskRef a referncia. */ @Nonnull public Optional<TaskInstance> getTaskNewer(@Nonnull ITaskDefinition taskRef) { return getTaskNewer(TaskPredicates.simpleTaskType(taskRef)); } /** * Encontra a mais nova tarefa encerrada ou ativa do tipo informado. * @param tipo o tipo informado. */ @Nonnull public Optional<TaskInstance> getTaskNewer(@Nonnull STask<?> tipo) { return getTaskNewer(TaskPredicates.simpleTaskType(tipo)); } /** * Encontra a mais nova tarefa encerrada e com a mesma sigla da referncia. * @param taskRef a referncia. */ @Nonnull public Optional<TaskInstance> getFinishedTask(@Nonnull ITaskDefinition taskRef) { return getTaskNewer(TaskPredicates.simpleFinished().and(TaskPredicates.simpleTaskType(taskRef))); } /** * Encontra a mais nova tarefa encerrada e com a mesma sigla do tipo. * @param tipo o tipo. */ @Nonnull public Optional<TaskInstance> getFinishedTask(@Nonnull STask<?> tipo) { return getTaskNewer(TaskPredicates.simpleFinished().and(TaskPredicates.simpleTaskType(tipo))); } protected IPersistenceService<IEntityCategory, IEntityProcessDefinition, IEntityProcessVersion, IEntityProcessInstance, IEntityTaskInstance, IEntityTaskDefinition, IEntityTaskVersion, IEntityVariableInstance, IEntityRoleDefinition, IEntityRoleInstance> getPersistenceService() { return getProcessDefinition().getPersistenceService(); } /** * Configura o contexto de execuo. * @param execucaoTask o novo contexto de execuo. */ final void setExecutionContext(@Nullable ExecutionContext execucaoTask) { if (this.executionContext != null && execucaoTask != null) { throw new SingularFlowException( createErrorMsg("A instancia j est com um tarefa em processo de execuo"), this); } this.executionContext = execucaoTask; } }