/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* Copyright (c) 2013, MPL CodeInside http://codeinside.ru
*/
package ru.codeinside.gses.activiti;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.IdentityService;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.form.StartFormHandler;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.deploy.DeploymentCache;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.variable.EntityManagerSession;
import ru.codeinside.adm.database.Bid;
import ru.codeinside.adm.database.BidStatus;
import ru.codeinside.adm.database.BidWorkers;
import ru.codeinside.adm.database.Directory;
import ru.codeinside.adm.database.Employee;
import ru.codeinside.adm.database.ExternalGlue;
import ru.codeinside.adm.database.InfoSystem;
import ru.codeinside.adm.database.Procedure;
import ru.codeinside.adm.database.ProcedureProcessDefinition;
import ru.codeinside.adm.database.Service;
import ru.codeinside.adm.database.SmevChain;
import ru.codeinside.gses.activiti.forms.CustomStartFormHandler;
import ru.codeinside.gses.activiti.forms.Signatures;
import ru.codeinside.gses.activiti.forms.SubmitFormDataCmd;
import ru.codeinside.gses.activiti.forms.api.definitions.FormDefinitionProvider;
import ru.codeinside.gses.activiti.forms.api.definitions.PropertyTree;
import ru.codeinside.gses.activiti.forms.api.duration.DurationPreference;
import ru.codeinside.gses.activiti.forms.api.duration.LazyCalendar;
import ru.codeinside.gses.service.BidID;
import ru.codeinside.gses.service.DeclarantService;
import ru.codeinside.gses.webui.form.DataAccumulator;
import ru.codeinside.gses.webui.form.ProcessInstanceAttachmentConverter;
import ru.codeinside.gses.webui.form.SignatureType;
import javax.persistence.EntityManager;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SubmitStartFormCommand implements Command<BidID>, Serializable {
private static final long serialVersionUID = 1L;
private final SmevChain smevChain;
private final String componentName;
private final String processDefinitionId;
private final Map<SignatureType, Signatures> signatures;
private final DataAccumulator accumulator;
private final Map<String, Object> properties;
private final String declarer;
private final String tag;
public SubmitStartFormCommand(
SmevChain smevChain, String componentName,
String processDefinitionId,
Map<String, Object> properties,
Map<SignatureType, Signatures> signatures,
String declarer, String tag,
DataAccumulator accumulator) {
this.smevChain = smevChain;
this.componentName = componentName;
this.processDefinitionId = processDefinitionId;
this.signatures = signatures;
this.accumulator = accumulator;
this.properties = new HashMap<String, Object>(properties);
this.declarer = declarer;
this.tag = tag == null ? "" : tag;
}
@Override
public BidID execute(CommandContext commandContext) {
identityService().setAuthenticatedUserId(smevChain == null ? declarer : null);
ProcessDefinitionEntity processDefinition = deploymentCache().findDeployedProcessDefinitionById(processDefinitionId);
if (processDefinition == null) {
throw new ActivitiException("No process definition found for id = '" + processDefinitionId + "'");
}
EntityManager em = entityManger(commandContext);
ProcedureProcessDefinition procedureDef = em.find(ProcedureProcessDefinition.class, processDefinitionId);
if (procedureDef == null) {
throw new ActivitiException("No procedure found for id = '" + processDefinitionId + "'");
}
addCustomProperties(em, procedureDef);
ExecutionEntity processInstance = processDefinition.createProcessInstance();
StartFormHandler startFormHandler = processDefinition.getStartFormHandler();
PropertyTree propertyTree = ((FormDefinitionProvider) startFormHandler).getPropertyTree();
new SubmitFormDataCmd(
propertyTree,
processInstance,
properties,
signatures,
new ProcessInstanceAttachmentConverter(processInstance.getProcessInstanceId()),
accumulator).execute(commandContext);
Bid bid = createBid(em, procedureDef, processInstance);
processInstance.start();
return new BidID(bid.getId(), Long.parseLong(bid.getProcessInstanceId()));
}
private Bid createBid(EntityManager em, ProcedureProcessDefinition procedureDef, ExecutionEntity processInstance) {
Employee employee = smevChain == null ? em.find(Employee.class, declarer) : null;
Bid bid = new Bid();
setExecutionDates(bid, processInstance);
bid.setTag(tag);
bid.setDeclarant(declarer == null ? "" : declarer);
bid.setStatus(BidStatus.New);
bid.setProcessInstanceId(processInstance.getProcessInstanceId());
bid.setEmployee(employee);
bid.setProcedureProcessDefinition(procedureDef);
if (procedureDef != null) {
Procedure procedure = procedureDef.getProcedure();
bid.setProcedure(procedure);
bid.setVersion(procedure.getVersion());
}
em.persist(bid);
if (smevChain != null) {
List<ExternalGlue> glues = em
.createQuery("select e from ExternalGlue e where e.requestIdRef=:ref", ExternalGlue.class)
.setParameter("ref", smevChain.originRequestIdRef).getResultList();
ExternalGlue externalGlue;
if (glues.isEmpty()) {
externalGlue = new ExternalGlue();
externalGlue.setName(componentName);
externalGlue.setRequestIdRef(smevChain.originRequestIdRef);
externalGlue.setId(bid.getId());
{
ru.codeinside.gws.api.InfoSystem senderSystem = smevChain.sender;
if (senderSystem != null) {
InfoSystem sender = em.find(InfoSystem.class, senderSystem.code);
if (sender == null) {
sender = new InfoSystem(senderSystem.code, senderSystem.name);
em.persist(sender);
}
externalGlue.setSender(sender);
}
ru.codeinside.gws.api.InfoSystem recipientSystem = smevChain.recipient;
if (recipientSystem != null) {
InfoSystem recipient = em.find(InfoSystem.class, recipientSystem.code);
if (recipient == null) {
recipient = new InfoSystem(recipientSystem.code, recipientSystem.name);
em.persist(recipient);
}
externalGlue.setRecipient(recipient);
}
}
{
ru.codeinside.gws.api.InfoSystem originSystem = smevChain.originator;
if (originSystem != null) {
InfoSystem origin = em.find(InfoSystem.class, originSystem.code);
if (origin == null) {
origin = new InfoSystem(originSystem.code, originSystem.name);
em.persist(origin);
}
externalGlue.setOrigin(origin);
}
}
em.persist(externalGlue);
} else {
externalGlue = glues.get(0);
}
bid.setGlue(externalGlue);
externalGlue.getBids().add(bid);
em.persist(bid);
em.persist(externalGlue);
}
if (employee != null) {
em.persist(new BidWorkers(bid, employee));
}
em.flush();
return bid;
}
void setExecutionDates(Bid bid, ExecutionEntity processInstance) {
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) processInstance.getProcessDefinition();
CustomStartFormHandler startFormHandler = (CustomStartFormHandler) processDefinition.getStartFormHandler();
DurationPreference durationPreference = startFormHandler.getPropertyTree().getDurationPreference();
durationPreference.initializeProcessDates(bid, new LazyCalendar());
}
private void addCustomProperties(EntityManager em, ProcedureProcessDefinition procedureDef) {
Procedure procedure = procedureDef.getProcedure();
Service service = procedure.getService();
properties.put(DeclarantService.VAR_PROCEDURE_TYPE_NAME, Integer.toString(procedure.getType().ordinal()));
properties.put(DeclarantService.VAR_PROCEDURE_ID, procedure.getId());
if (componentName == null) {
properties.put(DeclarantService.VAR_REQUESTER_LOGIN, declarer);
}
if (service != null) {
properties.put(DeclarantService.VAR_SERVICE_ID, Long.toString(service.getId()));
for (String dt : service.getDeclarantTypes()) {
Directory directory = em.find(Directory.class, DeclarantService.DECLARANT_TYPES);
final String val;
if (directory != null && directory.getValues().get(dt) != null) {
val = directory.getValues().get(dt);
} else {
val = dt;
}
properties.put(dt, val);
}
}
}
private ProcessEngineConfigurationImpl config() {
return Context.getProcessEngineConfiguration();
}
private DeploymentCache deploymentCache() {
return config().getDeploymentCache();
}
private IdentityService identityService() {
return config().getIdentityService();
}
private EntityManager entityManger(CommandContext commandContext) {
return commandContext.getSession(EntityManagerSession.class).getEntityManager();
}
}