Project

General

Profile

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

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

    
9
import javax.annotation.PostConstruct;
10

    
11
import org.apache.commons.lang3.StringUtils;
12
import org.apache.commons.logging.Log;
13
import org.apache.commons.logging.LogFactory;
14
import org.springframework.beans.BeansException;
15
import org.springframework.beans.PropertyAccessorFactory;
16
import org.springframework.context.ApplicationContext;
17
import org.springframework.context.ApplicationContextAware;
18
import org.springframework.stereotype.Component;
19

    
20
import com.fasterxml.jackson.core.type.TypeReference;
21
import com.fasterxml.jackson.databind.ObjectMapper;
22

    
23
import eu.dnetlib.exceptions.DnetGenericRuntimeException;
24
import eu.dnetlib.msro.annotations.ProcessNode;
25
import eu.dnetlib.msro.exceptions.MSROException;
26
import eu.dnetlib.msro.workflows.GraphNode;
27
import eu.dnetlib.msro.workflows.GraphNodeParameter;
28
import eu.dnetlib.msro.workflows.nodes.AbstractProcessNode;
29
import eu.dnetlib.msro.workflows.nodes.DefaultJobNode;
30
import eu.dnetlib.msro.workflows.nodes.SuccessNode;
31
import eu.dnetlib.msro.workflows.procs.Env;
32
import eu.dnetlib.msro.workflows.procs.ProcessAware;
33
import eu.dnetlib.msro.workflows.procs.WorkflowProcess;
34

    
35
/**
36
 * Created by michele on 19/11/15.
37
 */
38
@Component
39
public class NodeHelper implements ApplicationContextAware {
40

    
41
	private static final Log log = LogFactory.getLog(NodeHelper.class);
42

    
43
	private ApplicationContext applicationContext;
44

    
45
	private Map<String, Class<?>> validTypes = new HashMap<>();
46

    
47
	@PostConstruct
48
	public void init() {
49
		validTypes = applicationContext.getBeansWithAnnotation(ProcessNode.class)
50
				.values()
51
				.stream()
52
				.filter(bean -> bean instanceof AbstractProcessNode)
53
				.map(bean -> (AbstractProcessNode) bean)
54
				.collect(Collectors.toMap(
55
						bean -> bean.getClass().getAnnotation(ProcessNode.class).value(),
56
						Object::getClass));
57

    
58
	}
59

    
60
	public AbstractProcessNode newProcessNode(final GraphNode node, final WorkflowProcess process, final Env env) throws MSROException {
61
		if (node.isSucessNode()) {
62
			return new SuccessNode();
63
		} else if (StringUtils.isBlank(node.getType())) {
64
			return new DefaultJobNode(node.getName());
65
		} else {
66
			final Optional<AbstractProcessNode> optional = applicationContext.getBeansWithAnnotation(ProcessNode.class)
67
					.values()
68
					.stream()
69
					.filter(bean -> bean.getClass().getAnnotation(ProcessNode.class).value().equals(node.getType()))
70
					.filter(bean -> bean instanceof AbstractProcessNode)
71
					.map(bean -> (AbstractProcessNode) bean)
72
					.findFirst();
73

    
74
			if (optional.isPresent()) {
75
				final AbstractProcessNode pnode = optional.get();
76

    
77
				pnode.setNodeName(node.getName());
78
				// I invoke the setter methods using the static params of the graph node
79
				try {
80
					PropertyAccessorFactory.forBeanPropertyAccess(pnode).setPropertyValues(resolveParams(node, env));
81
				} catch (final Throwable e) {
82
					throw new MSROException(String.format("error setting parameters in wfNode %s", node.getName()), e);
83
				}
84
				if (pnode instanceof ProcessAware) {
85
					((ProcessAware) pnode).setProcess(process);
86
				}
87
				return pnode;
88
			} else {
89
				log.error("cannot find node " + node.getType() + ", valid types are: " + validTypes);
90
				throw new MSROException("cannot find node " + node.getType());
91
			}
92
		}
93
	}
94

    
95
	public Map<String, Object> resolveParamsWithNoEnv(final GraphNode node) {
96
		return resolveParams(node, null);
97
	}
98

    
99
	public Map<String, Object> resolveParams(final GraphNode node, final Env env) {
100
		final Map<String, Object> params = new HashMap<>();
101
		final ObjectMapper mapper = new ObjectMapper();
102

    
103
		try {
104
			if (node.getNodeParams() != null) {
105

    
106
				for (final Map.Entry<String, GraphNodeParameter> e : node.getNodeParams().entrySet()) {
107
					final String pName = e.getKey();
108
					final GraphNodeParameter param = e.getValue();
109

    
110
					if (param.isEnvParam()) {
111
						params.put(pName, resolveFromEnv(param, env));
112
					} else if (param.isMap()) {
113

    
114
						final Map<String, Object> map = new HashMap<>();
115

    
116
						final Map<String, GraphNodeParameter> unresolved =
117
								mapper.readValue(param.getValue(), new TypeReference<Map<String, GraphNodeParameter>>() {});
118

    
119
						for (final Map.Entry<String, GraphNodeParameter> entry : unresolved.entrySet()) {
120
							final String k = entry.getKey();
121
							final Object v = entry.getValue().isEnvParam() ? resolveFromEnv(entry.getValue(), env) : entry.getValue().getValue();
122
							map.put(k, v);
123
						}
124

    
125
						/*
126
						 * inputParam.entrySet() .stream() .collect(Collectors.toMap( e1 -> e1.getKey(), e1 -> e1.getValue().isEnvParam() ?
127
						 * : e1getValue().getValue()));
128
						 */
129
						params.put(pName, map);
130

    
131
					} else if (param.isList()) {
132
						final List<GraphNodeParameter> list =
133
								mapper.readValue(param.getValue(), new TypeReference<List<GraphNodeParameter>>() {});
134

    
135
						params.put(pName, list
136
								.stream()
137
								.map(p -> p.isEnvParam() ? resolveFromEnv(p, env) : p.getValue())
138
								.collect(Collectors.toList()));
139

    
140
					} else {
141
						params.put(pName, param.getValue());
142
					}
143

    
144
				}
145
			}
146
			return params;
147

    
148
		} catch (final Exception e) {
149
			throw new DnetGenericRuntimeException(e);
150
		}
151
	}
152

    
153
	private Object resolveFromEnv(final GraphNodeParameter param, final Env env) {
154
		return env != null ? env.getAttribute(param.getValue()) : "[this value will be resolved using the runtime ENV]";
155
	}
156

    
157
	@Override
158
	public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
159
		this.applicationContext = applicationContext;
160
	}
161

    
162
	public synchronized boolean isValidType(final String type) {
163
		return validTypes.containsKey(type);
164
	}
165

    
166
	public Map<String, Class<?>> getValidTypes() {
167
		return validTypes;
168
	}
169

    
170
}
(2-2/6)