
org.opensingular.requirement.module.service.RequirementService Maven / Gradle / Ivy
/*
* 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.requirement.module.service;
import org.apache.commons.collections.CollectionUtils;
import org.apache.wicket.Application;
import org.opensingular.flow.core.Flow;
import org.opensingular.flow.core.FlowDefinition;
import org.opensingular.flow.core.FlowInstance;
import org.opensingular.flow.core.ITransitionListener;
import org.opensingular.flow.core.STask;
import org.opensingular.flow.core.STransition;
import org.opensingular.flow.core.TaskInstance;
import org.opensingular.flow.core.TransitionCall;
import org.opensingular.flow.persistence.entity.Actor;
import org.opensingular.flow.persistence.entity.FlowInstanceEntity;
import org.opensingular.flow.persistence.entity.TaskInstanceEntity;
import org.opensingular.form.SFormUtil;
import org.opensingular.form.SIComposite;
import org.opensingular.form.SInstance;
import org.opensingular.form.SType;
import org.opensingular.form.persistence.FormKey;
import org.opensingular.form.persistence.entity.FormAnnotationEntity;
import org.opensingular.form.persistence.entity.FormEntity;
import org.opensingular.form.persistence.entity.FormTypeEntity;
import org.opensingular.form.persistence.entity.FormVersionEntity;
import org.opensingular.form.service.FormTypeService;
import org.opensingular.form.spring.UserDetailsProvider;
import org.opensingular.lib.commons.base.SingularException;
import org.opensingular.lib.commons.context.spring.SpringServiceRegistry;
import org.opensingular.lib.commons.util.FormatUtil;
import org.opensingular.lib.commons.util.Loggable;
import org.opensingular.lib.support.persistence.entity.BaseEntity;
import org.opensingular.lib.support.spring.util.ApplicationContextProvider;
import org.opensingular.requirement.module.RequirementDefinition;
import org.opensingular.requirement.module.RequirementSendInterceptor;
import org.opensingular.requirement.module.connector.ModuleService;
import org.opensingular.requirement.module.exception.SingularRequirementException;
import org.opensingular.requirement.module.exception.SingularServerException;
import org.opensingular.requirement.module.flow.RequirementTransitionContext;
import org.opensingular.requirement.module.flow.RequirementTransitionListener;
import org.opensingular.requirement.module.flow.builder.RequirementFlowDefinition;
import org.opensingular.requirement.module.form.SingularServerSpringTypeLoader;
import org.opensingular.requirement.module.persistence.dao.flow.ActorDAO;
import org.opensingular.requirement.module.persistence.dao.flow.TaskInstanceDAO;
import org.opensingular.requirement.module.persistence.dao.form.ApplicantDAO;
import org.opensingular.requirement.module.persistence.dao.form.RequirementContentHistoryDAO;
import org.opensingular.requirement.module.persistence.dao.form.RequirementDAO;
import org.opensingular.requirement.module.persistence.dao.form.RequirementDefinitionDAO;
import org.opensingular.requirement.module.persistence.dto.RequirementHistoryDTO;
import org.opensingular.requirement.module.persistence.entity.enums.PersonType;
import org.opensingular.requirement.module.persistence.entity.form.ApplicantEntity;
import org.opensingular.requirement.module.persistence.entity.form.FormRequirementEntity;
import org.opensingular.requirement.module.persistence.entity.form.FormVersionHistoryEntity;
import org.opensingular.requirement.module.persistence.entity.form.RequirementApplicant;
import org.opensingular.requirement.module.persistence.entity.form.RequirementContentHistoryEntity;
import org.opensingular.requirement.module.persistence.entity.form.RequirementDefinitionEntity;
import org.opensingular.requirement.module.persistence.entity.form.RequirementEntity;
import org.opensingular.requirement.module.persistence.filter.BoxFilter;
import org.opensingular.requirement.module.persistence.query.RequirementSearchExtender;
import org.opensingular.requirement.module.service.dto.RequirementSubmissionResponse;
import org.opensingular.requirement.module.spring.security.AuthorizationService;
import org.opensingular.requirement.module.spring.security.RequirementAuthMetadataDTO;
import org.opensingular.requirement.module.spring.security.SingularPermission;
import org.opensingular.requirement.module.spring.security.SingularRequirementUserDetails;
import org.opensingular.requirement.module.wicket.SingularSession;
import org.springframework.core.ResolvableType;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import static org.opensingular.flow.core.TaskInstance.TASK_VISUALIZATION;
@Transactional
public abstract class RequirementService implements Loggable {
@Inject
protected RequirementDAO requirementDAO;
@Inject
protected TaskInstanceDAO taskInstanceDAO;
@Inject
protected ApplicantDAO applicantDAO;
@Inject
protected AuthorizationService authorizationService;
@Inject
protected ActorDAO actorDAO;
@Inject
private RequirementContentHistoryDAO requirementContentHistoryDAO;
@Inject
private FormRequirementService formRequirementService;
@Inject
private RequirementDefinitionDAO requirementDefinitionDAO;
@Inject
private UserDetailsProvider singularUserDetails;
@Inject
private FormTypeService formTypeService;
@Inject
private SingularServerSpringTypeLoader singularServerSpringTypeLoader;
@Inject
private ModuleService moduleService;
@Inject
private SpringServiceRegistry springServiceRegistry;
/**
* FOR INTERNAL USE ONLY,
* MUST NOT BE EXPOSED BY SUBCLASSES
*
* @return
*/
protected SingularRequirementUserDetails getSingularUserDetails() {
return singularUserDetails.getTyped();
}
/**
* Recupera a petição associada ao fluxo informado ou dispara exception senão encontrar.
*/
@Deprecated
@Nonnull
private RI getRequirementInstance(@Nonnull RequirementEntity requirementEntity) {
Objects.requireNonNull(requirementEntity);
return loadRequirementInstance(requirementEntity.getCod());
}
/**
* Recupera a petição associada ao fluxo informado ou dispara exception senão encontrar.
*/
@Nonnull
public RI getRequirementInstance(@Nonnull FlowInstance flowInstance) {
Objects.requireNonNull(flowInstance);
return getRequirementInstance(getRequirementByFlowCod(flowInstance.getEntityCod()));
}
public > RD lookupRequirementDefinitionForRequirementId(Long requirementId) {
String key = getRequirementDefinitionByRequirementId(requirementId).getKey();
return lookupRequirementDefinition(key);
}
public > RD lookupRequirementDefinition(String requirementDefinitionKey) {
String[] definitions = ApplicationContextProvider.get().getBeanNamesForType(ResolvableType.forClass(RequirementDefinition.class));
for (String definitionName : definitions) {
RequirementDefinition> definition = (RequirementDefinition>) ApplicationContextProvider.get().getBean(definitionName);
if (definition.getKey().equals(requirementDefinitionKey)) {
return (RD) definition;
}
}
throw new SingularRequirementException(String.format("Could not corresponding definition for definition key %s", requirementDefinitionKey));
}
public RI loadRequirementInstance(Long requirementId) {
return (RI) lookupRequirementDefinitionForRequirementId(requirementId).loadRequirement(requirementId);
}
/**
* Retorna o serviço de formulários da petição.
*/
@Nonnull
protected FormRequirementService getFormRequirementService() {
return Objects.requireNonNull(formRequirementService);
}
/**
* Find applicant or create a new one
*/
public ApplicantEntity getApplicant(String codSubmitterActor) {
ApplicantEntity p;
p = applicantDAO.findApplicantByExternalId(codSubmitterActor);
if (p == null) {
Optional actorOpt = findActor(codSubmitterActor);
if (actorOpt.isPresent()) {
Actor actor = actorOpt.get();
p = new ApplicantEntity();
p.setIdPessoa(codSubmitterActor);
p.setName(actor.getNome());
p.setPersonType(PersonType.FISICA);
applicantDAO.save(p);
} else {
getLogger().error(" The applicant (current logged user, {}) could not be identified ", SingularRequirementUserDetails.class.getSimpleName());
}
}
return p;
}
/**
* Procura a petição com o código informado.
*/
@Nonnull
private Optional findRequirementByCod(@Nonnull Long cod) {
Objects.requireNonNull(cod);
return requirementDAO.find(cod);
}
/**
* Procura a petição com o código informado.
*/
@Nonnull
public Optional findRequirementEntity(@Nonnull Long cod) {
Objects.requireNonNull(cod);
return requirementDAO.find(cod);
}
/**
* Recupera a petição com o código informado ou dispara Exception senão encontrar.
*/
@Nonnull
@Deprecated
public RequirementEntity getRequirementByCod(@Nonnull Long cod) {
return findRequirementByCod(cod).orElseThrow(
() -> SingularServerException.rethrow("Não foi encontrada a petição de cod=" + cod));
}
/**
* Recupera a petição com o código informado ou dispara Exception senão encontrar.
*/
@Nonnull
public RequirementEntity getRequirementEntity(@Nonnull Long cod) {
return findRequirementEntity(cod).orElseThrow(
() -> SingularServerException.rethrow("Não foi encontrada a petição de cod=" + cod));
}
/**
* Recupera a petição associado a código de fluxo informado ou dispara exception senão encontrar.
*/
@Nonnull
public RequirementEntity getRequirementByFlowCod(@Nonnull Integer cod) {
Objects.requireNonNull(cod);
return requirementDAO.findByFlowCodOrException(cod);
}
public void deleteRequirement(@Nonnull Long idRequirement) {
requirementDAO.find(idRequirement).ifPresent(re -> requirementDAO.delete(re));
}
@Nonnull
public FormKey saveOrUpdate(@Nonnull RI requirement, @Nonnull SInstance instance, boolean mainForm) {
Objects.requireNonNull(requirement);
Objects.requireNonNull(instance);
updateRequirementDescription(instance, requirement);
requirementDAO.saveOrUpdate(requirement.getEntity());
if (requirement.getApplicant() != null) {
applicantDAO.saveOrUpdate((BaseEntity) requirement.getApplicant());
}
return formRequirementService.saveFormRequirement(requirement, instance, mainForm);
}
public void saveRequirementHistory(RI requirement, TaskInstance taskInstance, List newEntities) {
FormEntity formEntity = requirement.getEntity().getMainForm();
getLogger().info("Atualizando histórico da petição.");
final RequirementContentHistoryEntity contentHistoryEntity = new RequirementContentHistoryEntity();
contentHistoryEntity.setRequirementEntity(requirement.getEntity());
if (taskInstance != null) {
Actor actor = getActorOfAction(taskInstance);
contentHistoryEntity.setActor(actor);
contentHistoryEntity.setTaskInstanceEntity(taskInstance.getEntityTaskInstance());
}
if (CollectionUtils.isNotEmpty(formEntity.getCurrentFormVersionEntity().getFormAnnotations())) {
contentHistoryEntity.setFormAnnotationsVersions(formEntity.getCurrentFormVersionEntity().getFormAnnotations().stream().map(FormAnnotationEntity::getAnnotationCurrentVersion).collect(Collectors.toList()));
}
contentHistoryEntity.setApplicantEntity((ApplicantEntity) requirement.getApplicant());
contentHistoryEntity.setHistoryDate(new Date());
requirementContentHistoryDAO.saveOrUpdate(contentHistoryEntity);
contentHistoryEntity.setFormVersionHistoryEntities(
requirement.getEntity()
.getFormRequirementEntities()
.stream()
.filter(fpe -> newEntities.contains(fpe.getForm()))
.map(f -> formRequirementService.createFormVersionHistory(contentHistoryEntity, f))
.collect(Collectors.toList())
);
}
public void saveRequirementHistory(RI requirement, List newEntities) {
saveRequirementHistory(requirement, null, newEntities);
}
/**
* This method is responsible for get the user responsible for the action.
* First will try to get the authenticated user, if doesn't have the user will be the same of the allocated.
*
* @param taskInstance The task instance.
* @return Return the Actor.
*/
private Actor getActorOfAction(TaskInstance taskInstance) {
return Application.exists() && SingularSession.exists() && SingularSession.get().isAuthtenticated()
? (Actor) RequirementUtil.findUserOrException(SingularSession.get().getUsername())
: (Actor) taskInstance.getAllocatedUser();
}
/**
* Executa a transição informada, consolidando todos os rascunhos, este metodo não salva a petição
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public void executeTransition(@Nonnull String transitionName,
@Nonnull RI requirement,
@Nonnull List flowVariables,
@Nonnull List transitionVariables) {
try {
FlowInstance flowInstance = requirement.getFlowInstance();
RequirementTransitionContext requirementTransitionContext = new RequirementTransitionContext(requirement,
transitionName, flowVariables, transitionVariables);
STransition transition = flowInstance.getCurrentTaskOrException().findTransition(transitionName);
notifyBeforeConsolidateDrafts(transition, requirementTransitionContext);
List formEntities = formRequirementService.consolidateDrafts(requirement);
transition.notifyBeforeTransition(requirementTransitionContext);
for (Variable v : flowVariables) {
flowInstance.getVariables().addValueString(v.getKey(), v.getValue());
}
TransitionCall transitionCall = flowInstance.prepareTransition(transitionName);
for (Variable v : transitionVariables) {
transitionCall.addValueString(v.getKey(), v.getValue());
}
transitionCall.go();
TaskInstance taskInstance = requirement.getFlowInstance().getTasksNewerFirstAsStream()
.filter(i -> i.isAtTask(transition.getOrigin().getAbbreviation()) && i.isFinished() && !i.getFlowTaskOrException().isEnd())
.findFirst()
.orElse(null);
saveRequirementHistory(requirement, taskInstance, formEntities);
} catch (
SingularException e) {
getLogger().error(e.getMessage(), e);
throw e;
} catch (
Exception e) {
getLogger().error(e.getMessage(), e);
throw SingularServerException.rethrow(e.getMessage(), e);
}
}
protected void notifyBeforeConsolidateDrafts(STransition transition, RequirementTransitionContext requirementTransitionContext) {
List transitionListeners = transition.getTransitionListeners();
for (ITransitionListener transitionListener : transitionListeners) {
if (transitionListener instanceof RequirementTransitionListener) {
RequirementTransitionListener requirementTransitionListener = (RequirementTransitionListener) transitionListener;
springServiceRegistry.lookupSingularInjector().inject(requirementTransitionListener);
requirementTransitionListener.beforeConsolidateDrafts(requirementTransitionContext);
}
}
}
public List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy