Project

General

Profile

1
package eu.dnetlib.functionality.modular.ui.repositories;
2

    
3
import java.io.IOException;
4
import java.util.Date;
5
import java.util.List;
6
import java.util.Map;
7

    
8
import javax.annotation.Resource;
9
import javax.servlet.http.HttpServletRequest;
10
import javax.servlet.http.HttpServletResponse;
11

    
12
import org.apache.commons.io.IOUtils;
13
import org.apache.commons.lang.exception.ExceptionUtils;
14
import org.apache.commons.lang3.StringUtils;
15
import org.apache.commons.logging.Log;
16
import org.apache.commons.logging.LogFactory;
17
import org.springframework.beans.factory.annotation.Autowired;
18
import org.springframework.beans.factory.annotation.Value;
19
import org.springframework.cache.annotation.CacheEvict;
20
import org.springframework.cache.annotation.Cacheable;
21
import org.springframework.http.HttpStatus;
22
import org.springframework.stereotype.Controller;
23
import org.springframework.ui.ModelMap;
24
import org.springframework.web.bind.annotation.ExceptionHandler;
25
import org.springframework.web.bind.annotation.RequestBody;
26
import org.springframework.web.bind.annotation.RequestMapping;
27
import org.springframework.web.bind.annotation.RequestMethod;
28
import org.springframework.web.bind.annotation.RequestParam;
29
import org.springframework.web.bind.annotation.ResponseBody;
30
import org.springframework.web.bind.annotation.ResponseStatus;
31
import org.springframework.web.client.RestTemplate;
32

    
33
import com.google.common.collect.Maps;
34
import com.google.gson.Gson;
35
import com.google.gson.reflect.TypeToken;
36

    
37
import eu.dnetlib.data.collector.rmi.CollectorService;
38
import eu.dnetlib.data.collector.rmi.CollectorServiceException;
39
import eu.dnetlib.data.collector.rmi.ProtocolParameterValue;
40
import eu.dnetlib.enabling.datasources.common.Api;
41
import eu.dnetlib.enabling.datasources.common.ApiParam;
42
import eu.dnetlib.enabling.datasources.common.ApiParamImpl;
43
import eu.dnetlib.enabling.datasources.common.BrowseTerm;
44
import eu.dnetlib.enabling.datasources.common.Datasource;
45
import eu.dnetlib.enabling.datasources.common.DsmException;
46
import eu.dnetlib.enabling.datasources.common.Identity;
47
import eu.dnetlib.enabling.datasources.common.LocalDatasourceManager;
48
import eu.dnetlib.enabling.datasources.common.Organization;
49
import eu.dnetlib.enabling.datasources.common.SearchApisEntry;
50
import eu.dnetlib.enabling.datasources.common.SimpleDatasource;
51
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpDocumentNotFoundException;
52
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
53
import eu.dnetlib.enabling.is.registry.rmi.ISRegistryService;
54
import eu.dnetlib.enabling.locators.UniqueServiceLocator;
55
import eu.dnetlib.functionality.modular.ui.error.ErrorMessage;
56
import eu.dnetlib.functionality.modular.ui.repositories.objects.RepoInterfaceEntry;
57
import eu.dnetlib.functionality.modular.ui.workflows.objects.sections.WorkflowSectionGrouper;
58
import eu.dnetlib.msro.workflows.sarasvati.loader.WorkflowExecutor;
59
import eu.dnetlib.msro.workflows.util.WorkflowsConstants;
60

    
61
@Controller
62
public class RepoInternalController {
63

    
64
	@Autowired
65
	private LocalDatasourceManager<Datasource<?, ?>, Api<?>> dsManager;
66

    
67
	@Resource
68
	private UniqueServiceLocator serviceLocator;
69

    
70
	@Resource
71
	private WorkflowSectionGrouper workflowSectionGrouper;
72

    
73
	@Resource
74
	private WorkflowExecutor workflowExecutor;
75

    
76
	@Resource
77
	private RepoUIUtils repoUIUtils;
78

    
79
	@Value("${repo.ui.mdstore.sync.button}")
80
	private String syncButton;
81

    
82
	@Value("${repo.ui.mdstore.sync.remote.desc}")
83
	private String syncDesc;
84

    
85
	@Value("${repo.ui.mdstore.sync.remote.api.baseUrl}")
86
	private String syncApiBaseUrl;
87

    
88
	@Value("${repo.ui.mdstore.sync.remote.is.baseUrl}")
89
	private String syncISBaseUrl;
90

    
91
	@Value("${repo.ui.mdstore.sync.local.mongodb.url}")
92
	private String mongoUrl;
93

    
94
	@Value("${services.mdstore.mongodb.db}")
95
	private String mongoDb;
96

    
97
	private static final Log log = LogFactory.getLog(RepoInternalController.class);
98

    
99
	@RequestMapping(value = "/ui/browseRepoField.do")
100
	public @ResponseBody List<? extends BrowseTerm> browseRepoField(@RequestParam(value = "field", required = true) final String field) throws Exception {
101
		return dsManager.browseField(field);
102
	}
103

    
104
	@Cacheable(cacheNames = "repoUIJsonCache", key = "#param, #value", condition = "#refresh == false")
105
	@RequestMapping(value = "/ui/listApis.do")
106
	public @ResponseBody List<? extends SearchApisEntry> listApis(
107
		@RequestParam(value = "param", required = true) final String param,
108
		@RequestParam(value = "value", required = true) final String value,
109
		@RequestParam(value = "refresh", required = false) final String refresh) throws Exception {
110

    
111
		return dsManager.searchApis(param, value);
112
	}
113

    
114
	@RequestMapping(value = "/ui/listRepositories.json")
115
	public @ResponseBody List<SimpleDatasource> listRepositories(@RequestParam(value = "type", required = true) final String type) throws Exception {
116
		return dsManager.searchDatasourcesByType(type);
117
	}
118

    
119
	@CacheEvict("repoUIJsonCache")
120
	@RequestMapping(value = "/ui/validateRepo.do")
121
	public @ResponseBody String listRepositories(@RequestParam(value = "id", required = true) final String id,
122
		@RequestParam(value = "b", required = true) final boolean b) throws Exception {
123

    
124
		final String query = "count(/*[.//RESOURCE_TYPE/@value='MetaWorkflowDSResourceType' and .//DATAPROVIDER/@id='" + id + "'])";
125
		if (!b && Integer.parseInt(serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(query)) > 0) {
126
			throw new Exception("Repo " + id
127
				+ " can be invalidated: it is related to some metawfs");
128
		}
129

    
130
		final String newId = b ? serviceLocator.getService(ISRegistryService.class).validateProfile(id)
131
			: serviceLocator.getService(ISRegistryService.class).invalidateProfile(id);
132

    
133
		return newId;
134
	}
135

    
136
	@RequestMapping(value = "/ui/getRepoDetails.do")
137
	public @ResponseBody Datasource<?, ?> getRepoDetails(final HttpServletResponse response, @RequestParam(value = "id", required = true) final String id)
138
		throws Exception {
139
		return dsManager.getDs(id);
140
	}
141

    
142
	@RequestMapping("/ui/repoMetaWf.new")
143
	public @ResponseBody String newDataProviderWorkflow(@RequestParam(value = "id", required = true) final String repoId,
144
		@RequestParam(value = "name", required = true) final String repoName,
145
		@RequestParam(value = "iface", required = true) final String ifaceId,
146
		@RequestParam(value = "wf", required = true) final String wfId) throws Exception {
147

    
148
		final Map<String, Object> params = Maps.newHashMap();
149
		params.put(WorkflowsConstants.DATAPROVIDER_ID, repoId);
150
		params.put(WorkflowsConstants.DATAPROVIDER_NAME, repoName);
151
		params.put(WorkflowsConstants.DATAPROVIDER_INTERFACE, ifaceId);
152

    
153
		return workflowExecutor.startProcess(wfId, params);
154
	}
155

    
156
	@RequestMapping("/ui/repoMetaWf.destroy")
157
	public @ResponseBody String destroyDataProviderWorkflow(@RequestParam(value = "destroyWf", required = true) final String destroyWfId)
158
		throws Exception {
159
		return workflowExecutor.startProcess(destroyWfId, null);
160
	}
161

    
162
	@RequestMapping("/ui/repoApi.get")
163
	public @ResponseBody RepoInterfaceEntry getRepoApi(@RequestParam(value = "repoId", required = true) final String repoId,
164
		@RequestParam(value = "ifaceId", required = true) final String ifaceId) throws Exception {
165

    
166
		try {
167
			return repoUIUtils.getApi(repoId, ifaceId);
168
		} catch (final ISLookUpDocumentNotFoundException e) {
169

    
170
			log.warn(String
171
				.format("the Interface '%s' is not available for repository '%s', try to sync DB and profiles via the DatasourceManager", ifaceId, repoId));
172
			dsManager.setActive(repoId, ifaceId, dsManager.isActive(repoId, ifaceId));
173
			return repoUIUtils.getApi(repoId, ifaceId);
174
		}
175
	}
176

    
177
	@RequestMapping("/ui/repoApi.update")
178
	public @ResponseBody boolean updateRepoApi(
179
		@RequestParam(value = "id", required = true) final String repoId,
180
		@RequestParam(value = "iface", required = true) final String ifaceId,
181
		@RequestParam(value = "accessParams", required = false) final String accessParamsJson,
182
		@RequestParam(value = "mdIdPath", required = false) final String mdIdPath) throws Exception {
183

    
184
		if (!StringUtils.isEmpty(accessParamsJson)) {
185
			final Map<String, String> params = new Gson().fromJson(accessParamsJson, new TypeToken<Map<String, String>>() {}.getType());
186
			final String baseUrl = params.remove("baseUrl");
187
			dsManager.updateApiDetails(repoId, ifaceId, mdIdPath, baseUrl, params);
188
		}
189

    
190
		return true;
191
	}
192

    
193
	@RequestMapping("/ui/repoApi.delete")
194
	public @ResponseBody boolean deleteRepoApi(
195
		@RequestParam(value = "repo", required = true) final String repoId,
196
		@RequestParam(value = "iface", required = true) final String ifaceId) throws Exception {
197
		dsManager.deleteApi(repoId, ifaceId);
198
		return true;
199
	}
200

    
201
	@CacheEvict("repoUIJsonCache")
202
	@RequestMapping("/ui/repoApiCompliance.update")
203
	public @ResponseBody boolean updateRepoApiCompliance(@RequestParam(value = "id", required = true) final String repoId,
204
		@RequestParam(value = "iface", required = true) final String ifaceId,
205
		@RequestParam(value = "compliance", required = true) final String compliance) throws Exception {
206

    
207
		log.debug("SET COMPLIANCE TO " + compliance);
208

    
209
		dsManager.updateCompliance(repoId, ifaceId, compliance, true);
210

    
211
		return true;
212
	}
213

    
214
	@CacheEvict("repoUIJsonCache")
215
	@RequestMapping("/ui/repoApiCompliance.reset")
216
	public @ResponseBody boolean resetRepoApiCompliance(@RequestParam(value = "id", required = true) final String repoId,
217
		@RequestParam(value = "iface", required = true) final String ifaceId) throws Exception {
218

    
219
		log.debug("RESET COMPLIANCE");
220

    
221
		dsManager.updateCompliance(repoId, ifaceId, null, true);
222

    
223
		return true;
224
	}
225

    
226
	@RequestMapping("/ui/repos/repoApi.html")
227
	public void repoApiHtml(final ModelMap map) throws Exception {
228
		if (StringUtils.isNoneBlank(syncButton, syncDesc, syncApiBaseUrl, syncISBaseUrl)) {
229
			map.addAttribute("syncButton", syncButton);
230
			map.addAttribute("syncDesc", syncDesc);
231
			map.addAttribute("syncISBaseUrl", syncISBaseUrl);
232
			map.addAttribute("mongoDB", mongoDb);
233
			map.addAttribute("mongoUrl", mongoUrl);
234
		}
235
	}
236

    
237
	@RequestMapping("/ui/repoApi.new")
238
	public @ResponseBody boolean addRepoApi(@RequestParam(value = "repoId", required = true) final String repoId,
239
		@RequestParam(value = "iface", required = true) final String ifaceJson) throws DsmException {
240
		final Api<ApiParam> iface = new Gson().fromJson(ifaceJson, new TypeToken<Api<ApiParamImpl>>() {}.getType());
241

    
242
		iface.setDatasource(repoId);
243

    
244
		log.info("Adding api " + iface.getId() + " to repository " + repoId);
245

    
246
		dsManager.addApi(iface);
247

    
248
		return true;
249
	}
250

    
251
	@RequestMapping("/ui/repo.new")
252
	public @ResponseBody boolean addRepoApi(@RequestParam(value = "repo", required = true) final String repoJson) throws DsmException {
253
		final Datasource<Organization<?>, Identity> ds = new Gson().fromJson(repoJson, new TypeToken<Datasource<Organization<?>, Identity>>() {}.getType());
254
		final Date now = new Date();
255
		ds.setDateofcollection(new java.sql.Date(now.getTime()));
256

    
257
		if (StringUtils.isBlank(ds.getEnglishname())) {
258
			ds.setEnglishname(ds.getOfficialname());
259
		}
260

    
261
		if (StringUtils.isBlank(ds.getProvenanceaction())) {
262
			ds.setProvenanceaction("user:insert");
263
		}
264

    
265
		log.info("Adding datasource " + ds.getId() + " - name " + ds.getOfficialname());
266

    
267
		dsManager.saveDs(ds);
268

    
269
		return true;
270
	}
271

    
272
	@RequestMapping("/ui/listValidValuesForParam.do")
273
	public @ResponseBody List<ProtocolParameterValue> listValidValuesForParam(
274
		@RequestParam(value = "protocol", required = true) final String protocol,
275
		@RequestParam(value = "param", required = true) final String param,
276
		@RequestParam(value = "baseUrl", required = true) final String baseUrl) throws CollectorServiceException {
277

    
278
		return serviceLocator.getService(CollectorService.class).listValidValuesForParam(protocol, baseUrl, param, null);
279
	}
280

    
281
	@RequestMapping(value = "/ui/remoteDatasource/apis", method = RequestMethod.GET)
282
	public void listRemoteApis(@RequestParam(value = "repo", required = true) final String repoId,
283
		final HttpServletResponse response) throws IOException {
284

    
285
		final RestTemplate restTemplate = new RestTemplate();
286

    
287
		final String res = restTemplate.getForObject(syncApiBaseUrl + "/ds/api/" + repoId, String.class);
288

    
289
		response.setContentType("application/json;charset=UTF-8");
290

    
291
		IOUtils.write(res, response.getOutputStream());
292
	}
293

    
294
	@RequestMapping(value = "/ui/remoteDatasource/api", method = RequestMethod.POST)
295
	public void saveRemoteApi(@RequestBody final Api<ApiParamImpl> api, final HttpServletResponse response) throws IOException {
296

    
297
		final String url = syncApiBaseUrl + "/ds/api/add";
298

    
299
		log.info("Adding new remote API:");
300
		log.info(" - repo id: " + api.getDatasource());
301
		log.info(" - api id: " + api.getId());
302
		log.info(" - rest call: " + url);
303
		log.info(" - json: " + new Gson().toJson(api));
304

    
305
		final RestTemplate restTemplate = new RestTemplate();
306

    
307
		restTemplate.postForObject(url, api, Void.class);
308

    
309
		listRemoteApis(api.getDatasource(), response);
310
	}
311

    
312
	@ExceptionHandler(Exception.class)
313
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
314
	public @ResponseBody ErrorMessage handleException(final HttpServletRequest req, final Exception e) {
315
		log.error("Error processing " + req.getRequestURI(), e);
316
		return new ErrorMessage(e.getMessage(), ExceptionUtils.getStackTrace(e));
317
	}
318

    
319
}
(5-5/6)