package com.constellio.model.services.workflows.config;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom2.Document;
import com.constellio.data.dao.managers.StatefulService;
import com.constellio.data.dao.managers.config.ConfigManager;
import com.constellio.data.dao.managers.config.DocumentAlteration;
import com.constellio.model.entities.workflows.definitions.WorkflowConfiguration;
import com.constellio.model.entities.workflows.definitions.WorkflowDefinition;
import com.constellio.model.entities.workflows.trigger.Trigger;
import com.constellio.model.entities.workflows.trigger.TriggerType;
import com.constellio.model.entities.workflows.trigger.TriggeredWorkflowDefinition;
import com.constellio.model.services.collections.CollectionsListManager;
import com.constellio.model.services.workflows.bpmn.WorkflowBPMNDefinitionsService;
import com.constellio.model.services.workflows.config.WorkflowsConfigManagerRuntimeException.WorkflowsConfigManagerRuntimeException_InvalidWorkflowConfiguration;
import com.constellio.model.services.workflows.config.WorkflowsConfigManagerRuntimeException.WorkflowsConfigManagerRuntimeException_NoWorkflowConfigurationForThisCollection;
import com.constellio.model.services.workflows.config.WorkflowsConfigManagerRuntimeException.WorkflowsConfigManagerRuntimeException_WorkflowConfigurationAlreadyExists;
import com.constellio.model.services.workflows.config.xml.WorkflowsConfigReader;
import com.constellio.model.services.workflows.config.xml.WorkflowsConfigWriter;
import com.constellio.model.utils.OneXMLConfigPerCollectionManager;
import com.constellio.model.utils.OneXMLConfigPerCollectionManagerListener;
import com.constellio.model.utils.XMLConfigReader;
public class WorkflowsConfigManager
implements StatefulService, OneXMLConfigPerCollectionManagerListener<List<WorkflowConfiguration>> {
private static String WORKFLOWS_CONFIG = "/workflows/config.xml";
WorkflowBPMNDefinitionsService workflowBPMNDefinitionsService;
private OneXMLConfigPerCollectionManager<List<WorkflowConfiguration>> oneXMLConfigPerCollectionManager;
private Map<String, WorkflowDefinition> workflowDefinitions;
private ConfigManager configManager;
private CollectionsListManager collectionsListManager;
public WorkflowsConfigManager(ConfigManager configManager, CollectionsListManager collectionsListManager,
WorkflowBPMNDefinitionsService workflowBPMNDefinitionsService) {
this.configManager = configManager;
this.collectionsListManager = collectionsListManager;
this.workflowDefinitions = new HashMap<String, WorkflowDefinition>();
this.workflowBPMNDefinitionsService = workflowBPMNDefinitionsService;
}
@Override
public void initialize() {
this.oneXMLConfigPerCollectionManager = new OneXMLConfigPerCollectionManager<>(configManager, collectionsListManager,
WORKFLOWS_CONFIG, xmlConfigReader(), this);
}
public TriggeredWorkflowDefinition getWorkflowDefinitionForCreating(String collection, String schemaCode) {
return getTriggeredWorflowDefinitionFor(collection, schemaCode, TriggerType.RECORD_CREATED);
}
public TriggeredWorkflowDefinition getWorkflowDefinitionForModifying(String collection, String schemaCode) {
return getTriggeredWorflowDefinitionFor(collection, schemaCode, TriggerType.RECORD_MODIFIED);
}
public TriggeredWorkflowDefinition getWorkflowDefinitionForDeleting(String collection, String schemaCode) {
return getTriggeredWorflowDefinitionFor(collection, schemaCode, TriggerType.RECORD_DELETED);
}
public TriggeredWorkflowDefinition getWorkflowDefinitionForModifiedMetadata(String collection, String metadataCode) {
return getTriggeredWorflowDefinitionFor(collection, metadataCode, TriggerType.METADATA_MODIFIED);
}
public List<TriggeredWorkflowDefinition> getManualWorflowDefinitionsFor(String collection, String schemaCode) {
return getManualTriggeredWorflowDefinitionFor(collection, schemaCode);
}
public WorkflowDefinition getWorkflowDefinition(String collection, String id) {
return workflowDefinitions.get(collection + id);
}
public List<WorkflowConfiguration> getWorkflows(String collection) {
List<WorkflowConfiguration> workflowConfigurations = oneXMLConfigPerCollectionManager.get(collection);
if (workflowConfigurations != null) {
return workflowConfigurations;
} else {
throw new WorkflowsConfigManagerRuntimeException_NoWorkflowConfigurationForThisCollection(collection);
}
}
public void addUpdateWorkflow(WorkflowConfiguration workflowConfiguration) {
validateWorkflowConfiguration(workflowConfiguration);
boolean update = workflowDefinitions.containsKey(workflowConfiguration.getCollection() + workflowConfiguration.getId());
if (!update) {
validateThatNotExists(workflowConfiguration);
}
String collection = workflowConfiguration.getCollection();
if (!update) {
oneXMLConfigPerCollectionManager.updateXML(collection,
newAddWorkflowConfigurationDocumentAlteration(workflowConfiguration));
} else {
oneXMLConfigPerCollectionManager.updateXML(collection,
newUpdateWorkflowConfigurationDocumentAlteration(workflowConfiguration));
}
}
@Override
public void onValueModified(String collection, List<WorkflowConfiguration> workflowConfigurations) {
this.workflowDefinitions.clear();
for (WorkflowConfiguration workflowConfiguration : workflowConfigurations) {
WorkflowDefinition workflowDefinition = workflowBPMNDefinitionsService.getWorkflowDefinition(
workflowConfiguration.getBpmnFilename(), workflowConfiguration.getMapping(), workflowConfiguration);
workflowDefinitions.put(workflowConfiguration.getCollection() + workflowConfiguration.getId(), workflowDefinition);
}
}
private List<TriggeredWorkflowDefinition> getManualTriggeredWorflowDefinitionFor(String collection, String code) {
List<TriggeredWorkflowDefinition> triggeredWorkflowDefinitions = new ArrayList<>();
WorkflowDefinition workflowDefinition = null;
for (WorkflowConfiguration workflowConfiguration : getWorkflows(collection)) {
for (Trigger trigger : workflowConfiguration.getTriggers()) {
String schemaCode = trigger.getTriggeredSchemaCode();
if (trigger.getTriggerType() == TriggerType.MANUAL && schemaCode.equals(code)) {
workflowDefinition = workflowDefinitions.get(collection + workflowConfiguration.getId());
triggeredWorkflowDefinitions.add(new TriggeredWorkflowDefinition(workflowDefinition, trigger));
}
}
}
return triggeredWorkflowDefinitions;
}
private TriggeredWorkflowDefinition getTriggeredWorflowDefinitionFor(String collection, String code,
TriggerType triggerType) {
TriggeredWorkflowDefinition triggeredWorkflowDefinition = null;
for (WorkflowConfiguration workflowConfiguration : getWorkflows(collection)) {
for (Trigger trigger : workflowConfiguration.getTriggers()) {
String generiCode = trigger.getTriggeredSchemaCode();
if (triggerType == TriggerType.METADATA_MODIFIED && trigger.getTriggerType() == TriggerType.METADATA_MODIFIED) {
generiCode = trigger.getTriggeredMetadataCode();
}
if (trigger.getTriggerType() == triggerType && generiCode.equals(code)) {
WorkflowDefinition workflowDefinition = workflowDefinitions.get(collection + workflowConfiguration.getId());
triggeredWorkflowDefinition = new TriggeredWorkflowDefinition(workflowDefinition, trigger);
break;
}
}
}
return triggeredWorkflowDefinition;
}
private void validateWorkflowConfiguration(WorkflowConfiguration workflowConfiguration) {
for (Trigger trigger : workflowConfiguration.getTriggers()) {
if (trigger.getTriggerType() == TriggerType.METADATA_MODIFIED && trigger.getTriggeredMetadataCode() == null) {
throw new WorkflowsConfigManagerRuntimeException_InvalidWorkflowConfiguration();
}
}
}
private void validateThatNotExists(WorkflowConfiguration workflowConfiguration) {
for (WorkflowConfiguration retrievedWorkflowConfiguration : getWorkflows(workflowConfiguration.getCollection())) {
compareWorkflowsConfigurationTriggers(workflowConfiguration, retrievedWorkflowConfiguration);
}
}
private void compareWorkflowsConfigurationTriggers(WorkflowConfiguration workflowConfiguration,
WorkflowConfiguration retrievedWorkflowConfiguration) {
for (Trigger retrievedTrigger : retrievedWorkflowConfiguration.getTriggers()) {
if (retrievedTrigger.getTriggerType() == TriggerType.MANUAL) {
continue;
}
for (Trigger trigger : workflowConfiguration.getTriggers()) {
if (retrievedTrigger.getTriggerType() == trigger.getTriggerType() && retrievedTrigger.getTriggeredSchemaCode()
.equals(trigger.getTriggeredSchemaCode())) {
throw new WorkflowsConfigManagerRuntimeException_WorkflowConfigurationAlreadyExists(
retrievedTrigger.getTriggeredSchemaCode(), retrievedTrigger.getTriggerType().name());
}
}
}
}
private XMLConfigReader<List<WorkflowConfiguration>> xmlConfigReader() {
return new XMLConfigReader<List<WorkflowConfiguration>>() {
@Override
public List<WorkflowConfiguration> read(String collection, Document document) {
return newWorkflowsConfigManagerReader(document).getWorkflows();
}
};
}
private WorkflowsConfigReader newWorkflowsConfigManagerReader(Document document) {
return new WorkflowsConfigReader(document);
}
private WorkflowsConfigWriter newWorkflowsConfigManagerWriter(Document document) {
return new WorkflowsConfigWriter(document);
}
DocumentAlteration newAddWorkflowConfigurationDocumentAlteration(final WorkflowConfiguration workflowConfiguration) {
return new DocumentAlteration() {
@Override
public void alter(Document document) {
newWorkflowsConfigManagerWriter(document).add(workflowConfiguration);
}
};
}
DocumentAlteration newUpdateWorkflowConfigurationDocumentAlteration(final WorkflowConfiguration workflowConfiguration) {
return new DocumentAlteration() {
@Override
public void alter(Document document) {
newWorkflowsConfigManagerWriter(document).update(workflowConfiguration);
}
};
}
public void createCollectionWorkflows(String collection) {
DocumentAlteration createConfigAlteration = new DocumentAlteration() {
@Override
public void alter(Document document) {
WorkflowsConfigWriter writer = newWorkflowsConfigManagerWriter(document);
writer.createEmptyWorkflows();
}
};
oneXMLConfigPerCollectionManager.createCollectionFile(collection, createConfigAlteration);
}
@Override
public void close() {
}
}