optimajet.workflow.ravendb.RavenDbProvider Maven / Gradle / Ivy
The newest version!
package optimajet.workflow.ravendb;
import com.fasterxml.jackson.core.type.TypeReference;
import com.mysema.query.types.expr.BooleanExpression;
import lombok.Getter;
import net.ravendb.client.IDocumentSession;
import net.ravendb.client.document.DocumentQueryCustomizationFactory;
import net.ravendb.client.document.DocumentStore;
import optimajet.workflow.core.DefiningParametersSerializer;
import optimajet.workflow.core.HashHelper;
import optimajet.workflow.core.fault.*;
import optimajet.workflow.core.model.*;
import optimajet.workflow.core.persistence.ErrorLevel;
import optimajet.workflow.core.persistence.ProcessStatus;
import optimajet.workflow.core.provider.WorkflowDocumentProvider;
import optimajet.workflow.core.runtime.ParametersSerializer;
import optimajet.workflow.core.runtime.ProcessHistoryItem;
import optimajet.workflow.core.runtime.TimerToExecute;
import optimajet.workflow.core.runtime.WorkflowRuntime;
import optimajet.workflow.core.util.CollectionUtil;
import optimajet.workflow.core.util.DocumentUtil;
import optimajet.workflow.core.util.JsonConvert;
import optimajet.workflow.core.util.StringUtil;
import org.w3c.dom.Document;
import java.util.*;
import static optimajet.workflow.core.util.CollectionUtil.select;
import static optimajet.workflow.core.util.CollectionUtil.singleOrDefault;
public class RavenDbProvider implements WorkflowDocumentProvider {
@Getter
private final DocumentStore documentStore;
private WorkflowRuntime runtime;
/**
* Constructor
*
* @param documentStore DocumentStore object
*/
public RavenDbProvider(DocumentStore documentStore) {
this.documentStore = documentStore;
this.documentStore.initialize();
}
@Override
public void init(WorkflowRuntime runtime) {
this.runtime = runtime;
}
@Override
public void initializeProcess(ProcessInstance processInstance) {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstance oldProcess = session.load(WorkflowProcessInstance.class, processInstance.getProcessId());
if (oldProcess != null) {
throw new ProcessAlreadyExistsException(processInstance.getProcessId());
}
WorkflowProcessInstance newProcess = new WorkflowProcessInstance();
newProcess.setId(processInstance.getProcessId());
newProcess.setSchemeId(processInstance.getSchemeId());
newProcess.setActivityName(processInstance.getProcessScheme().getInitialActivity().getName());
newProcess.setStateName(processInstance.getProcessScheme().getInitialActivity().getState());
newProcess.setRootProcessId(processInstance.getRootProcessId());
newProcess.setParentProcessId(processInstance.getParentProcessId());
newProcess.setPersistence(new ArrayList());
session.store(newProcess);
session.saveChanges();
}
}
@Override
public void bindProcessToNewScheme(ProcessInstance processInstance) throws ProcessNotFoundException {
bindProcessToNewScheme(processInstance, false);
}
@Override
public void bindProcessToNewScheme(ProcessInstance processInstance, boolean resetIsDeterminingParametersChanged) throws ProcessNotFoundException {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstance oldProcess = session.load(WorkflowProcessInstance.class, processInstance.getProcessId());
if (oldProcess == null) {
throw new ProcessNotFoundException(processInstance.getProcessId());
}
oldProcess.setSchemeId(processInstance.getSchemeId());
if (resetIsDeterminingParametersChanged) {
oldProcess.setDeterminingParametersChanged(false);
}
session.saveChanges();
}
}
@Override
public void fillProcessParameters(ProcessInstance processInstance) {
processInstance.addParameters(getProcessParameters(processInstance.getProcessId(), processInstance.getProcessScheme()));
}
@Override
public void fillPersistedProcessParameters(ProcessInstance processInstance) {
processInstance.addParameters(getPersistedProcessParameters(processInstance.getProcessId(), processInstance.getProcessScheme()));
}
@Override
public void fillSystemProcessParameters(ProcessInstance processInstance) {
processInstance.addParameters(getSystemProcessParameters(processInstance.getProcessId(), processInstance.getProcessScheme()));
}
@Override
public void savePersistenceParameters(ProcessInstance processInstance) {
List parametersToPersistList = new ArrayList<>();
for (ParameterDefinitionWithValue ptp : processInstance.getProcessParameters()) {
if (ptp.getPurpose() == ParameterPurpose.Persistence) {
ParameterDefinitionWithValue parameterDefinitionWithValue = new ParameterDefinitionWithValue();
parameterDefinitionWithValue.setParameterDefinition(ptp);
if (ptp.getType().equals(UnknownParameterType.class)) {
parameterDefinitionWithValue.setValue(ptp.getValue());
} else {
parameterDefinitionWithValue.setValue(ParametersSerializer.serialize(ptp.getValue()));
}
parametersToPersistList.add(parameterDefinitionWithValue);
}
}
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstance process = session.load(WorkflowProcessInstance.class, processInstance.getProcessId());
if (process != null && process.getPersistence() != null) {
List persistedParameters = process.getPersistence();
for (final ParameterDefinitionWithValue parameterDefinitionWithValue : parametersToPersistList) {
WorkflowProcessInstancePersistence persistence = singleOrDefault(persistedParameters,
new CollectionUtil.ItemCondition() {
@Override
public boolean check(WorkflowProcessInstancePersistence pp) {
return pp.getParameterName().equals(parameterDefinitionWithValue.getName());
}
});
if (persistence == null) {
if (parameterDefinitionWithValue.getValue() instanceof String) {
persistence = new WorkflowProcessInstancePersistence();
persistence.setParameterName(parameterDefinitionWithValue.getName());
persistence.setValue((String) parameterDefinitionWithValue.getValue());
process.getPersistence().add(persistence);
}
} else {
if (parameterDefinitionWithValue.getValue() instanceof String) {
persistence.setValue((String) parameterDefinitionWithValue.getValue());
} else {
process.getPersistence().remove(persistence);
}
}
}
session.store(process);
session.saveChanges();
}
}
}
@Override
public void setWorkflowInitialized(ProcessInstance processInstance) {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstanceStatus instanceStatus = session.load(WorkflowProcessInstanceStatus.class, processInstance.getProcessId());
if (instanceStatus == null) {
instanceStatus = new WorkflowProcessInstanceStatus();
instanceStatus.setId(processInstance.getProcessId());
instanceStatus.setLock(UUID.randomUUID());
instanceStatus.setStatus(ProcessStatus.Initialized.getId());
session.store(instanceStatus);
} else {
instanceStatus.setStatus(ProcessStatus.Initialized.getId());
session.store(instanceStatus);
}
session.saveChanges();
}
}
@Override
public void setWorkflowIdled(ProcessInstance processInstance) {
setCustomStatus(processInstance.getProcessId(), ProcessStatus.Idled);
}
@Override
public void setWorkflowRunning(ProcessInstance processInstance) {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstanceStatus instanceStatus = session.load(WorkflowProcessInstanceStatus.class, processInstance.getProcessId());
if (instanceStatus == null) {
throw new StatusNotDefinedException();
}
if (instanceStatus.getStatus() == ProcessStatus.Running.getId()) {
throw new ImpossibleToSetStatusException();
}
instanceStatus.setLock(UUID.randomUUID());
instanceStatus.setStatus(ProcessStatus.Running.getId());
session.store(instanceStatus);
session.saveChanges();
}
}
@Override
public void setWorkflowFinalized(ProcessInstance processInstance) {
setCustomStatus(processInstance.getProcessId(), ProcessStatus.Finalized);
}
@Override
public void setWorkflowTerminated(ProcessInstance processInstance, ErrorLevel level, String errorMessage) {
setCustomStatus(processInstance.getProcessId(), ProcessStatus.Terminated);
}
@Override
public void resetWorkflowRunning() {
do {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessInstanceStatus qwpis = QWorkflowProcessInstanceStatus.workflowProcessInstanceStatus;
List instanceStatusList = session.query(WorkflowProcessInstanceStatus.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qwpis.status.eq(ProcessStatus.Running.getId()))
.toList();
if (instanceStatusList.isEmpty()) {
break;
}
for (WorkflowProcessInstanceStatus workflowProcessInstanceStatus : instanceStatusList) {
workflowProcessInstanceStatus.setStatus(ProcessStatus.Idled.getId());
}
session.saveChanges();
}
} while (true);
}
@Override
public void updatePersistenceState(ProcessInstance processInstance, TransitionDefinition transition) {
ParameterDefinitionWithValue paramIdentityId = processInstance.getParameter(DefaultDefinitions.PARAMETER_IDENTITY_ID);
ParameterDefinitionWithValue paramImpIdentityId = processInstance.getParameter(DefaultDefinitions.PARAMETER_IMPERSONATED_IDENTITY_ID);
String identityId = paramIdentityId == null ? StringUtil.EMPTY : (String) paramIdentityId.getValue();
String impIdentityId = paramImpIdentityId == null ? identityId : (String) paramImpIdentityId.getValue();
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstance instance = session.load(WorkflowProcessInstance.class, processInstance.getProcessId());
if (instance != null) {
if (!StringUtil.isNullOrEmpty(transition.getTo().getState())) {
instance.setStateName(transition.getTo().getState());
}
instance.setActivityName(transition.getTo().getName());
instance.setPreviousActivity(transition.getFrom().getName());
if (!StringUtil.isNullOrEmpty(transition.getFrom().getState())) {
instance.setPreviousState(transition.getFrom().getState());
}
if (transition.getClassifier() == TransitionClassifier.Direct) {
instance.setPreviousActivityForDirect(transition.getFrom().getName());
if (!StringUtil.isNullOrEmpty(transition.getFrom().getState())) {
instance.setPreviousStateForDirect(transition.getFrom().getState());
}
} else if (transition.getClassifier() == TransitionClassifier.Reverse) {
instance.setPreviousActivityForReverse(transition.getFrom().getName());
if (!StringUtil.isNullOrEmpty(transition.getFrom().getState())) {
instance.setPreviousStateForReverse(transition.getFrom().getState());
}
}
instance.setParentProcessId(processInstance.getParentProcessId());
instance.setRootProcessId(processInstance.getRootProcessId());
}
WorkflowProcessTransitionHistory history = new WorkflowProcessTransitionHistory();
history.setActorIdentityId(impIdentityId);
history.setExecutorIdentityId(identityId);
history.setId(UUID.randomUUID());
history.setFinalised(transition.getTo().isFinalActivity());
history.setProcessId(processInstance.getProcessId());
history.setFromActivityName(transition.getFrom().getName());
history.setFromStateName(transition.getFrom().getState());
history.setToActivityName(transition.getTo().getName());
history.setToStateName(transition.getTo().getState());
history.setTransitionClassifier(transition.getClassifier().toString());
history.setTransitionTime(runtime.getRuntimeDateTimeNow());
history.setTriggerName(StringUtil.isNullOrEmpty(processInstance.getExecutedTimer()) ? processInstance.getCurrentCommand() : processInstance.getExecutedTimer());
session.store(history);
session.saveChanges();
}
}
@Override
public boolean isProcessExists(UUID processId) {
try (IDocumentSession session = documentStore.openSession()) {
return session.load(WorkflowProcessInstance.class, processId) != null;
}
}
@Override
public ProcessStatus getInstanceStatus(UUID processId) {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstanceStatus instance = session.load(WorkflowProcessInstanceStatus.class, processId);
if (instance == null) {
return ProcessStatus.NotFound;
}
return ProcessStatus.getById(instance.getStatus());
}
}
private void setCustomStatus(UUID processId, ProcessStatus status) {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstanceStatus instanceStatus = session.load(WorkflowProcessInstanceStatus.class, processId);
if (instanceStatus == null) {
throw new StatusNotDefinedException();
}
instanceStatus.setStatus(status.getId());
session.store(instanceStatus);
session.saveChanges();
}
}
private Collection getProcessParameters(UUID processId, ProcessDefinition processDefinition) {
List parameters = new ArrayList<>(processDefinition.getParameters().size());
parameters.addAll(getPersistedProcessParameters(processId, processDefinition));
parameters.addAll(getSystemProcessParameters(processId, processDefinition));
return parameters;
}
private Collection getSystemProcessParameters(UUID processId,
ProcessDefinition processDefinition) {
WorkflowProcessInstance processInstance = getProcessInstance(processId);
Collection systemParameters = CollectionUtil.where(processDefinition.getParameters(),
new CollectionUtil.ItemCondition() {
@Override
public boolean check(ParameterDefinition p) {
return p.getPurpose() == ParameterPurpose.System;
}
});
List parameters = new ArrayList<>(systemParameters.size());
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_PROCESS_ID, processId));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_PREVIOUS_STATE, processInstance.getPreviousState()));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_CURRENT_STATE, processInstance.getStateName()));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_PREVIOUS_STATE_FOR_DIRECT, processInstance.getPreviousStateForDirect()));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_PREVIOUS_STATE_FOR_REVERSE, processInstance.getPreviousStateForReverse()));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_PREVIOUS_ACTIVITY, processInstance.getPreviousActivity()));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_CURRENT_ACTIVITY, processInstance.getActivityName()));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_PREVIOUS_ACTIVITY_FOR_DIRECT, processInstance.getPreviousActivityForDirect()));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_PREVIOUS_ACTIVITY_FOR_REVERSE, processInstance.getPreviousActivityForReverse()));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_SCHEME_CODE, processDefinition.getName()));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_SCHEME_ID, processInstance.getSchemeId()));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_IS_PRE_EXECUTION, Boolean.FALSE));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_PARENT_PROCESS_ID, processInstance.getParentProcessId()));
parameters.add(createSystemParameter(systemParameters, DefaultDefinitions.PARAMETER_ROOT_PROCESS_ID, processInstance.getRootProcessId()));
return parameters;
}
private ParameterDefinitionWithValue createSystemParameter(Collection systemParameters,
final ParameterDefinition definition,
Object value) {
ParameterDefinition parameterDefinition = CollectionUtil.single(systemParameters,
new CollectionUtil.ItemCondition() {
@Override
public boolean check(ParameterDefinition sp) {
return sp.getName().equals(definition.getName());
}
});
return ParameterDefinitionWithValue.create(parameterDefinition, value);
}
private Collection getPersistedProcessParameters(UUID processId, ProcessDefinition processDefinition) {
Collection persistenceParameters = processDefinition.getPersistenceParameters();
List parameters = new ArrayList<>();
Collection persistedParameters;
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstance process = session.load(WorkflowProcessInstance.class, processId);
if (process != null && process.getPersistence() != null) {
persistedParameters = process.getPersistence();
} else {
return parameters;
}
}
for (final WorkflowProcessInstancePersistence persistedParameter : persistedParameters) {
ParameterDefinition parameterDefinition = CollectionUtil.firstOrDefault(persistenceParameters,
new CollectionUtil.ItemCondition() {
@Override
public boolean check(ParameterDefinition p) {
return p.getName().equals(persistedParameter.getParameterName());
}
});
if (parameterDefinition == null) {
parameterDefinition = ParameterDefinition.create(persistedParameter.getParameterName(),
UnknownParameterType.class, ParameterPurpose.Persistence);
parameters.add(ParameterDefinitionWithValue.create(parameterDefinition, persistedParameter.getValue()));
} else {
parameters.add(ParameterDefinitionWithValue.create(parameterDefinition,
ParametersSerializer.deserialize(persistedParameter.getValue(), parameterDefinition.getType())));
}
}
return parameters;
}
private WorkflowProcessInstance getProcessInstance(UUID processId) throws ProcessNotFoundException {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstance processInstance = session.load(WorkflowProcessInstance.class, processId);
if (processInstance == null) {
throw new ProcessNotFoundException(processId);
}
return processInstance;
}
}
@Override
public void deleteProcess(UUID[] processIds) {
for (UUID processId : processIds) {
deleteProcess(processId);
}
}
@Override
public void saveGlobalParameter(String type, String name, T value) {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowGlobalParameter qWorkflowGlobalParameter = QWorkflowGlobalParameter.workflowGlobalParameter;
WorkflowGlobalParameter parameter = session.query(WorkflowGlobalParameter.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowGlobalParameter.type.eq(type).and(
qWorkflowGlobalParameter.name.eq(name)))
.firstOrDefault();
if (parameter == null) {
parameter = new WorkflowGlobalParameter();
parameter.setId(UUID.randomUUID());
parameter.setType(type);
parameter.setName(name);
parameter.setValue(JsonConvert.serializeObject(value));
session.store(parameter);
} else {
parameter.setValue(JsonConvert.serializeObject(value));
}
session.saveChanges();
}
}
@Override
public T loadGlobalParameter(String type, String name, Class cls) {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowGlobalParameter qWorkflowGlobalParameter = QWorkflowGlobalParameter.workflowGlobalParameter;
WorkflowGlobalParameter parameter = session.query(WorkflowGlobalParameter.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowGlobalParameter.type.eq(type).and(
qWorkflowGlobalParameter.name.eq(name)))
.firstOrDefault();
if (parameter == null) {
return null;
}
return JsonConvert.deserializeObject(parameter.getValue(), cls);
}
}
@Override
public T loadGlobalParameter(String type, String name, TypeReference typeReference) {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowGlobalParameter qWorkflowGlobalParameter = QWorkflowGlobalParameter.workflowGlobalParameter;
WorkflowGlobalParameter parameter = session.query(WorkflowGlobalParameter.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowGlobalParameter.type.eq(type).and(
qWorkflowGlobalParameter.name.eq(name)))
.firstOrDefault();
if (parameter == null) {
return null;
}
return JsonConvert.deserializeTypeObject(parameter.getValue(), typeReference);
}
}
@Override
public Collection loadGlobalParameters(String type, final Class cls) {
Collection result = new ArrayList<>();
int skip = 0;
try (IDocumentSession session = documentStore.openSession()) {
do {
QWorkflowGlobalParameter qWorkflowGlobalParameter = QWorkflowGlobalParameter.workflowGlobalParameter;
List parameters = session.query(WorkflowGlobalParameter.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowGlobalParameter.type.eq(type))
.skip(skip)
.take(session.advanced().getMaxNumberOfRequestsPerSession())
.toList();
result.addAll(select(parameters, new CollectionUtil.ItemTransformer() {
@Override
public T transform(WorkflowGlobalParameter p) {
return JsonConvert.deserializeObject(p.getValue(), cls);
}
}));
if (parameters.isEmpty()) {
break;
}
skip += session.advanced().getMaxNumberOfRequestsPerSession();
} while (true);
}
return result;
}
@Override
public void deleteGlobalParameters(String type) {
deleteGlobalParameters(type, null);
}
@Override
public void deleteGlobalParameters(String type, String name) {
List globalParameterList;
do {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowGlobalParameter qWorkflowGlobalParameter = QWorkflowGlobalParameter.workflowGlobalParameter;
if (StringUtil.isNullOrEmpty(name)) {
globalParameterList = session.query(WorkflowGlobalParameter.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowGlobalParameter.type.eq(type))
.toList();
} else {
globalParameterList = session.query(WorkflowGlobalParameter.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowGlobalParameter.type.eq(type).and(
qWorkflowGlobalParameter.name.eq(name)))
.toList();
}
for (WorkflowGlobalParameter workflowGlobalParameter : globalParameterList) {
session.delete(workflowGlobalParameter);
}
session.saveChanges();
}
} while (!globalParameterList.isEmpty());
}
@Override
public void deleteProcess(UUID processId) {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstance workflowProcessInstance = session.load(WorkflowProcessInstance.class, processId);
if (workflowProcessInstance != null) {
session.delete(workflowProcessInstance);
}
WorkflowProcessInstanceStatus instanceStatus = session.load(WorkflowProcessInstanceStatus.class, processId);
if (instanceStatus != null) {
session.delete(instanceStatus);
session.saveChanges();
}
}
List transitionHistories;
do {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessTransitionHistory qwpth = QWorkflowProcessTransitionHistory.workflowProcessTransitionHistory;
transitionHistories = session.query(WorkflowProcessTransitionHistory.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qwpth.processId.eq(processId))
.toList();
for (WorkflowProcessTransitionHistory history : transitionHistories) {
session.delete(history);
}
session.saveChanges();
}
} while (!transitionHistories.isEmpty());
List timers;
do {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessTimer qWorkflowProcessTimer = QWorkflowProcessTimer.workflowProcessTimer;
timers = session.query(WorkflowProcessTimer.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessTimer.processId.eq(processId))
.toList();
for (WorkflowProcessTimer timer : timers) {
session.delete(timer);
}
session.saveChanges();
}
} while (!timers.isEmpty());
}
@Override
public void registerTimer(UUID processId, String name, Date nextExecutionDateTime, boolean notOverrideIfExists) {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessTimer qWorkflowProcessTimer = QWorkflowProcessTimer.workflowProcessTimer;
WorkflowProcessTimer timer = session.query(WorkflowProcessTimer.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessTimer.processId.eq(processId).and(
qWorkflowProcessTimer.name.eq(name)))
.firstOrDefault();
if (timer == null) {
timer = new WorkflowProcessTimer();
timer.setId(UUID.randomUUID());
timer.setName(name);
timer.setNextExecutionDateTime(nextExecutionDateTime);
timer.setProcessId(processId);
timer.setIgnore(false);
session.store(timer);
} else if (!notOverrideIfExists) {
timer.setNextExecutionDateTime(nextExecutionDateTime);
}
session.saveChanges();
}
}
@Override
public void clearTimers(UUID processId, Collection timersIgnoreList) {
List workflowProcessTimers;
do {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessTimer qWorkflowProcessTimer = QWorkflowProcessTimer.workflowProcessTimer;
workflowProcessTimers = session.query(WorkflowProcessTimer.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessTimer.processId.eq(processId)
.and(qWorkflowProcessTimer.name.notIn(timersIgnoreList)))
.toList();
for (WorkflowProcessTimer timer : workflowProcessTimers) {
session.delete(timer);
}
session.saveChanges();
}
} while (!workflowProcessTimers.isEmpty());
}
@Override
public void clearTimersIgnore() {
List workflowProcessTimers;
do {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessTimer qWorkflowProcessTimer = QWorkflowProcessTimer.workflowProcessTimer;
workflowProcessTimers = session.query(WorkflowProcessTimer.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessTimer.ignore.eq(Boolean.TRUE))
.toList();
for (WorkflowProcessTimer timer : workflowProcessTimers) {
timer.setIgnore(false);
}
session.saveChanges();
}
} while (!workflowProcessTimers.isEmpty());
}
@Override
public void clearTimerIgnore(UUID timerId) {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessTimer timer = session.load(WorkflowProcessTimer.class, timerId);
if (timer != null) {
timer.setIgnore(false);
session.saveChanges();
}
}
}
@Override
public void clearTimer(UUID timerId) {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessTimer timer = session.load(WorkflowProcessTimer.class, timerId);
if (timer != null) {
session.delete(timer);
session.saveChanges();
}
}
}
@Override
public Date getCloseExecutionDateTime() {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessTimer qWorkflowProcessTimer = QWorkflowProcessTimer.workflowProcessTimer;
WorkflowProcessTimer timer = session.query(WorkflowProcessTimer.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessTimer.ignore.eq(Boolean.FALSE))
.orderBy(qWorkflowProcessTimer.nextExecutionDateTime.asc())
.firstOrDefault();
if (timer == null) {
return null;
}
return timer.getNextExecutionDateTime();
}
}
@Override
public List getTimersToExecute() {
Date now = runtime.getRuntimeDateTimeNow();
List timers = new ArrayList<>();
List workflowProcessTimers;
do {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessTimer qWorkflowProcessTimer = QWorkflowProcessTimer.workflowProcessTimer;
workflowProcessTimers = session.query(WorkflowProcessTimer.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessTimer.ignore.eq(Boolean.FALSE).and(
qWorkflowProcessTimer.nextExecutionDateTime.loe(now)))
.toList();
for (WorkflowProcessTimer workflowProcessTimer : workflowProcessTimers) {
workflowProcessTimer.setIgnore(true);
}
timers.addAll(workflowProcessTimers);
session.saveChanges();
}
} while (!workflowProcessTimers.isEmpty());
Collection result = CollectionUtil.select(timers, new CollectionUtil.ItemTransformer() {
@Override
public TimerToExecute transform(WorkflowProcessTimer t) {
TimerToExecute timerToExecute = new TimerToExecute();
timerToExecute.setName(t.getName());
timerToExecute.setProcessId(t.getProcessId());
timerToExecute.setTimerId(t.getId());
return timerToExecute;
}
});
return new ArrayList<>(result);
}
@Override
public List getProcessHistory(UUID processId) {
List result = new ArrayList<>();
int skip = 0;
try (IDocumentSession session = documentStore.openSession()) {
do {
QWorkflowProcessTransitionHistory qWorkflowProcessTransitionHistory = QWorkflowProcessTransitionHistory.workflowProcessTransitionHistory;
List transitionHistories = session.query(WorkflowProcessTransitionHistory.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessTransitionHistory.processId.eq(processId))
.skip(skip)
.take(session.advanced().getMaxNumberOfRequestsPerSession())
.toList();
for (WorkflowProcessTransitionHistory item : transitionHistories) {
ProcessHistoryItem processHistoryItem = new ProcessHistoryItem();
processHistoryItem.setActorIdentityId(item.getActorIdentityId());
processHistoryItem.setExecutorIdentityId(item.getExecutorIdentityId());
processHistoryItem.setFromActivityName(item.getFromActivityName());
processHistoryItem.setFromStateName(item.getFromStateName());
processHistoryItem.setFinalised(item.isFinalised());
processHistoryItem.setProcessId(item.getProcessId());
processHistoryItem.setToActivityName(item.getToActivityName());
processHistoryItem.setToStateName(item.getToStateName());
processHistoryItem.setTransitionClassifier(TransitionClassifier.valueOf(item.getTransitionClassifier()));
processHistoryItem.setTransitionTime(item.getTransitionTime());
processHistoryItem.setTriggerName(item.getTriggerName());
result.add(processHistoryItem);
}
if (transitionHistories.isEmpty()) {
break;
}
skip += session.advanced().getMaxNumberOfRequestsPerSession();
} while (true);
}
return result;
}
@Override
public SchemeDefinition getProcessSchemeByProcessId(UUID processId) {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessInstance processInstance = session.load(WorkflowProcessInstance.class, processId);
if (processInstance == null) {
throw new ProcessNotFoundException(processId);
}
if (processInstance.getSchemeId() == null) {
throw new SchemeNotFoundException(processId, SchemeLocation.WorkflowProcessInstance);
}
SchemeDefinition schemeDefinition = getProcessSchemeBySchemeId(processInstance.getSchemeId());
schemeDefinition.setDeterminingParametersChanged(processInstance.isDeterminingParametersChanged());
return schemeDefinition;
}
}
@Override
public SchemeDefinition getProcessSchemeBySchemeId(UUID schemeId) {
try (IDocumentSession session = documentStore.openSession()) {
WorkflowProcessScheme processScheme = session.load(WorkflowProcessScheme.class, schemeId);
if (processScheme == null || StringUtil.isNullOrEmpty(processScheme.getScheme())) {
throw new SchemeNotFoundException(schemeId, SchemeLocation.WorkflowProcessScheme);
}
return convertToSchemeDefinition(processScheme);
}
}
@Override
public SchemeDefinition getProcessSchemeWithParameters(String schemeCode, String definingParameters,
UUID rootSchemeId, boolean ignoreObsolete) {
Collection processSchemes;
String hash = HashHelper.generateStringHash(definingParameters);
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessScheme qWorkflowProcessScheme = QWorkflowProcessScheme.workflowProcessScheme;
final BooleanExpression rootSchemeCondition = rootSchemeId == null
? qWorkflowProcessScheme.rootSchemeId.isNull()
: qWorkflowProcessScheme.rootSchemeId.eq(rootSchemeId);
if (ignoreObsolete) {
processSchemes = session.query(WorkflowProcessScheme.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessScheme.schemeCode.eq(schemeCode).and(
qWorkflowProcessScheme.definingParametersHash.eq(hash).and(
rootSchemeCondition.and(qWorkflowProcessScheme.obsolete.eq(Boolean.FALSE)))))
.toList();
} else {
processSchemes = session.query(WorkflowProcessScheme.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessScheme.schemeCode.eq(schemeCode).and(
qWorkflowProcessScheme.definingParametersHash.eq(hash).and(rootSchemeCondition)))
.toList();
}
}
if (processSchemes.isEmpty()) {
throw new SchemeNotFoundException(schemeCode, SchemeLocation.WorkflowProcessScheme, definingParameters);
}
if (processSchemes.size() == 1) {
WorkflowProcessScheme scheme = CollectionUtil.first(processSchemes);
return convertToSchemeDefinition(scheme);
}
for (WorkflowProcessScheme processScheme : processSchemes) {
if (processScheme.getDefiningParameters().equals(definingParameters)) {
return convertToSchemeDefinition(processScheme);
}
}
throw new SchemeNotFoundException(schemeCode, SchemeLocation.WorkflowProcessScheme, definingParameters);
}
@Override
public void setSchemeIsObsolete(String schemeCode, Map parameters) {
String definingParameters = DefiningParametersSerializer.serialize(parameters);
String definingParametersHash = HashHelper.generateStringHash(definingParameters);
do {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessScheme qWorkflowProcessScheme = QWorkflowProcessScheme.workflowProcessScheme;
List oldSchemes = session.query(WorkflowProcessScheme.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessScheme.schemeCode.eq(schemeCode).or(
qWorkflowProcessScheme.rootSchemeCode.eq(schemeCode)).and(
qWorkflowProcessScheme.obsolete.eq(Boolean.FALSE).and(
qWorkflowProcessScheme.definingParametersHash.eq(definingParametersHash))))
.toList();
if (oldSchemes.isEmpty()) {
break;
}
for (WorkflowProcessScheme scheme : oldSchemes) {
scheme.setObsolete(true);
}
session.saveChanges();
if (session.advanced().getNumberOfRequests() < session.advanced().getMaxNumberOfRequestsPerSession() - 2) {
break;
}
}
} while (true);
}
@Override
public void setSchemeIsObsolete(String schemeCode) {
do {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessScheme qWorkflowProcessScheme = QWorkflowProcessScheme.workflowProcessScheme;
List oldSchemes = session.query(WorkflowProcessScheme.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessScheme.schemeCode.eq(schemeCode).or(
qWorkflowProcessScheme.rootSchemeCode.eq(schemeCode)).and(
qWorkflowProcessScheme.obsolete.eq(Boolean.FALSE)
))
.toList();
if (oldSchemes.isEmpty()) {
break;
}
for (WorkflowProcessScheme scheme : oldSchemes) {
scheme.setObsolete(true);
}
session.saveChanges();
if (session.advanced().getNumberOfRequests() < session.advanced().getMaxNumberOfRequestsPerSession() - 2) {
break;
}
}
} while (true);
}
@Override
public void saveScheme(SchemeDefinition scheme) {
final String definingParameters = scheme.getDefiningParameters();
String definingParametersHash = HashHelper.generateStringHash(definingParameters);
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowProcessScheme qWorkflowProcessScheme = QWorkflowProcessScheme.workflowProcessScheme;
List oldSchemes = session.query(WorkflowProcessScheme.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.where(qWorkflowProcessScheme.definingParametersHash.eq(definingParametersHash).and(
qWorkflowProcessScheme.schemeCode.eq(scheme.getSchemeCode()).and(
qWorkflowProcessScheme.obsolete.eq(scheme.isObsolete()))))
.toList();
boolean any = CollectionUtil.any(oldSchemes, new CollectionUtil.ItemCondition() {
@Override
public boolean check(WorkflowProcessScheme oldScheme) {
return oldScheme.getDefiningParameters().equals(definingParameters);
}
});
if (any) {
throw new SchemeAlreadyExistsException(scheme.getSchemeCode(), SchemeLocation.WorkflowProcessScheme,
scheme.getDefiningParameters());
}
WorkflowProcessScheme newProcessScheme = new WorkflowProcessScheme();
newProcessScheme.setId(scheme.getId());
newProcessScheme.setDefiningParameters(definingParameters);
newProcessScheme.setDefiningParametersHash(definingParametersHash);
newProcessScheme.setScheme(DocumentUtil.serialize(scheme.getScheme()));
newProcessScheme.setSchemeCode(scheme.getSchemeCode());
newProcessScheme.setRootSchemeCode(scheme.getRootSchemeCode());
newProcessScheme.setRootSchemeId(scheme.getRootSchemeId());
newProcessScheme.setAllowedActivities(scheme.getAllowedActivities());
newProcessScheme.setStartingTransition(scheme.getStartingTransition());
newProcessScheme.setObsolete(scheme.isObsolete());
session.store(newProcessScheme);
session.saveChanges();
}
}
@Override
public void saveScheme(String schemaCode, String scheme) {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowScheme qWorkflowScheme = QWorkflowScheme.workflowScheme;
WorkflowScheme wfScheme = session.query(WorkflowScheme.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.firstOrDefault(qWorkflowScheme.code.eq(schemaCode));
if (wfScheme == null) {
wfScheme = new WorkflowScheme();
wfScheme.setId(schemaCode);
wfScheme.setCode(schemaCode);
wfScheme.setScheme(scheme);
session.store(wfScheme);
} else {
wfScheme.setScheme(scheme);
}
session.saveChanges();
}
}
@Override
public Document getScheme(String code) {
try (IDocumentSession session = documentStore.openSession()) {
QWorkflowScheme qWorkflowScheme = QWorkflowScheme.workflowScheme;
WorkflowScheme scheme = session.query(WorkflowScheme.class)
.customize(new DocumentQueryCustomizationFactory().waitForNonStaleResultsAsOfNow())
.firstOrDefault(qWorkflowScheme.code.eq(code));
if (scheme == null || StringUtil.isNullOrEmpty(scheme.getScheme())) {
throw new SchemeNotFoundException(code, SchemeLocation.WorkflowScheme);
}
return DocumentUtil.parse(scheme.getScheme());
}
}
@Override
public Document generate(String schemeCode, UUID schemeId, Map parameters) {
if (!parameters.isEmpty()) {
throw new IllegalArgumentException("Parameters not supported");
}
return getScheme(schemeCode);
}
private SchemeDefinition convertToSchemeDefinition(WorkflowProcessScheme workflowProcessScheme) {
return new SchemeDefinition<>(workflowProcessScheme.getId(), workflowProcessScheme.getRootSchemeId(),
workflowProcessScheme.getSchemeCode(), workflowProcessScheme.getRootSchemeCode(),
DocumentUtil.parse(workflowProcessScheme.getScheme()), workflowProcessScheme.isObsolete(), false,
workflowProcessScheme.getAllowedActivities(),
workflowProcessScheme.getStartingTransition(),
workflowProcessScheme.getDefiningParameters());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy