119 lines
3.9 KiB
Java
119 lines
3.9 KiB
Java
package eu.dnetlib.manager.wf.workflows.graph;
|
|
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.function.Function;
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.context.expression.MapAccessor;
|
|
import org.springframework.core.env.Environment;
|
|
import org.springframework.expression.ExpressionParser;
|
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import com.google.common.collect.Sets;
|
|
|
|
import eu.dnetlib.errors.WorkflowManagerException;
|
|
import eu.dnetlib.manager.wf.model.WorkflowTemplate;
|
|
import eu.dnetlib.manager.wf.workflows.procs.Env;
|
|
import eu.dnetlib.manager.wf.workflows.util.NodeHelper;
|
|
|
|
@Service
|
|
public class GraphLoader {
|
|
|
|
@Autowired
|
|
private NodeHelper nodeHelper;
|
|
|
|
@Autowired
|
|
private Environment environment;
|
|
|
|
public Graph loadGraph(final WorkflowTemplate wfTemplate, final Map<String, String> globalParams)
|
|
throws WorkflowManagerException {
|
|
final Graph graph = new Graph();
|
|
|
|
for (final WorkflowTemplate.Node node : wfTemplate.getGraph()) {
|
|
final String nodeName = node.getName();
|
|
final String nodeType = node.getType();
|
|
final boolean isStart = node.isStart();
|
|
final boolean isJoin = node.isJoin();
|
|
|
|
final Map<String, Object> params = node.calculateInitialParams(globalParams, environment);
|
|
final Map<String, String> envParams = node.findEnvParams();
|
|
|
|
if (isStart) {
|
|
graph.addNode(GraphNode.newStartNode(nodeName, nodeType, params, envParams));
|
|
} else if (isJoin) {
|
|
graph.addNode(GraphNode.newJoinNode(nodeName, nodeType, params, envParams));
|
|
} else {
|
|
graph.addNode(GraphNode.newNode(nodeName, nodeType, params, envParams));
|
|
}
|
|
|
|
if (node.getArcs() != null) {
|
|
for (final WorkflowTemplate.Arc a : node.getArcs()) {
|
|
final String to = a.getTo();
|
|
final Function<Env, Boolean> condFunction = generateFunction(a.getCondition());
|
|
graph.addArc(new Arc(nodeName, to, condFunction));
|
|
}
|
|
}
|
|
|
|
graph.addNode(GraphNode.newSuccessNode());
|
|
}
|
|
|
|
checkValidity(graph);
|
|
|
|
return graph;
|
|
}
|
|
|
|
private Function<Env, Boolean> generateFunction(final String condition) {
|
|
if (StringUtils.isBlank(condition)) {
|
|
return (env) -> true;
|
|
} else {
|
|
return env -> {
|
|
final ExpressionParser parser = new SpelExpressionParser();
|
|
|
|
final StandardEvaluationContext context = new StandardEvaluationContext(env.getAttributes());
|
|
context.addPropertyAccessor(new MapAccessor());
|
|
|
|
return parser.parseExpression(condition).getValue(context, Boolean.class);
|
|
};
|
|
}
|
|
}
|
|
|
|
private void checkValidity(final Graph graph) throws WorkflowManagerException {
|
|
|
|
final Set<String> nodesFromArcs = new HashSet<>();
|
|
|
|
boolean foundSuccess = false;
|
|
boolean foundStart = false;
|
|
|
|
for (final Arc arc : graph.getArcs()) {
|
|
if (StringUtils.isBlank(arc.getFrom()) || StringUtils.isBlank(arc.getFrom())) {
|
|
throw new WorkflowManagerException("Invalid arc: missing from e/o to");
|
|
}
|
|
if (StringUtils.equals(arc.getTo(), GraphNode.SUCCESS_NODE)) {
|
|
foundSuccess = true;
|
|
}
|
|
nodesFromArcs.add(arc.getFrom());
|
|
nodesFromArcs.add(arc.getTo());
|
|
}
|
|
|
|
if (!foundSuccess) { throw new WorkflowManagerException("Arc to success not found"); }
|
|
|
|
final Set<String> diff = Sets.symmetricDifference(graph.nodeNames(), nodesFromArcs);
|
|
if (!diff.isEmpty()) { throw new WorkflowManagerException("Missing or invalid nodes in arcs: " + diff); }
|
|
|
|
for (final GraphNode n : graph.nodes()) {
|
|
if (StringUtils.isBlank(n.getName())) { throw new WorkflowManagerException("Invalid node: missing name"); }
|
|
if (n.isStart()) {
|
|
foundStart = true;
|
|
}
|
|
if (!this.nodeHelper.isValid(n)) { throw new WorkflowManagerException("Invalid node type: " + n.getType()); }
|
|
}
|
|
if (!foundStart) { throw new WorkflowManagerException("Start node not found"); }
|
|
}
|
|
|
|
}
|