Project

General

Profile

1
package eu.dnetlib.functionality.modular.ui.workflows.controllers;
2

    
3
import java.awt.image.BufferedImage;
4
import java.io.IOException;
5
import java.io.OutputStream;
6
import java.io.StringReader;
7
import java.util.*;
8
import javax.annotation.Resource;
9
import javax.imageio.ImageIO;
10
import javax.servlet.http.HttpServletResponse;
11

    
12
import com.google.common.base.Function;
13
import com.google.common.base.Splitter;
14
import com.google.common.collect.Iterators;
15
import com.google.common.collect.Lists;
16
import com.google.common.collect.Maps;
17
import com.google.common.collect.Sets;
18
import com.google.gson.Gson;
19
import com.google.gson.reflect.TypeToken;
20
import eu.dnetlib.common.logging.DnetLogger;
21
import eu.dnetlib.common.logging.LogMessage;
22
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
23
import eu.dnetlib.functionality.modular.ui.AbstractAjaxController;
24
import eu.dnetlib.functionality.modular.ui.workflows.objects.EnvParam;
25
import eu.dnetlib.functionality.modular.ui.workflows.objects.ProcessInfo;
26
import eu.dnetlib.functionality.modular.ui.workflows.objects.WorkflowPair;
27
import eu.dnetlib.functionality.modular.ui.workflows.objects.WorkflowUpdateInfo;
28
import eu.dnetlib.functionality.modular.ui.workflows.objects.sections.WorkflowSectionGrouper;
29
import eu.dnetlib.functionality.modular.ui.workflows.util.ISLookupClient;
30
import eu.dnetlib.functionality.modular.ui.workflows.util.ISRegistryClient;
31
import eu.dnetlib.miscutils.datetime.DateUtils;
32
import eu.dnetlib.miscutils.functional.xml.ApplyXslt;
33
import eu.dnetlib.msro.workflows.procs.ProcessRegistry;
34
import eu.dnetlib.msro.workflows.procs.WorkflowExecutor;
35
import eu.dnetlib.msro.workflows.procs.WorkflowProcess;
36
import eu.dnetlib.msro.workflows.util.ProcessUtils;
37
import eu.dnetlib.msro.workflows.util.WorkflowsConstants;
38
import org.apache.commons.io.IOUtils;
39
import org.apache.commons.lang.math.NumberUtils;
40
import org.apache.commons.logging.Log;
41
import org.apache.commons.logging.LogFactory;
42
import org.joda.time.DateTime;
43
import org.joda.time.format.DateTimeFormat;
44
import org.joda.time.format.DateTimeFormatter;
45
import org.springframework.core.io.ClassPathResource;
46
import org.springframework.stereotype.Controller;
47
import org.springframework.web.bind.annotation.RequestMapping;
48
import org.springframework.web.bind.annotation.RequestParam;
49
import org.springframework.web.bind.annotation.ResponseBody;
50

    
51
/**
52
 * Web controller for the UI
53
 *
54
 * @author Michele Artini
55
 */
