Project

General

Profile

1
package eu.dnetlib.msro.workflows.util;
2

    
3
import java.util.HashMap;
4
import java.util.HashSet;
5
import java.util.List;
6
import java.util.Map;
7
import java.util.Set;
8
import java.util.stream.Collectors;
9

    
10
import org.apache.commons.lang3.StringUtils;
11
import org.apache.commons.logging.Log;
12
import org.apache.commons.logging.LogFactory;
13
import org.dom4j.Document;
14
import org.dom4j.Element;
15
import org.dom4j.Node;
16
import org.springframework.beans.factory.annotation.Autowired;
17
import org.springframework.core.env.Environment;
18
import org.springframework.stereotype.Component;
19

    
20
import com.google.common.collect.Sets;
21

    
22
import eu.dnetlib.msro.exceptions.MSROException;
23
import eu.dnetlib.msro.workflows.Arc;
24
import eu.dnetlib.msro.workflows.Graph;
25
import eu.dnetlib.msro.workflows.GraphNode;
26
import eu.dnetlib.msro.workflows.GraphNodeParameter;
27

    
28
/**
29
 * Created by michele on 19/11/15.
30
 */
31
@Component
32
public class GraphLoader {
33

    
34
	private static final Log log = LogFactory.getLog(GraphLoader.class);
35

    
36
	@Autowired
37
	private Environment springEnv;
38

    
39
	public Graph loadGraph(final Document doc, final Map<String, String> globalParams) throws MSROException {
40
		final Graph graph = new Graph();
41

    
42
		for (final Object o : doc.selectNodes("//CONFIGURATION/WORKFLOW/NODE")) {
43
			final Element n = (Element) o;
44
			final String nodeName = n.valueOf("@name");
45
			final String nodeType = n.valueOf("@type");
46
			final boolean isStart = StringUtils.equalsIgnoreCase(n.valueOf("@isStart"), "true");
47
			final boolean isJoin = StringUtils.equalsIgnoreCase(n.valueOf("@isJoin"), "true");
48

    
49
			final Map<String, GraphNodeParameter> params = calculateParamsForNode(n, globalParams);
50

    
51
			if (isStart) {
52
				graph.addNode(GraphNode.newStartNode(nodeName, nodeType, params));
53
			} else if (isJoin) {
54
				graph.addNode(GraphNode.newJoinNode(nodeName, nodeType, params));
55
			} else {
56
				graph.addNode(GraphNode.newNode(nodeName, nodeType, params));
57
			}
58

    
59
			for (final Object o1 : n.selectNodes(".//ARC")) {
60
				final Element a = (Element) o1;
61
				final String arcName = a.valueOf("@name");
62
				final String to = a.valueOf("@to");
63
				graph.addArc(new Arc(StringUtils.isNotBlank(arcName) ? arcName : Arc.DEFAULT_ARC, nodeName, to));
64
			}
65

    
66
			graph.addNode(GraphNode.newSuccessNode());
67
		}
68

    
69
		checkValidity(graph);
70

    
71
		return graph;
72
	}
73

    
74
	public Map<String, GraphNodeParameter> calculateParamsForNode(final Node node, final Map<String, String> globalParams) {
75

    
76
		final Map<String, GraphNodeParameter> params = new HashMap<>();
77

    
78
		if (node != null) {
79
			for (final Object o : node.selectNodes(".//PARAM")) {
80
				final Element p = (Element) o;
81

    
82
				final String pName = p.valueOf("@name");
83
				final GraphNodeParameter pValue = calculateSimpleValue((Element) o, globalParams);
84

    
85
				if (pValue != null) {
86
					params.put(pName, pValue);
87
				} else if (p.selectSingleNode("./MAP") != null) {
88

    
89
					@SuppressWarnings("unchecked")
90
					final Map<String, GraphNodeParameter> map = ((List<Element>) p.selectNodes("./MAP/ENTRY"))
91
							.stream()
92
							.collect(Collectors.toMap(
93
									e -> e.valueOf("@key"),
94
									e -> {
95
										final GraphNodeParameter gnp = calculateSimpleValue(e, globalParams);
96
										if (gnp == null) {
97
											final String msg = String.format("missing value for param: \"%s\"", e.valueOf("@key"));
98
											log.debug(msg);
99
											return GraphNodeParameter.newNullParam();
100
										}
101
										return gnp;
102
									}));
103

    
104
					params.put(pName, GraphNodeParameter.newMapParam(map));
105

    
106
				} else if (p.selectSingleNode("./LIST") != null) {
107
					@SuppressWarnings("unchecked")
108
					final List<GraphNodeParameter> list = ((List<Element>) p.selectNodes("./LIST/ITEM"))
109
							.stream()
110
							.map(e -> calculateSimpleValue(e, globalParams))
111
							.collect(Collectors.toList());
112
					params.put(pName, GraphNodeParameter.newListParam(list));
113
				}
114
			}
115
		}
116

    
117
		return params;
118
	}
119

    
120
	private GraphNodeParameter calculateSimpleValue(final Element elem, final Map<String, String> globalParams) {
121
		final String value = elem.valueOf("@value");
122
		final String ref = elem.valueOf("@ref");
123
		final String prop = elem.valueOf("@property");
124
		final String envRef = elem.valueOf("@env");
125

    
126
		if (StringUtils.isNotBlank(ref) && StringUtils.isNotBlank(globalParams.get(ref))) {
127
			return GraphNodeParameter.newSimpleParam(globalParams.get(ref));
128
		} else if (StringUtils.isNotBlank(envRef)) {
129
			return GraphNodeParameter.newEnvParam(envRef);
130
		} else if (StringUtils.isNotBlank(value)) {
131
			return GraphNodeParameter.newSimpleParam(value);
132
		} else if (StringUtils.isNotBlank(prop)) {
133
			return GraphNodeParameter.newSimpleParam(springEnv.getProperty(prop));
134
		} else {
135
			return null;
136
		}
137
	}
138

    
139
	private void checkValidity(final Graph graph) throws MSROException {
140

    
141
		final Set<String> nodesFromArcs = new HashSet<String>();
142

    
143
		boolean foundSuccess = false;
144
		boolean foundStart = false;
145

    
146
		for (final Arc arc : graph.getArcs()) {
147
			if (StringUtils.isBlank(arc.getFrom()) || StringUtils.isBlank(arc.getFrom())) { throw new MSROException("Invalid arc: missing from e/o to"); }
148
			if (StringUtils.equals(arc.getTo(), GraphNode.SUCCESS_NODE)) {
149
				foundSuccess = true;
150
			}
151
			nodesFromArcs.add(arc.getFrom());
152
			nodesFromArcs.add(arc.getTo());
153
		}
154

    
155
		if (!foundSuccess) { throw new MSROException("Arc to success not found"); }
156

    
157
		final Set<String> diff = Sets.symmetricDifference(graph.nodeNames(), nodesFromArcs);
158
		if (!diff.isEmpty()) { throw new MSROException("Missing or invalid nodes in arcs: " + diff); }
159

    
160
		for (final GraphNode n : graph.nodes()) {
161
			if (StringUtils.isBlank(n.getName())) { throw new MSROException("Invalid node: missing name"); }
162
			if (n.isStart()) {
163
				foundStart = true;
164
			}
165
		}
166
		if (!foundStart) { throw new MSROException("Start node not found"); }
167
	}
168

    
169
}
(1-1/6)