181 lines
6.0 KiB
Java
181 lines
6.0 KiB
Java
package eu.dnetlib.manager.wf.workflows.graph;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
import java.util.stream.Collectors;
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.core.env.Environment;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import com.google.common.collect.Sets;
|
|
|
|
import eu.dnetlib.errors.WorkflowManagerException;
|
|
import eu.dnetlib.manager.wf.model.GraphArcDbEntry;
|
|
import eu.dnetlib.manager.wf.model.GraphNodeDbEntry;
|
|
import eu.dnetlib.manager.wf.model.GraphParameterDbEntry;
|
|
import eu.dnetlib.manager.wf.model.GraphParameterValueDbEntry;
|
|
import eu.dnetlib.manager.wf.workflows.util.NodeHelper;
|
|
|
|
@Service
|
|
public class GraphLoader {
|
|
|
|
private static final Log log = LogFactory.getLog(GraphLoader.class);
|
|
|
|
private final String regExRef = "\\$\\{(\\w*)\\}";
|
|
|
|
final Pattern pattern = Pattern.compile(regExRef, Pattern.MULTILINE);
|
|
|
|
@Autowired
|
|
private NodeHelper nodeHelper;
|
|
|
|
@Autowired
|
|
private Environment env;
|
|
|
|
public Graph loadGraph(final GraphNodeDbEntry[] workflowGraph, final Map<String, String> globalParams) throws WorkflowManagerException {
|
|
final Graph graph = new Graph();
|
|
|
|
for (final GraphNodeDbEntry node : workflowGraph) {
|
|
final String nodeName = node.getName();
|
|
final String nodeType = node.getType();
|
|
final boolean isStart = node.isStart();
|
|
final boolean isJoin = node.isJoin();
|
|
|
|
final Map<String, GraphNodeParameter> params = calculateParamsForNode(node, globalParams);
|
|
|
|
if (isStart) {
|
|
graph.addNode(GraphNode.newStartNode(nodeName, nodeType, params));
|
|
} else if (isJoin) {
|
|
graph.addNode(GraphNode.newJoinNode(nodeName, nodeType, params));
|
|
} else {
|
|
graph.addNode(GraphNode.newNode(nodeName, nodeType, params));
|
|
}
|
|
|
|
if (graph.getArcs() != null) {
|
|
for (final GraphArcDbEntry a : node.getArcs()) {
|
|
final String arcName = a.getName();
|
|
final String to = a.getTo();
|
|
graph.addArc(new Arc(StringUtils.isNotBlank(arcName) ? arcName : Arc.DEFAULT_ARC, nodeName, to));
|
|
}
|
|
}
|
|
|
|
graph.addNode(GraphNode.newSuccessNode());
|
|
}
|
|
|
|
checkValidity(graph);
|
|
|
|
return graph;
|
|
}
|
|
|
|
public Map<String, GraphNodeParameter> calculateParamsForNode(final GraphNodeDbEntry node, final Map<String, String> globalParams) {
|
|
|
|
final Map<String, GraphNodeParameter> params = new HashMap<>();
|
|
|
|
if (node.getParams() != null) {
|
|
for (final GraphParameterDbEntry p : node.getParams()) {
|
|
|
|
final String pName = p.getName();
|
|
|
|
final GraphNodeParameter pValue = calculateSimpleValue(p, globalParams);
|
|
|
|
if (pValue != null) {
|
|
params.put(pName, pValue);
|
|
} else if (p.getMap() != null) {
|
|
|
|
final Map<String, GraphNodeParameter> map = p.getMap()
|
|
.entrySet()
|
|
.stream()
|
|
.collect(Collectors.toMap(e -> e.getKey(), e -> {
|
|
final GraphNodeParameter gnp = calculateSimpleValue(e.getValue(), globalParams);
|
|
if (gnp == null) {
|
|
final String msg = String.format("missing value for param: \"%s\"", e.getKey());
|
|
log.debug(msg);
|
|
return GraphNodeParameter.newNullParam();
|
|
}
|
|
return gnp;
|
|
}));
|
|
params.put(pName, GraphNodeParameter.newMapParam(map));
|
|
} else if (p.getValues() != null) {
|
|
final List<GraphNodeParameter> list = p.getValues()
|
|
.stream()
|
|
.map(e -> calculateSimpleValue(e, globalParams))
|
|
.collect(Collectors.toList());
|
|
params.put(pName, GraphNodeParameter.newListParam(list));
|
|
}
|
|
}
|
|
}
|
|
|
|
return params;
|
|
}
|
|
|
|
private GraphNodeParameter calculateSimpleValue(final GraphParameterValueDbEntry graphValue, final Map<String, String> globalParams) {
|
|
String value = graphValue.getValue();
|
|
final String ref = graphValue.getRef();
|
|
final String prop = graphValue.getProperty();
|
|
final String envRef = graphValue.getEnv();
|
|
|
|
if (StringUtils.isNotBlank(ref) && StringUtils.isNotBlank(globalParams.get(ref))) {
|
|
return GraphNodeParameter.newSimpleParam(globalParams.get(ref));
|
|
} else if (StringUtils.isNotBlank(envRef)) {
|
|
return GraphNodeParameter.newEnvParam(envRef);
|
|
} else if (StringUtils.isNotBlank(value)) {
|
|
final Matcher matcher = pattern.matcher(value);
|
|
while (matcher.find()) {
|
|
final String rName = matcher.group(1);
|
|
final String rValue = globalParams.get(rName);
|
|
if (StringUtils.isBlank(rValue)) { return null; }
|
|
value = value.replaceAll(Pattern.quote(matcher.group(0)), rValue);
|
|
System.out.println("NEW VALUE " + value);
|
|
}
|
|
return GraphNodeParameter.newSimpleParam(value);
|
|
} else if (StringUtils.isNotBlank(prop)) {
|
|
return GraphNodeParameter.newSimpleParam(env.getProperty(prop));
|
|
} else {
|
|
return null;
|
|
}
|
|
|
|
}
|
|
|
|
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.isValidType(n.getType())) { throw new WorkflowManagerException("Invalid node type: " + n.getType()); }
|
|
}
|
|
if (!foundStart) { throw new WorkflowManagerException("Start node not found"); }
|
|
}
|
|
|
|
}
|