56

    
57
@Controller
58
public class WorkflowsController extends AbstractAjaxController {
59

    
60
	private static final Log log = LogFactory.getLog(WorkflowsController.class);
61
	@Resource
62
	private ISLookupClient isLookupClient;
63

    
64
	@Resource
65
	private ISRegistryClient isRegistryClient;
66

    
67
	@Resource
68
	private ProcessRegistry graphProcessRegistry;
69

    
70
	@Resource
71
	private WorkflowSectionGrouper workflowSectionGrouper;
72

    
73
	@Resource
74
	private WorkflowExecutor workflowExecutor;
75

    
76
	@Resource(name = "msroWorkflowLogger")
77
	private DnetLogger dnetLogger;
78

    
79
	@RequestMapping("/ui/wf/list_workflows.json")
80
	public
81
	@ResponseBody
82
	List<WorkflowPair> listWorflowsForSection(@RequestParam(value = "section", required = false) final String sectionName,
83
			@RequestParam(value = "dsId", required = false) final String dsId)
84
			throws ISLookUpException, IOException {
85
		if (sectionName != null) {
86
			return workflowSectionGrouper.listWorflowsForSection(sectionName);
87
		} else if (dsId != null) {
88
			return workflowSectionGrouper.listWorflowsForDatasource(dsId);
89
		} else {
90
			return Lists.newArrayList();
91
		}
92
	}
93

    
94
	@RequestMapping("/ui/wf/workflow.html")
95
	public void getWorkflowHtml(HttpServletResponse res, @RequestParam(value = "id", required = true) final String id) throws Exception {
96
		final String profile = isLookupClient.getProfile(id);
97
		final ApplyXslt xslt = new ApplyXslt(new ClassPathResource("/eu/dnetlib/functionality/modular/workflows/xslt/wf_profile2html.xslt"));
98
		res.setContentType("text/html");
99
		IOUtils.copy(new StringReader(xslt.evaluate(profile)), res.getOutputStream());
100
	}
101

    
102
	private void sendImage(final HttpServletResponse response, final BufferedImage image) throws IOException {
103
		response.setContentType("image/png");
104
		OutputStream out = response.getOutputStream();
105
		ImageIO.write(image, "png", out);
106
		out.flush();
107
		out.close();
108
	}
109

    
110
	@RequestMapping("/ui/wf/wf.start")
111
	public
112
	@ResponseBody
113
	ProcessInfo startWorkflow(@RequestParam(value = "id", required = true) final String id) throws Exception {
114
		final String procId = workflowExecutor.startWorkflow(id, null, null);
115
		final WorkflowProcess process = graphProcessRegistry.findProcess(id);
116
		if (process != null) {
117
			return new ProcessInfo(process);
118
		} else {
119
			return new ProcessInfo(procId);
120
		}
121
	}
122

    
123
	@RequestMapping("/ui/wf/update_workflow.do")
124
	public
125
	@ResponseBody
126
	boolean updateWorkflow(@RequestParam(value = "json", required = true) final String json) throws Exception {
127

    
128
		final WorkflowUpdateInfo info = (new Gson()).fromJson(json, WorkflowUpdateInfo.class);
129

    
130
		log.info("Updating workflow " + info.getWfId());
131

    
132
		final String xml = isLookupClient.getProfile(info.getWfId());
133
		boolean res = isRegistryClient.updateWorkflowProfile(info.getWfId(), xml, info);
134

    
135
		return res;
136
	}
137

    
138
	@RequestMapping("/ui/wf/proc.kill")
139
	public
140
	@ResponseBody
141
	boolean killProcessWorkflow(@RequestParam(value = "id", required = true) final String id) throws Exception {
142
		graphProcessRegistry.findProcess(id).kill();
143
		return true;
144
	}
145

    
146
	@RequestMapping("/ui/wf/journal.range")
147
	public
148
	@ResponseBody
149
	Collection<ProcessInfo> rangeWfJournal(@RequestParam(value = "start", required = true) final String start,
150
			@RequestParam(value = "end", required = true) final String end) throws Exception {
151

    
152
		final Map<String, ProcessInfo> res = Maps.newHashMap();
153

    
154
		final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
155
		final DateTime startDate = formatter.parseDateTime(start);
156
		final DateTime endDate = formatter.parseDateTime(end).plusHours(23).plusMinutes(59).plusSeconds(59);
157

    
158
		final Iterator<ProcessInfo> iter = Iterators.transform(dnetLogger.range(startDate.toDate(), endDate.toDate()), new JournalEntryFunction());
159
		while (iter.hasNext()) {
160
			ProcessInfo e = iter.next();
161
			res.put(e.getProcId(), e);
162
		}
163

    
164
		long now = DateUtils.now();
165
		if (startDate.isBefore(now) && endDate.isAfter(now)) {
166
			for (WorkflowProcess proc : graphProcessRegistry.listProcesses()) {
167
				res.put(proc.getId(), new ProcessInfo(proc));
168
			}
169
		}
170

    
171
		return res.values();
172

    
173
	}
174

    
175
	@RequestMapping("/ui/wf/journal.find")
176
	public
177
	@ResponseBody
178
	List<ProcessInfo> findWfJournal(@RequestParam(value = "wfs", required = true) final String wfs) {
179
		final Map<String, ProcessInfo> map = Maps.newHashMap();
180

    
181
		final Set<String> wfFilter = Sets.newHashSet(Splitter.on(",").omitEmptyStrings().trimResults().split(wfs));
182

    
183
		for (String wfId : wfFilter) {
184
			final Iterator<ProcessInfo> iter =
185
					Iterators.transform(dnetLogger.find(WorkflowsConstants.SYSTEM_WF_PROFILE_ID, wfId), new JournalEntryFunction());
186
			while (iter.hasNext()) {
187
				ProcessInfo e = iter.next();
188
				map.put(e.getProcId(), e);
189
			}
190
		}
191

    
192
		for (WorkflowProcess proc : graphProcessRegistry.listProcesses()) {
193
			if (wfFilter.contains(ProcessUtils.calculateWfId(proc))) {
194
				map.put(proc.getId(), new ProcessInfo(proc));
195
			}
196
		}
197

    
198
		final List<ProcessInfo> res = Lists.newArrayList(map.values());
199

    
200
		Collections.sort(res, new Comparator<ProcessInfo>() {
201
			@Override
202
			public int compare(final ProcessInfo p1, final ProcessInfo p2) {
203
				if (p1.getDate() == 0) {
204
					return -1;
205
				} else if (p2.getDate() == 0) {
206
					return 1;
207
				} else {
208
					return Long.compare(p2.getDate(), p1.getDate());
209
				}
210
			}
211
		});
212

    
213
		return res;
214
	}
215

    
216
	@RequestMapping("/ui/wf/journal_byFamily.find")
217
	public
218
	@ResponseBody
219
	Collection<ProcessInfo> findWfJournalByFamily(@RequestParam(value = "family", required = true) final String family) throws IOException {
220
		final Iterator<ProcessInfo> iter =
221
				Iterators.transform(dnetLogger.find(WorkflowsConstants.SYSTEM_WF_PROFILE_FAMILY, family), new JournalEntryFunction());
222
		return Lists.newArrayList(iter);
223
	}
224

    
225
	@RequestMapping("/ui/wf/journal.get")
226
	public
227
	@ResponseBody
228
	ProcessInfo getWfJournalLog(@RequestParam(value = "id", required = true) final String procId) throws Exception {
229
		final WorkflowProcess process = graphProcessRegistry.findProcess(procId);
230
		final ProcessInfo info = (process != null) ? new ProcessInfo(process) : new ProcessInfo();
231

    
232
		final Map<String, String> logs = dnetLogger.findOne("system:processId", procId);
233

    
234
		if (logs != null && !logs.isEmpty()) {
235
			final List<String> keys = Lists.newArrayList(logs.keySet());
236
			Collections.sort(keys);
237
			final List<Map<String, String>> journalEntry = Lists.newArrayList();
238
			for (String k : keys) {
239
				info.getCurrentEnv().add(new EnvParam(k, logs.get(k)));
240
			}
241
		}
242

    
243
		return info;
244
	}
245

    
246
	@RequestMapping(value = "/ui/wf/saveParams.do")
247
	public
248
	@ResponseBody
249
	boolean saveWorkflowParams(@RequestParam(value = "wf", required = true) final String wfId,
250
			@RequestParam(value = "params", required = true) final String jsonParams) throws Exception {
251

    
252
		final String xml = isLookupClient.getProfile(wfId);
253

    
254
		final Map<String, String> params = new Gson().fromJson(jsonParams, new TypeToken<Map<String, String>>() {
255
		}.getType());
256

    
257
		return isRegistryClient.updateWorkflowProfile(wfId, xml, params);
258
	}
259

    
260
	private final class JournalEntryFunction implements Function<Map<String, String>, ProcessInfo> {
261

    
262
		@Override
263
		public ProcessInfo apply(final Map<String, String> input) {
264
			final ProcessInfo info = new ProcessInfo();
265

    
266
			info.setProcId(input.get(WorkflowsConstants.SYSTEM_WF_PROCESS_ID));
267
			info.setWfId(input.get(WorkflowsConstants.SYSTEM_WF_PROFILE_ID));
268
			info.setName(input.get(WorkflowsConstants.SYSTEM_WF_PROFILE_NAME));
269
			info.setFamily(input.get(WorkflowsConstants.SYSTEM_WF_PROFILE_FAMILY));
270
			info.setDatasource(input.containsKey(WorkflowsConstants.DATASOURCE_NAME) ? input.get(WorkflowsConstants.DATASOURCE_NAME) : "");
271
			info.setStatus(Boolean.valueOf(input.get(WorkflowsConstants.SYSTEM_COMPLETED_SUCCESSFULLY)) ? "SUCCESS" : "FAILURE");
272
			info.setDate(NumberUtils.toLong(input.get(LogMessage.LOG_DATE_FIELD), 0));
273
			info.setStartDate(NumberUtils.toLong(input.get(WorkflowsConstants.SYSTEM_START_DATE), 0));
274
			info.setEndDate(NumberUtils.toLong(input.get(WorkflowsConstants.SYSTEM_END_DATE), 0));
275

    
276
			return info;
277
		}
278
	}
279

    
280
}
(5-5/5)