Project

General

Profile

1
package eu.dnetlib.openaire.dsm;
2

    
3
import java.util.List;
4
import javax.validation.Valid;
5

    
6
import eu.dnetlib.enabling.datasources.common.DsmException;
7
import eu.dnetlib.enabling.datasources.common.DsmForbiddenException;
8
import eu.dnetlib.enabling.datasources.common.DsmNotFoundException;
9
import eu.dnetlib.openaire.dsm.domain.*;
10
import eu.dnetlib.openaire.common.AbstractExporterController;
11
import eu.dnetlib.openaire.common.OperationManager;
12
import eu.dnetlib.openaire.dsm.domain.ApiDetailsResponse;
13
import eu.dnetlib.openaire.dsm.domain.DatasourceResponse;
14
import eu.dnetlib.openaire.dsm.domain.Response;
15
import eu.dnetlib.openaire.vocabularies.Country;
16
import io.swagger.annotations.ApiOperation;
17
import io.swagger.annotations.ApiResponse;
18
import io.swagger.annotations.ApiResponses;
19
import org.apache.commons.lang3.StringUtils;
20
import org.apache.commons.lang3.time.StopWatch;
21
import org.apache.http.HttpStatus;
22
import org.springframework.beans.factory.annotation.Autowired;
23
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
24
import org.springframework.web.bind.annotation.*;
25

    
26
import static eu.dnetlib.openaire.common.ExporterConstants.*;
27

    
28
@RestController
29
@CrossOrigin(origins = { "*" })
30
@ConditionalOnProperty(value = "openaire.exporter.enable.dsm", havingValue = "true")
31
@io.swagger.annotations.Api(tags = "OpenAIRE DSM API", description = "the OpenAIRE Datasource Manager API")
32
public class DsmApiController extends AbstractExporterController {
33

    
34
	@Autowired
35
	private DsmCore dsmCore;
36

    
37
	@RequestMapping(value = "/ds/countries", produces = { "application/json" }, method = RequestMethod.GET)
38
	@ApiOperation(
39
			value = "list the datasource countries",
40
			notes = "list the datasource countries",
41
			tags = { DS, R },
42
			response = Country[].class)
43
	@ApiResponses(value = {
44
			@ApiResponse(code = 200, message = "OK", response = Country[].class),
45
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
46
	public List<Country> listCountries() throws DsmException {
47
		return dsmCore.listCountries();
48
	}
49

    
50
	@RequestMapping(value = "/ds/search/{page}/{size}", produces = { "application/json" }, method = RequestMethod.POST)
51
	@ApiOperation(
52
			value = "search datasources",
53
			notes = "Returns list of Datasource details.",
54
			tags = { DS, R },
55
			response = DatasourceResponse.class)
56
	@ApiResponses(value = {
57
			@ApiResponse(code = 200, message = "OK", response = DatasourceResponse.class),
58
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
59
	public DatasourceResponse search(
60
			@RequestParam final RequestSort requestSortBy,
61
			@RequestParam final RequestSortOrder order,
62
			@RequestBody final RequestFilter requestFilter,
63
			@PathVariable final int page,
64
			@PathVariable final int size) throws DsmException {
65
		final StopWatch stop = StopWatch.createStarted();
66
		final DatasourceResponse rsp = dsmCore.search(requestSortBy, order, requestFilter, page, size);
67
		return prepareResponse(page, size, stop, rsp);
68
	}
69

    
70
	@RequestMapping(value = "/ds/searchsnippet/{page}/{size}", produces = { "application/json" }, method = RequestMethod.POST)
71
	@ApiOperation(
72
			value = "search datasources",
73
			notes = "Returns list of Datasource basic info.",
74
			tags = { DS, R },
75
			response = DatasourceResponse.class)
76
	@ApiResponses(value = {
77
			@ApiResponse(code = 200, message = "OK", response = DatasourceResponse.class),
78
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
79
	public DatasourceResponse searchSnippet(
80
			@RequestParam final RequestSort requestSortBy,
81
			@RequestParam final RequestSortOrder order,
82
			@RequestBody final RequestFilter requestFilter,
83
			@PathVariable final int page,
84
			@PathVariable final int size) throws DsmException {
85
		final StopWatch stop = StopWatch.createStarted();
86
		final DatasourceResponse rsp = dsmCore.searchSnippet(requestSortBy, order, requestFilter, page, size);
87
		return prepareResponse(page, size, stop, rsp);
88
	}
89

    
90
	@RequestMapping(value = "/ds/api/{dsId}", produces = { "application/json" }, method = RequestMethod.GET)
91
	@ApiOperation(
92
			value = "get the list of API for a given datasource",
93
			notes = "Returns the list of API for a given datasource.",
94
			tags = { API, R },
95
			response = ApiDetailsResponse.class)
96
	@ApiResponses(value = {
97
			@ApiResponse(code = 200, message = "OK", response = ApiDetailsResponse.class),
98
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
99
	public ApiDetailsResponse getApi(
100
			@PathVariable final String dsId) throws DsmException {
101

    
102
		final StopWatch stop = StopWatch.createStarted();
103
		final ApiDetailsResponse rsp = dsmCore.getApis(dsId);
104
		return prepareResponse(0, rsp.getApi().size(), stop, rsp);
105
	}
106

    
107
	@RequestMapping(value = "/api/baseurl/{page}/{size}", produces = { "application/json" }, method = RequestMethod.POST)
108
	@ApiOperation(
109
			value = "search for the list of base URLs of Datasource APIs managed by a user",
110
	        notes = "Returns the list of base URLs of Datasource APIs managed by a user",
111
			tags = { DS, API, R },
112
			response = String[].class)
113
	@ApiResponses(value = {
114
			@ApiResponse(code = 200, message = "OK", response = String[].class),
115
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
116
	public List<String> searchBaseUrls(
117
			@RequestBody final RequestFilter requestFilter,
118
			@PathVariable final int page,
119
			@PathVariable final int size) throws DsmException {
120

    
121
		return dsmCore.findBaseURLs(requestFilter, page, size);
122
	}
123

    
124
	@RequestMapping(value = "/ds/api/{apiId}", method = RequestMethod.DELETE)
125
	@ApiOperation(
126
			value = "delete an API",
127
			notes = "delete an API, if removable",
128
			tags = { API, W })
129
	@ApiResponses(value = {
130
			@ApiResponse(code = 200, message = "OK"),
131
			@ApiResponse(code = 403, message = "Api not removable", response = ErrorMessage.class) })
132
	public void deleteApi(@PathVariable final String apiId) throws DsmException, DsmForbiddenException {
133
		dsmCore.deleteApi(apiId);
134
	}
135

    
136
	@RequestMapping(value = "/ds/manage", method = RequestMethod.POST)
137
	@ApiOperation(
138
			value = "set the managed status for a given datasource",
139
			notes = "set the managed status for a given datasource",
140
			tags = { DS, W })
141
	@ApiResponses(value = {
142
			@ApiResponse(code = 200, message = "OK"),
143
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
144
	public void setManaged(
145
			@RequestParam final String id,
146
			@RequestParam final boolean managed) throws DsmException {
147

    
148
		dsmCore.setManaged(id, managed);
149
	}
150

    
151
	@RequestMapping(value = "/ds/managed/{dsId}", method = RequestMethod.GET)
152
	@ApiOperation(
153
			value = "get the datasource managed status",
154
			notes = "get the datasource managed status",
155
			tags = { DS, R })
156
	@ApiResponses(value = {
157
			@ApiResponse(code = 200, message = "OK"),
158
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
159
	public boolean isManaged(@PathVariable final String id) throws DsmException {
160
		return dsmCore.isManaged(id);
161
	}
162

    
163
	@RequestMapping(value = "/ds/add", method = RequestMethod.POST)
164
	@ApiOperation(
165
			value = "add a new Datasource",
166
			notes = "add a new Datasource",
167
			tags = { DS, W })
168
	@ApiResponses(value = {
169
			@ApiResponse(code = 200, message = "OK"),
170
			@ApiResponse(code = 400, message = "Malformed request", response = ErrorMessage[].class),
171
			@ApiResponse(code = 500, message = "Unexpected error", response = ErrorMessage.class) })
172
	public void saveDs(@Valid @RequestBody final DatasourceDetails datasource) throws DsmException {
173

    
174
		if (dsmCore.exist(datasource)) { // TODO further check that the DS doesn't have any API
175
			throw new DsmException(HttpStatus.SC_CONFLICT, String.format("cannot register, datasource already defined '%s'", datasource.getId()));
176
		}
177
		dsmCore.save(datasource);
178
	}
179

    
180
	@RequestMapping(value = "/ds/update", method = RequestMethod.POST)
181
	@ApiOperation(
182
			value = "update Datasource details",
183
			notes = "update Datasource details",
184
			tags = { DS, W })
185
	@ApiResponses(value = {
186
			@ApiResponse(code = 200, message = "OK"),
187
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
188
	public void updateDatasource(
189
			@RequestBody final DatasourceDetailsUpdate ds) throws DsmException, DsmNotFoundException {
190

    
191
		dsmCore.updateDatasource(ds);
192
	}
193

    
194
	@Deprecated
195
	@RequestMapping(value = "/ds/logourl", method = RequestMethod.POST)
196
	@ApiOperation(
197
			value = "update a datasource name",
198
			notes = "update a datasource name",
199
			tags = { DS, W, D })
200
	@ApiResponses(value = {
201
			@ApiResponse(code = 200, message = "OK"),
202
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
203
	public void updateDatasourceLogoURL(
204
			@RequestParam final String dsId,
205
			@RequestParam final String logourl) throws DsmException {
206

    
207
		dsmCore.updateDatasourceLogoUrl(dsId, logourl);
208
	}
209

    
210
	@Deprecated
211
	@RequestMapping(value = "/ds/name", method = RequestMethod.POST)
212
	@ApiOperation(
213
			value = "update a datasource name",
214
			notes = "update a datasource name",
215
			tags = { DS, W, D })
216
	@ApiResponses(value = {
217
			@ApiResponse(code = 200, message = "OK"),
218
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
219
	public void updateDatasourceName(
220
			@RequestParam final String dsId,
221
			@RequestParam final String officialname,
222
			@RequestParam final String englishname) throws DsmException {
223

    
224
		dsmCore.updateDatasourcename(dsId, officialname, englishname);
225
	}
226

    
227
	@Deprecated
228
	@RequestMapping(value = "/ds/coordinates", method = RequestMethod.POST)
229
	@ApiOperation(
230
			value = "update the datasource coordinates (latitude, longitude)",
231
			notes = "update the datasource coordinates (latitude, longitude)",
232
			tags = { DS, W, D })
233
	@ApiResponses(value = {
234
			@ApiResponse(code = 200, message = "OK"),
235
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
236
	public void updateCoordinates(
237
			@RequestParam final String dsId,
238
			@RequestParam final Double latitude,
239
			@RequestParam final Double longitude) throws DsmException {
240

    
241
		dsmCore.updateCoordinates(dsId, latitude, longitude);
242
	}
243

    
244
	@Deprecated
245
	@RequestMapping(value = "/ds/timezone", method = RequestMethod.POST)
246
	@ApiOperation(
247
			value = "update a datasource timezone",
248
			notes = "update a datasource timezone",
249
			tags = { DS, W, D } )
250
	@ApiResponses(value = {
251
			@ApiResponse(code = 200, message = "OK"),
252
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
253
	public void updateTimezone(
254
			@RequestParam final String dsId,
255
			@RequestParam final String timezone) throws DsmException {
256

    
257
		dsmCore.updateTimezone(dsId, timezone);
258
	}
259

    
260
	@Deprecated
261
	@RequestMapping(value = "/ds/typology", method = RequestMethod.POST)
262
	@ApiOperation(
263
			value = "update a datasource typology code",
264
			notes = "update a datasource typology code",
265
			tags = { DS, W, D } )
266
	@ApiResponses(value = {
267
			@ApiResponse(code = 200, message = "OK"),
268
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
269
	public void updateTypology(
270
			@RequestParam final String dsId,
271
			@RequestParam final String typology) throws DsmException {
272

    
273
		dsmCore.updateDsTypology(dsId, typology);
274
	}
275

    
276
	@Deprecated
277
	@RequestMapping(value = "/ds/registeredby", method = RequestMethod.POST)
278
	@ApiOperation(
279
			value = "update a datasource registeredBy",
280
			notes = "update a datasource registeredBy",
281
			tags = { DS, W, D } )
282
	@ApiResponses(value = {
283
			@ApiResponse(code = 200, message = "OK"),
284
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
285
	public void updateRegisteringUser(
286
			@RequestParam final String dsId,
287
			@RequestParam final String registeredBy) throws DsmException {
288

    
289
		dsmCore.updateDsRegisteringUser(dsId, registeredBy);
290
	}
291

    
292
	@Deprecated
293
	@RequestMapping(value = "/ds/platform", method = RequestMethod.POST)
294
	@ApiOperation(
295
			value = "update a datasource platform",
296
			notes = "update a datasource platform",
297
			tags = { DS, W, D } )
298
	@ApiResponses(value = {
299
			@ApiResponse(code = 200, message = "OK"),
300
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
301
	public void updatePlatform(
302
			@RequestParam final String dsId,
303
			@RequestParam final String platform) throws DsmException {
304

    
305
		dsmCore.updateDsPlatform(dsId, platform);
306
	}
307

    
308
	@RequestMapping(value = "/ds/api/baseurl", method = RequestMethod.POST)
309
	@ApiOperation(
310
			value = "update the base URL of a datasource interface",
311
			notes = "update the base URL of a datasource interface",
312
			tags = { API, W })
313
	@ApiResponses(value = {
314
			@ApiResponse(code = 200, message = "OK"),
315
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
316
	public void updateBaseUrl(
317
			@RequestParam final String dsId,
318
			@RequestParam final String apiId,
319
			@RequestParam final String baseUrl) throws DsmException {
320

    
321
		dsmCore.updateApiBaseurl(dsId, apiId, baseUrl);
322
	}
323

    
324
	@RequestMapping(value = "/ds/api/compliance", method = RequestMethod.POST)
325
	@ApiOperation(
326
			value = "update the compatibility of a datasource interface",
327
			notes = "update the compatibility of a datasource interface",
328
			tags = { API, W })
329
	@ApiResponses(value = {
330
			@ApiResponse(code = 200, message = "OK"),
331
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
332
	public void updateCompliance(
333
			@RequestParam final String dsId,
334
			@RequestParam final String apiId,
335
			@RequestParam final String compliance,
336
			@RequestParam(required = false, defaultValue = "false") boolean override) throws DsmException {
337

    
338
		dsmCore.updateApiCompatibility(dsId, apiId, compliance, override);
339
	}
340

    
341
	@RequestMapping(value = "/ds/api/oaiset", method = RequestMethod.POST)
342
	@ApiOperation(
343
			value = "update the OAI set of a datasource interface",
344
			notes = "update the OAI set of a datasource interface",
345
			tags = { API, W })
346
	@ApiResponses(value = {
347
			@ApiResponse(code = 200, message = "OK"),
348
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
349
	public void updateOaiSetl(
350
			@RequestParam final String dsId,
351
			@RequestParam final String apiId,
352
			@RequestParam final String oaiSet) throws DsmException {
353

    
354
		dsmCore.updateApiOaiSet(dsId, apiId, oaiSet);
355
	}
356

    
357
	@RequestMapping(value = "/ds/api/add", method = RequestMethod.POST)
358
	@ApiOperation(
359
			value = "adds a new Interface to one Datasource",
360
			notes = "adds an Interface to one Datasource",
361
			tags = { API, W })
362
	@ApiResponses(value = {
363
			@ApiResponse(code = 200, message = "OK"),
364
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
365
	public void addApi(@RequestBody final ApiDetails api) throws DsmException {
366
		if (StringUtils.isBlank(api.getDatasource())) {
367
			throw new DsmException(HttpStatus.SC_BAD_REQUEST, "missing datasource id");
368
		}
369
		dsmCore.addApi(api);
370
	}
371

    
372
	// MANAGEMENT
373

    
374
	@Autowired
375
	private OperationManager operationManager;
376

    
377
	@RequestMapping(value = "/dsm/ops", method = RequestMethod.GET)
378
	@ApiOperation(
379
			value = "get the number of pending operations",
380
			notes = "get the number of pending operations",
381
			tags = { R, M })
382
	@ApiResponses(value = {
383
			@ApiResponse(code = 200, message = "OK"),
384
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
385
	public int getOps() throws DsmException {
386
		return operationManager.getOpSize();
387
	}
388

    
389
	@RequestMapping(value = "/dsm/killops", method = RequestMethod.POST)
390
	@ApiOperation(
391
			value = "interrupts the pending operations",
392
			notes = "return the number of interrupted operations",
393
			tags = { W, M })
394
	@ApiResponses(value = {
395
			@ApiResponse(code = 200, message = "OK"),
396
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
397
	public int killOps() throws DsmException {
398
		return operationManager.dropAll();
399
	}
400

    
401
	@RequestMapping(value = "/dsm/dropcache", method = RequestMethod.POST)
402
	@ApiOperation(
403
			value = "drop the caches",
404
			notes = "drop the internal caches",
405
			tags = { W, M })
406
	@ApiResponses(value = {
407
			@ApiResponse(code = 200, message = "OK"),
408
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
409
	public void dropCache() throws DsmException {
410
		dsmCore.dropCaches();
411
	}
412

    
413

    
414
	// OLD DEPRECATED METHODS
415

    
416
	@Deprecated
417
	@ApiOperation(value = "search datasources by name", notes = "Returns list of Datasource details.", tags = { D })
418
	@ApiResponses(value = {
419
			@ApiResponse(code = 200, message = "OK", response = DatasourceResponse.class),
420
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
421
	@RequestMapping(value = "/ds/search/name/{page}/{size}", produces = { "application/json" }, method = RequestMethod.GET)
422
	DatasourceResponse searchByName(String name, int page, int size) throws DsmException {
423
		final RequestSort sort = RequestSort.id;
424
		final RequestSortOrder order = RequestSortOrder.ASCENDING;
425
		final RequestFilter filter = new RequestFilter();
426
		filter.put(FilterName.englishname, name);
427

    
428
		return dsmCore.search(sort, order, filter, page, size);
429
	}
430

    
431
	@Deprecated
432
	@ApiOperation(value = "search datasources by contact email", notes = "Returns list of Datasource details.", tags = { D })
433
	@ApiResponses(value = {
434
			@ApiResponse(code = 200, message = "OK", response = DatasourceResponse.class),
435
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
436
	@RequestMapping(value = "/ds/search/email/{page}/{size}", produces = { "application/json" }, method = RequestMethod.GET)
437
	DatasourceResponse searchByContactemail(String contactemail, int page, int size) throws DsmException {
438
		final RequestSort sort = RequestSort.id;
439
		final RequestSortOrder order = RequestSortOrder.ASCENDING;
440
		final RequestFilter filter = new RequestFilter();
441
		filter.put(FilterName.contactemail, contactemail);
442

    
443
		return dsmCore.search(sort, order, filter, page, size);
444
	}
445

    
446
	@Deprecated
447
	@ApiOperation(value = "search datasources by country", notes = "Returns list of Datasource details.", tags = { D })
448
	@ApiResponses(value = {
449
			@ApiResponse(code = 200, message = "OK", response = DatasourceResponse.class),
450
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
451
	@RequestMapping(value = "/ds/search/country/{page}/{size}", produces = { "application/json" }, method = RequestMethod.GET)
452
	DatasourceResponse searchByCountry(String country, Boolean managed, int page, int size) throws DsmException {
453
		final RequestSort sort = RequestSort.id;
454
		final RequestSortOrder order = RequestSortOrder.ASCENDING;
455
		final RequestFilter filter = new RequestFilter();
456
		filter.put(FilterName.country, country);
457
		filter.put(FilterName.managed, managed);
458

    
459
		return dsmCore.search(sort, order, filter, page, size);
460
	}
461

    
462
	@Deprecated
463
	@ApiOperation(value = "search datasources by registering user", notes = "Returns list of Datasource details.", tags = { D })
464
	@ApiResponses(value = {
465
			@ApiResponse(code = 200, message = "OK", response = DatasourceResponse.class),
466
			@ApiResponse(code = 500, message = "unexpected error", response = ErrorMessage.class) })
467
	@RequestMapping(value = "/ds/search/registeredby/{page}/{size}", produces = { "application/json" }, method = RequestMethod.GET)
468
	DatasourceResponse searchByRegisteringUser(String registeredBy, int page, int size) throws DsmException {
469
		final RequestSort sort = RequestSort.id;
470
		final RequestSortOrder order = RequestSortOrder.ASCENDING;
471
		final RequestFilter filter = new RequestFilter();
472
		filter.put(FilterName.registeredby, registeredBy);
473

    
474
		return dsmCore.search(sort, order, filter, page, size);
475
	}
476

    
477
	// HELPERS
478

    
479
	private <T extends Response> T prepareResponse(int page, int size, final StopWatch stop, final Response rsp) {
480
		rsp.getHeader()
481
				.setTime(stop.getTime())
482
				.setPage(page)
483
				.setSize(size);
484
		return (T) rsp;
485
	}
486
}
(1-1/2)