/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.gui.workflow.editor.validator;
import java.util.ArrayList;
import java.util.List;
import de.rcenvironment.core.component.api.ComponentUtils;
import de.rcenvironment.core.component.validation.api.ComponentValidationMessage;
import de.rcenvironment.core.component.validation.api.ComponentValidationMessageStore;
import de.rcenvironment.core.component.workflow.model.api.Connection;
import de.rcenvironment.core.component.workflow.model.api.WorkflowDescription;
import de.rcenvironment.core.component.workflow.model.api.WorkflowNode;
import de.rcenvironment.core.gui.workflow.editor.commands.WorkflowNodeDeleteCommand;
/**
* Utility class with useful methods when validating a {@link WorkflowDescription}.
*
* @author Jascha Riedel
*/
public final class WorkflowDescriptionValidationUtils {
private static final ComponentValidationMessageStore MESSAGE_STORE = ComponentValidationMessageStore.getInstance();
private WorkflowDescriptionValidationUtils() {};
/**
* Validates the given {@link WorkflowDescription} and saves the messages in the {@link ComponentValidationMessageStore}.
*
* @param workflowDescription to validate.
* @param onWorkflowStart Boolean whether to active additional validation steps that are only necessary right before a workflow start.
* @param cleanWorkflow Cleaning the workflow in this context means, that all disabled and not available components are temporarily
* removed from the description. This is necessary since a component does not know anything about the state of the other
* components especially those connected which may be disabled or N/A.
*/
public static void validateWorkflowDescription(WorkflowDescription workflowDescription, boolean onWorkflowStart,
boolean cleanWorkflow) {
// This is necessary to make sure the true description isn't changed.
// Since the validation messages are linked to the componentId this is
// not a problem
WorkflowDescription workflowDescriptionClone = workflowDescription.clone();
if (cleanWorkflow) {
cleanWorkflowDescription(workflowDescription, workflowDescriptionClone);
}
validateWorkflowNodesAndUpdateValidState(workflowDescriptionClone.getWorkflowNodes(), onWorkflowStart);
// Should not be required anymore as Mantis Issue #0014726 is fixed; seeb_ol, November 23, 2016
// for (WorkflowNode n : workflowDescription.getWorkflowNodes()) {
// if (!MESSAGE_STORE.getMessagesByComponentId(n.getIdentifier()).isEmpty()) {
// n.setValid(false);
// }
// }
}
private static void cleanWorkflowDescription(WorkflowDescription workflowDescription,
WorkflowDescription workflowDescriptionClone) {
removeDisabledNodesAndMarkTargetsInvalid(workflowDescription, workflowDescriptionClone);
removeNotAvailableNodesAndMarkTargetsInvalid(workflowDescription, workflowDescriptionClone);
}
private static void removeDisabledNodesAndMarkTargetsInvalid(WorkflowDescription workflowDescription,
WorkflowDescription workflowDescriptionClone) {
List<WorkflowNode> nodesToDelete = new ArrayList<>();
for (WorkflowNode node : workflowDescriptionClone.getWorkflowNodes()) {
if (!node.isEnabled()) {
nodesToDelete.add(node);
setTargetNodesInvalid(workflowDescription, node);
}
}
new WorkflowNodeDeleteCommand(workflowDescriptionClone, nodesToDelete).execute();
}
private static void removeNotAvailableNodesAndMarkTargetsInvalid(WorkflowDescription workflowDescription,
WorkflowDescription workflowDescriptionClone) {
List<WorkflowNode> nodesToDelete = new ArrayList<>();
for (WorkflowNode node : workflowDescriptionClone.getWorkflowNodes()) {
if (node.getComponentDescription().getIdentifier().startsWith(ComponentUtils.MISSING_COMPONENT_PREFIX)) {
nodesToDelete.add(node);
setTargetNodesInvalid(workflowDescription, node);
}
}
new WorkflowNodeDeleteCommand(workflowDescriptionClone, nodesToDelete).execute();
}
private static void validateWorkflowNodesAndUpdateValidState(List<WorkflowNode> nodes, boolean onWorkflowStart) {
MESSAGE_STORE.emptyMessageStore(); // Delete all old messages
for (WorkflowNode node : nodes) {
// for the node fix above, this must be commented, but it's not the best for the performance
if (!node.isValid()) {
validateComponent(node, onWorkflowStart);
}
}
}
private static void setTargetNodesInvalid(WorkflowDescription workflowDescription, WorkflowNode node) {
for (Connection connection : workflowDescription.getConnections()) {
if (connection.getSourceNode().getIdentifier().equals(node.getIdentifier())) {
connection.getTargetNode().setValid(false);
}
}
}
/**
* Validates only one {@link WorkflowNode} and adds the validation messages to the current ones.
*
* @param workflowNode to validate
* @param onWorkflowStart if this validation is on the start of a workflow
*/
public static void validateComponent(WorkflowNode workflowNode, boolean onWorkflowStart) {
List<ComponentValidationMessage> messages;
messages = ValidationSupport.getInstance().validate(workflowNode.getComponentDescription(), onWorkflowStart);
MESSAGE_STORE.addValidationMessagesByComponentId(workflowNode.getIdentifier(), messages);
}
}