Project

General

Profile

1
package eu.dnetlib.repo.manager.service;
2

    
3
import com.fasterxml.jackson.databind.ObjectMapper;
4
import com.google.gson.JsonArray;
5
import com.google.gson.JsonElement;
6
import com.google.gson.JsonObject;
7
import eu.dnetlib.api.functionality.ValidatorServiceException;
8
import eu.dnetlib.domain.data.Repository;
9
import eu.dnetlib.domain.data.RepositoryInterface;
10
import eu.dnetlib.domain.enabling.Vocabulary;
11
import eu.dnetlib.domain.functionality.validator.JobForValidation;
12
import eu.dnetlib.repo.manager.domain.*;
13
import eu.dnetlib.repo.manager.domain.dto.Role;
14
import eu.dnetlib.repo.manager.exception.ResourceNotFoundException;
15
import eu.dnetlib.repo.manager.service.aai.registry.AaiRegistryService;
16
import eu.dnetlib.repo.manager.service.security.AuthorizationService;
17
import eu.dnetlib.repo.manager.utils.Converter;
18
import gr.uoa.di.driver.enabling.vocabulary.VocabularyLoader;
19
import org.apache.commons.codec.digest.DigestUtils;
20
import org.apache.log4j.Logger;
21
import org.json.JSONArray;
22
import org.json.JSONException;
23
import org.json.JSONObject;
24
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
25
import org.springframework.beans.factory.annotation.Autowired;
26
import org.springframework.beans.factory.annotation.Value;
27
import org.springframework.core.ParameterizedTypeReference;
28
import org.springframework.http.*;
29
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
30
import org.springframework.security.core.Authentication;
31
import org.springframework.security.core.context.SecurityContextHolder;
32
import org.springframework.stereotype.Service;
33
import org.springframework.web.client.RestClientException;
34
import org.springframework.web.client.RestTemplate;
35
import org.springframework.web.util.UriComponents;
36
import org.springframework.web.util.UriComponentsBuilder;
37

    
38
import javax.annotation.PostConstruct;
39
import java.io.IOException;
40
import java.sql.Timestamp;
41
import java.util.*;
42
import java.util.concurrent.ConcurrentHashMap;
43
import java.util.stream.Collectors;
44

    
45
@Service("repositoryService")
46
public class RepositoryServiceImpl implements RepositoryService {
47

    
48
    @Value("${api.baseAddress}")
49
    private String baseAddress;
50

    
51
    @Value("${services.repo-manager.adminEmail}")
52
    private String adminEmail;
53

    
54
    @Autowired
55
    RestTemplate restTemplate;
56

    
57
    private HttpHeaders httpHeaders;
58

    
59
    private final String[] vocabularyNames = {"dnet:countries", "dnet:datasource_typologies", "dnet:compatibilityLevel"};
60

    
61
    private static final Logger LOGGER = Logger.getLogger(RepositoryServiceImpl.class);
62

    
63
    @Value("${services.repomanager.usageStatisticsDiagramsBaseURL}")
64
    private String usageStatisticsDiagramsBaseURL;
65

    
66
    @Value("${services.repomanager.usageStatisticsNumbersBaseURL}")
67
    private String usageStatisticsNumbersBaseURL;
68

    
69
    @Autowired
70
    private VocabularyLoader vocabularyLoader;
71

    
72
    @Autowired
73
    private PiWikService piWikService;
74

    
75
    @Autowired
76
    private EmailUtils emailUtils;
77

    
78
    @Autowired
79
    ValidatorService validatorService;
80

    
81
    @Autowired
82
    private AaiRegistryService registryCalls;
83

    
84
    // TODO: Antonis K. This should be uncommented
85
//    @Autowired
86
//    private AuthoritiesUpdater authoritiesUpdater;
87

    
88
    @Autowired
89
    private AuthorizationService authorizationService;
90

    
91

    
92
    private Map<String, Vocabulary> vocabularyMap = new ConcurrentHashMap<>();
93

    
94
    private Map<String, String> countriesMap = new HashMap<>();
95
    private Map<String, String> inverseCountriesMap = new HashMap<>();
96

    
97
    private static Map<String, List<String>> dataSourceClass = new HashMap<>();
98

    
99
    private static Map<String, String> invertedDataSourceClass = new HashMap<>();
100

    
101
    private String sendEmail() {
102
        OIDCAuthenticationToken authenticationToken = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
103
        return authenticationToken.getUserInfo().getEmail();
104
    }
105

    
106

    
107
    @PostConstruct
108
    private void init() {
109
        LOGGER.debug("Initialization method of repository api!");
110
        LOGGER.debug("Updated version!");
111

    
112
        dataSourceClass.put("opendoar", Arrays.asList("pubsrepository::institutional", "pubsrepository::thematic", "pubsrepository::unknown", "pubsrepository::mock"));
113
        dataSourceClass.put("re3data", Collections.singletonList("datarepository::unknown"));
114
        dataSourceClass.put("journal", Collections.singletonList("pubsrepository::journal"));
115
        dataSourceClass.put("aggregator", Arrays.asList("aggregator::pubsrepository::institutional", "aggregator::pubsrepository::journals", "aggregator::datarepository", "aggregator::pubsrepository::unknown"));
116

    
117
        invertedDataSourceClass.put("pubsrepository::institutional", "opendoar");
118
        invertedDataSourceClass.put("pubsrepository::thematic", "opendoar");
119
        invertedDataSourceClass.put("pubsrepository::unknown", "opendoar");
120
        invertedDataSourceClass.put("pubsrepository::mock", "opendoar");
121
        invertedDataSourceClass.put("datarepository::unknown", "re3data");
122
        invertedDataSourceClass.put("pubsrepository::journal", "journal");
123
        invertedDataSourceClass.put("aggregator::pubsrepository::institutional", "aggregator");
124
        invertedDataSourceClass.put("aggregator::pubsrepository::journals", "aggregator");
125
        invertedDataSourceClass.put("aggregator::datarepository", "aggregator");
126
        invertedDataSourceClass.put("aggregator::pubsrepository::unknown", "aggregator");
127

    
128

    
129
        httpHeaders = new HttpHeaders();
130
        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
131

    
132
        for (String vocName : vocabularyNames) {
133
            vocabularyMap.put(vocName, vocabularyLoader.getVocabulary(vocName, Locale.ENGLISH, Locale.ROOT));
134
        }
135

    
136
        Country[] countries = getCountries();
137
        for (Country c : countries) {
138
            countriesMap.put(c.getName(), c.getCode());
139
            inverseCountriesMap.put(c.getCode(), c.getName());
140
        }
141

    
142

    
143
    }
144

    
145
    @Override
146
    public Country[] getCountries() {
147
        UriComponents uriComponents = UriComponentsBuilder
148
                .fromHttpUrl(baseAddress + "/ds/countries")
149
                .build().encode();
150
        return restTemplate.getForObject(uriComponents.toUri(), Country[].class);
151
    }
152

    
153

    
154
    @Override
155
    public List<RepositorySnippet> getRepositoriesByCountry(String country,
156
                                                            String mode,
157
                                                            Boolean managed) throws JSONException, IOException {
158

    
159
        LOGGER.debug("Getting repositories by country!");
160
        int page = 0;
161
        int size = 100;
162
        List<RepositorySnippet> resultSet = new ArrayList<>();
163
        ObjectMapper mapper = new ObjectMapper();
164

    
165
        String filterKey = "UNKNOWN";
166
        if (mode.equalsIgnoreCase("opendoar"))
167
            filterKey = "openaire____::opendoar";
168
        else if (mode.equalsIgnoreCase("re3data"))
169
            filterKey = "openaire____::re3data";
170

    
171

    
172
        LOGGER.debug("Country code equals : " + country);
173
        LOGGER.debug("Filter mode equals : " + filterKey);
174

    
175
        UriComponents uriComponents = searchSnipperDatasource(String.valueOf(page), String.valueOf(size));
176
        RequestFilter requestFilter = new RequestFilter();
177
        requestFilter.setCountry(country);
178
        requestFilter.setCollectedfrom(filterKey);
179

    
180
        try {
181
            String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
182
            JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
183
            while (jsonArray.length() > 0) {
184
                resultSet.addAll(mapper.readValue(String.valueOf(jsonArray),
185
                        mapper.getTypeFactory().constructCollectionType(List.class, RepositorySnippet.class)));
186
                page += 1;
187
                uriComponents = searchSnipperDatasource(String.valueOf(page), String.valueOf(size));
188
                rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
189
                jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
190
            }
191
            return resultSet;
192
        } catch (Exception e) {
193
            LOGGER.debug("Exception on getRepositoriesByCountry", e);
194
//            emailUtils.reportException(e);
195
            throw e;
196
        }
197
    }
198

    
199
    public List<RepositorySnippet> searchRegisteredRepositories(String country, String typology, String englishName,
200
                                                                String officialName, String requestSortBy, String order, int page, int pageSize) throws Exception {
201

    
202
        LOGGER.debug("Searching registered repositories");
203

    
204
        List<RepositorySnippet> resultSet = new ArrayList<>();
205
        ObjectMapper mapper = new ObjectMapper();
206

    
207
        UriComponents uriComponents = searchRegisteredDatasource(requestSortBy, order, Integer.toString(page), Integer.toString(pageSize));
208

    
209
        RequestFilter requestFilter = new RequestFilter();
210
        requestFilter.setCountry(country);
211
        requestFilter.setTypology(typology);
212
        requestFilter.setOfficialname(officialName);
213
        requestFilter.setEnglishname(englishName);
214

    
215
        try {
216
            String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
217
            JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
218

    
219
            resultSet.addAll(mapper.readValue(String.valueOf(jsonArray), mapper.getTypeFactory().constructCollectionType(List.class, RepositorySnippet.class)));
220

    
221
            return resultSet;
222
        } catch (Exception e) {
223
            LOGGER.error("Error searching registered datasources", e);
224
            throw e;
225
        }
226
    }
227

    
228
    private Repository updateRepositoryInfo(Repository r) throws JSONException {
229

    
230
        /*
231
         * from datasource class
232
         * we get the datasource type form the inverted map
233
         * */
234
        r.setDatasourceType(getRepositoryType(r.getDatasourceClass()));
235
        r.setInterfaces(this.getRepositoryInterface(r.getId()));
236
        r.setPiwikInfo(piWikService.getPiwikSiteForRepo(r.getId()));
237
        r.setCountryName(getCountryName(r.getCountryCode()));
238
        return r;
239
    }
240

    
241

    
242
    private Collection<Repository> getRepositoriesByMode(String mode, List<Repository> rs) {
243

    
244
        List<Repository> reps = new ArrayList<>();
245
        for (Repository r : rs) {
246
            if (r.getCollectedFrom() != null && r.getCollectedFrom().equals(mode))
247
                reps.add(r);
248

    
249
        }
250
        return reps;
251
    }
252

    
253
    @Override
254
    public List<Repository> getRepositoriesOfUser(String userEmail,
255
                                                  String page,
256
                                                  String size) throws JSONException {
257

    
258
        LOGGER.debug("Retreiving repositories of user : " + userEmail);
259
        UriComponents uriComponents = searchDatasource(page, size);
260
        RequestFilter requestFilter = new RequestFilter();
261
//        requestFilter.setRegisteredby(userEmail);
262

    
263
        List<String> repoIds = getRepoIdsFromUserRoles(userEmail);
264
        List<Repository> repos = new ArrayList<>();
265

    
266
        try {
267
            for (String repoId : repoIds) {
268
                requestFilter.setId(repoId);
269
                String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
270

    
271
                repos.addAll(Converter.jsonToRepositoryList(new JSONObject(rs)));
272
            }
273
        } catch (Exception e) {
274
            LOGGER.debug("Exception on getRepositoriesOfUser", e);
275
            emailUtils.reportException(e);
276
            throw e;
277
        }
278

    
279
        for (Repository r : repos)
280
            r.setPiwikInfo(piWikService.getPiwikSiteForRepo(r.getId()));
281
        return repos;
282
    }
283

    
284
    @Override
285
    public List<RepositorySnippet> getRepositoriesSnippetOfUser(String userEmail, String page, String size) throws IOException, JSONException {
286

    
287
        // TODO: Step 3 - For each repo from the previous step call findByRepositoryId piwik_site to get the full info of repo
288
        List<String> repoIds = getRepoIdsFromUserRoles(userEmail);
289

    
290
        List<RepositorySnippet> resultSet = new ArrayList<>();
291
        ObjectMapper mapper = new ObjectMapper();
292

    
293
        // here page should be 0
294
        UriComponents uriComponents = searchSnipperDatasource(page, size);
295
        RequestFilter requestFilter = new RequestFilter();
296

    
297
        try {
298
            for (String repoId : repoIds) {
299
                requestFilter.setId(repoId);
300

    
301
                String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
302
                JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
303
                resultSet.addAll(mapper.readValue(String.valueOf(jsonArray),
304
                        mapper.getTypeFactory().constructCollectionType(List.class, RepositorySnippet.class)));
305
            }
306
        } catch (Exception e) {
307
            LOGGER.debug("Exception on getRepositoriesSnippetOfUser", e);
308
            throw e;
309
        }
310

    
311
        LOGGER.debug("resultSet:" + resultSet);
312
        resultSet.parallelStream().forEach(repositorySnippet -> {
313
            repositorySnippet.setPiwikInfo(piWikService.getPiwikSiteForRepo(repositorySnippet.getId()));
314
        });
315
        return resultSet;
316
    }
317

    
318
    @Override
319
    public RepositorySnippet getRepositorySnippetById(String id) throws JSONException, ResourceNotFoundException {
320

    
321
        LOGGER.debug("Retreiving repositories with id : " + id);
322
        RepositorySnippet repo = null;
323
        UriComponents uriComponents = searchSnipperDatasource("0", "100");
324
        RequestFilter requestFilter = new RequestFilter();
325
        requestFilter.setId(id);
326

    
327
        try {
328
            String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
329
            JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
330

    
331
            if (jsonArray.length() == 0)
332
                throw new ResourceNotFoundException();
333

    
334
            repo = Converter.jsonToRepositorySnippetObject(jsonArray.getJSONObject(0));
335
            return repo;
336
        } catch (JSONException e) {
337
            LOGGER.debug("Exception on getRepositoryById", e);
338
            emailUtils.reportException(e);
339
            throw e;
340
        }
341

    
342
    }
343

    
344
    @Override
345
    public Repository getRepositoryById(String id) throws JSONException, ResourceNotFoundException {
346

    
347
        LOGGER.debug("Retreiving repositories with id : " + id);
348
        Repository repo = null;
349
        UriComponents uriComponents = searchDatasource("0", "100");
350
        RequestFilter requestFilter = new RequestFilter();
351
        requestFilter.setId(id);
352

    
353
        try {
354
            String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
355
            JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
356

    
357
            if (jsonArray.length() == 0)
358
                throw new ResourceNotFoundException();
359

    
360
            repo = Converter.jsonToRepositoryObject(jsonArray.getJSONObject(0));
361
            return updateRepositoryInfo(repo);
362
        } catch (JSONException e) {
363
            LOGGER.debug("Exception on getRepositoryById", e);
364
            emailUtils.reportException(e);
365
            throw e;
366
        }
367

    
368
    }
369

    
370

    
371
    @Override
372
    public List<AggregationDetails> getRepositoryAggregations(String id, int from, int size) throws JSONException {
373

    
374
        LOGGER.debug("Retreiving aggregations for repository with id : " + id);
375
        UriComponents uriComponents = searchDatasource(from + "", size + "");
376
        RequestFilter requestFilter = new RequestFilter();
377
        requestFilter.setId(id);
378

    
379
        List<AggregationDetails> aggregationHistory = new ArrayList<>();
380

    
381
        try {
382
            long start = System.currentTimeMillis();
383
            String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
384
            long end = System.currentTimeMillis();
385

    
386
            System.out.println("Aggregations request through rest template took " + (end - start) + "ms");
387
            JSONObject repository = new JSONObject(rs);
388

    
389
            if (repository.getJSONArray("datasourceInfo").length() == 0)
390
                return aggregationHistory;
391

    
392
            start = System.currentTimeMillis();
393
            aggregationHistory.addAll(Converter.getAggregationHistoryFromJson(repository.getJSONArray("datasourceInfo").getJSONObject(0)));
394
            end = System.currentTimeMillis();
395

    
396
            System.out.println("Getting aggregations history from json " + (end - start) + "ms");
397
            return aggregationHistory.size() == 0 ? aggregationHistory : aggregationHistory.stream()
398
                    .sorted(Comparator.comparing(AggregationDetails::getDate).reversed())
399
                    .limit(size)
400
                    .collect(Collectors.toList());
401
        } catch (JSONException e) {
402
            LOGGER.debug("Exception on getRepositoryAggregations", e);
403
            emailUtils.reportException(e);
404
            throw e;
405
        }
406

    
407
    }
408

    
409
    @Override
410
    public Map<String, List<AggregationDetails>> getRepositoryAggregationsByYear(String id) throws JSONException {
411
        LOGGER.debug("Retreiving aggregations (by year) for repository with id : " + id);
412
        UriComponents uriComponents = searchDatasource("0", "100");
413
        RequestFilter requestFilter = new RequestFilter();
414
        requestFilter.setId(id);
415

    
416
        List<AggregationDetails> aggregationHistory = new ArrayList<>();
417
        Map<String, List<AggregationDetails>> aggregationByYear = new HashMap<>();
418
        try {
419
            String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
420
            JSONObject repository = new JSONObject(rs);
421

    
422
            if (repository.getJSONArray("datasourceInfo").length() == 0)
423
                return aggregationByYear;
424

    
425
            aggregationHistory.addAll(Converter.getAggregationHistoryFromJson(repository.getJSONArray("datasourceInfo").getJSONObject(0)));
426
            return aggregationHistory.size() == 0 ? aggregationByYear : createYearMap(aggregationHistory);
427

    
428
        } catch (JSONException e) {
429
            LOGGER.debug("Exception on getRepositoryAggregations", e);
430
            emailUtils.reportException(e);
431
            throw e;
432
        }
433
    }
434

    
435
    private Map<String, List<AggregationDetails>> createYearMap(List<AggregationDetails> aggregationHistory) {
436
        Map<String, List<AggregationDetails>> aggregationByYear;
437
        aggregationHistory = aggregationHistory.stream()
438
                .sorted(Comparator.comparing(AggregationDetails::getDate).reversed())
439
                .collect(Collectors.toList());
440

    
441
        return aggregationHistory.stream()
442
                .collect(Collectors.groupingBy(AggregationDetails::getYear));
443
    }
444

    
445

    
446
    @Override
447
    public List<Repository> getRepositoriesByName(String name,
448
                                                  String page,
449
                                                  String size) throws JSONException {
450

    
451
        LOGGER.debug("Retreiving  repositories with official name : " + name);
452
        UriComponents uriComponents = searchDatasource("0", "100");
453
        RequestFilter requestFilter = new RequestFilter();
454
        requestFilter.setOfficialname(name);
455

    
456
        try {
457
            String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
458
            List<Repository> repos = Converter.jsonToRepositoryList(new JSONObject(rs));
459
            for (Repository r : repos)
460
                updateRepositoryInfo(r);
461
            return repos;
462
        } catch (Exception e) {
463
            LOGGER.debug("Exception on getRepositoriesByName", e);
464
            emailUtils.reportException(e);
465
            throw e;
466
        }
467

    
468
    }
469

    
470
    @Override
471
    public List<RepositoryInterface> getRepositoryInterface(String id) throws JSONException {
472

    
473
        UriComponents uriComponents = UriComponentsBuilder
474
                .fromHttpUrl(baseAddress + "/ds/api/")
475
                .path("/{id}")
476
                .build().expand(id).encode();
477

    
478
        try {
479
            String rs = restTemplate.getForObject(uriComponents.toUri(), String.class);
480
            return Converter.jsonToRepositoryInterfaceList(new JSONObject(rs));
481
        } catch (Exception e) {
482
            LOGGER.debug("Exception on getRepositoryInterface", e);
483
            emailUtils.reportException(e);
484
            throw e;
485
        }
486

    
487
    }
488

    
489
    @Override
490
    public Repository addRepository(String datatype,
491
                                    Repository repository) throws Exception {
492

    
493
        LOGGER.debug("storing " + datatype + " repository with id: " + repository.getId());
494

    
495
        repository.setCountryCode(countriesMap.get(repository.getCountryName()));
496
        repository.setActivationId(UUID.randomUUID().toString());
497
        repository.setCollectedFrom("infrastruct_::openaire");
498

    
499
        if (datatype.equals("journal")) {
500
            repository.setId("openaire____::issn" + repository.getIssn());
501
            repository.setNamespacePrefix("issn" + repository.getIssn());
502
            this.storeRepository(repository, SecurityContextHolder.getContext().getAuthentication());
503
        } else if (datatype.equals("aggregator")) {
504
            repository.setId("openaire____::" + com.unboundid.util.Base64.encode(repository.getOfficialName()));
505
            repository.setNamespacePrefix(DigestUtils.md5Hex(repository.getOfficialName()).substring(0, 12));
506
            this.storeRepository(repository, SecurityContextHolder.getContext().getAuthentication());
507
        } else {
508
            this.latentUpdate(repository, SecurityContextHolder.getContext().getAuthentication());
509
        }
510

    
511
        // TODO: Antonis K. - Create new role ROLE_(datasource.datasourceId) and assign it to the user that created the folder (+ replace :: with $$)
512
        // Create new role ( careful ... replace :: with $$ )
513
        String newRoleName = repository.getId().replaceAll(":", "\\$");
514
        String newRoleDescr = repository.getId().replaceAll(":", "\\$");
515
        Role newRole = new Role(newRoleName, newRoleDescr);
516
        try {
517
            registryCalls.createRole(newRole);
518
        } catch (Exception e) {
519
            LOGGER.debug("Exception on create role during add repository", e);
520
            throw e;
521
        }
522

    
523
        // Assign new role to the user that created it
524
        Integer coPersonId = registryCalls.getCoPersonIdByIdentifier();
525
        Integer couId = registryCalls.getCouId("datasource", newRoleName);
526
        if (couId != null) {
527
            Integer role = registryCalls.getRoleId(coPersonId, couId);
528
            try {
529
                registryCalls.assignMemberRole(coPersonId, couId, role);
530
                // TODO: Antonis K. This should be uncommented to make a role DATASOURCE.OP... for every new repo
531
//                authoritiesUpdater.update(sendEmail(), old -> {
532
//                    HashSet<SimpleGrantedAuthority> authorities = new HashSet<>((Collection<? extends SimpleGrantedAuthority>) old);
533
//                    authorities.add(new SimpleGrantedAuthority(authorizationService.member("datasource", newRoleName)));
534
//                    return authorities;
535
//                });
536
            } catch (Exception e) {
537
                LOGGER.debug("Exception on assign role to user during add repository", e);
538
                throw e;
539
            }
540

    
541
        }
542

    
543

    
544
        return repository;
545
    }
546

    
547
    /* update method acting as add -> send email with registration topic/body*/
548
    private Repository latentUpdate(Repository repository, Authentication authentication) throws Exception {
549
        UriComponents uriComponents = UriComponentsBuilder
550
                .fromHttpUrl(baseAddress + "/ds/update/")
551
                .build()
552
                .encode();
553

    
554
        try {
555
            String json_repository = Converter.repositoryObjectToJson(repository);
556
            LOGGER.debug("JSON to add(update) -> " + json_repository);
557

    
558
            HttpEntity<String> httpEntity = new HttpEntity<String>(json_repository, httpHeaders);
559
            ResponseEntity responseEntity = restTemplate.exchange(uriComponents.toUri(), HttpMethod.POST, httpEntity, ResponseEntity.class);
560

    
561
            if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
562
//                emailUtils.sendUserRegistrationEmail(repository, authentication);
563
//                emailUtils.sendAdminRegistrationEmail(repository, authentication);
564
            } else
565
                LOGGER.debug(responseEntity.getBody().toString());
566

    
567
            return repository;
568
        } catch (Exception e) {
569
            LOGGER.debug("Exception on updateRepository", e);
570
            emailUtils.reportException(e);
571
            throw e;
572
        }
573

    
574

    
575
    }
576

    
577
    @Override
578
    public Repository updateRepository(Repository repository, Authentication authentication) throws Exception {
579
        UriComponents uriComponents = UriComponentsBuilder
580
                .fromHttpUrl(baseAddress + "/ds/update/")
581
                .build()
582
                .encode();
583

    
584
        try {
585
            String json_repository = Converter.repositoryObjectToJson(repository);
586

    
587
            LOGGER.debug("JSON to update -> " + json_repository);
588

    
589
            HttpEntity<String> httpEntity = new HttpEntity<String>(json_repository, httpHeaders);
590
            ResponseEntity responseEntity = restTemplate.exchange(uriComponents.toUri(), HttpMethod.POST, httpEntity
591
                    , ResponseEntity.class);
592

    
593
            if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
594
                emailUtils.sendUserUpdateRepositoryInfoEmail(repository, authentication);
595
                emailUtils.sendAdminUpdateRepositoryInfoEmail(repository, authentication);
596
            } else
597
                LOGGER.debug(responseEntity.getBody().toString());
598

    
599
            return repository;
600
        } catch (Exception e) {
601
            LOGGER.debug("Exception on updateRepository", e);
602
            emailUtils.reportException(e);
603
            throw e;
604
        }
605
    }
606

    
607
    private void storeRepository(Repository repository, Authentication authentication) throws Exception {
608

    
609
        Date utilDate = new Date();
610
        Timestamp date = new Timestamp(utilDate.getTime());
611
        repository.setDateOfCollection(date);
612
        repository.setAggregator("OPENAIRE");
613
        repository.setCountryCode(countriesMap.get(repository.getCountryName()));
614

    
615
        UriComponents uriComponents = UriComponentsBuilder
616
                .fromHttpUrl(baseAddress + "/ds/add/")
617
                .build()
618
                .encode();
619
        String json_repository = Converter.repositoryObjectToJson(repository);
620
        HttpEntity<String> httpEntity = new HttpEntity<String>(json_repository, httpHeaders);
621
        ResponseEntity responseEntity = restTemplate.exchange(uriComponents.toUri(), HttpMethod.POST, httpEntity, ResponseEntity.class);
622

    
623
        if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
624
            emailUtils.sendUserRegistrationEmail(repository, authentication);
625
            emailUtils.sendAdminRegistrationEmail(repository, authentication);
626
        } else {
627
            LOGGER.debug(responseEntity.getBody().toString());
628
        }
629
    }
630

    
631
    @Override
632
    public void deleteRepositoryInterface(String id,
633
                                          String registeredBy) {
634
        UriComponents uriComponents = UriComponentsBuilder
635
                .fromHttpUrl(baseAddress + "/ds/api/")
636
                .path("/{id}")
637
                .build().expand(id).encode();
638
        LOGGER.debug(uriComponents.toUri());
639
        restTemplate.delete(uriComponents.toUri());
640
    }
641

    
642
    @Override
643
    public RepositoryInterface addRepositoryInterface(String datatype,
644
                                                      String repoId,
645
                                                      String registeredBy,
646
                                                      String comment, RepositoryInterface repositoryInterface) throws Exception {
647
        try {
648
            Repository e = this.getRepositoryById(repoId);
649
            repositoryInterface = createRepositoryInterface(e, repositoryInterface, datatype);
650
            String json_interface = Converter.repositoryInterfaceObjectToJson(e, repositoryInterface);
651

    
652
            UriComponents uriComponents = UriComponentsBuilder
653
                    .fromHttpUrl(baseAddress + "/ds/api/add/")
654
                    .build()
655
                    .encode();
656

    
657
            HttpEntity<String> httpEntity = new HttpEntity<>(json_interface, httpHeaders);
658

    
659
            restTemplate.postForObject(uriComponents.toUri(), httpEntity, String.class);
660

    
661
            emailUtils.sendAdminRegisterInterfaceEmail(e, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
662
            emailUtils.sendUserRegisterInterfaceEmail(e, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
663

    
664
            submitInterfaceValidation(e, registeredBy, repositoryInterface, false);
665

    
666
            return repositoryInterface;
667

    
668
        } catch (Exception e) {
669
            LOGGER.error("Exception on addRepositoryInterface", e);
670
            emailUtils.reportException(e);
671
            throw e;
672
        }
673
    }
674

    
675
    @Override
676
    public RepositoryInterface updateRepositoryInterface(String repoId,
677
                                                         String registeredBy,
678
                                                         String comment, RepositoryInterface repositoryInterface) throws Exception {
679

    
680
        this.updateBaseUrl(repoId, repositoryInterface.getId(), repositoryInterface.getBaseUrl());
681
        this.updateCompliance(repoId, repositoryInterface.getId(), repositoryInterface.getCompliance());
682
        this.updateValidationSet(repoId, repositoryInterface.getId(), repositoryInterface.getAccessSet());
683

    
684
        Repository e = this.getRepositoryById(repoId);
685
        emailUtils.sendAdminUpdateInterfaceEmail(e, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
686
        emailUtils.sendUserUpdateInterfaceEmail(e, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
687
        submitInterfaceValidation(getRepositoryById(repoId), registeredBy, repositoryInterface, true);
688

    
689
        return repositoryInterface;
690
    }
691

    
692
    private void submitInterfaceValidation(Repository repo, String userEmail, RepositoryInterface iFace, boolean updateExisting) throws ValidatorServiceException {
693
        JobForValidation job = new JobForValidation();
694

    
695
        job.setActivationId(UUID.randomUUID().toString());
696
        job.setAdminEmails(Collections.singletonList(this.adminEmail));
697
        job.setBaseUrl(iFace.getBaseUrl());
698
        job.setDatasourceId(repo.getId());
699
        job.setDesiredCompatibilityLevel(iFace.getDesiredCompatibilityLevel());
700
        job.setInterfaceId(iFace.getId());
701
        job.setOfficialName(repo.getOfficialName());
702
        job.setRepoType(repo.getDatasourceType());
703
        job.setUserEmail(userEmail);
704
        job.setValidationSet((iFace.getAccessSet().isEmpty() ? "none" : iFace.getAccessSet()));
705
        job.setRecords(-1);
706
        job.setRegistration(!updateExisting);
707
        job.setUpdateExisting(updateExisting);
708

    
709
        this.validatorService.submitJobForValidation(job);
710
    }
711

    
712
    private RepositoryInterface createRepositoryInterface(Repository repo, RepositoryInterface iFace, String datatype) {
713

    
714
        iFace.setContentDescription("metadata");
715
        iFace.setCompliance("UNKNOWN");
716

    
717
        if (datatype.equals("re3data"))
718
            iFace.setAccessFormat("oai_datacite");
719
        else
720
            iFace.setAccessFormat("oai_dc");
721

    
722

    
723
        if (repo.getDatasourceClass() != null && !repo.getDatasourceClass().isEmpty())
724
            iFace.setTypology(repo.getDatasourceClass());
725
        else if (datatype.equalsIgnoreCase("journal"))
726
            iFace.setTypology("pubsrepository::journal");
727
        else if (datatype.equalsIgnoreCase("aggregator"))
728
            iFace.setTypology("aggregator::pubsrepository::unknown");
729
        else if (datatype.equalsIgnoreCase("opendoar"))
730
            iFace.setTypology("pubsrepository::unknown");
731
        else if (datatype.equalsIgnoreCase("re3data"))
732
            iFace.setTypology("datarepository::unknown");
733

    
734
        iFace.setRemovable(true);
735
        iFace.setAccessProtocol("oai");
736
        iFace.setMetadataIdentifierPath("//*[local-name()='header']/*[local-name()='identifier']");
737
        iFace.setId("api_________::" + repo.getId() + "::" + UUID.randomUUID().toString().substring(0, 8));
738
        if (iFace.getAccessSet() == null || iFace.getAccessSet().isEmpty()) {
739
            LOGGER.debug("set is empty: " + iFace.getAccessSet());
740
            iFace.removeAccessSet();
741
            iFace.setAccessSet("none");
742
        }
743
        return iFace;
744
    }
745

    
746
    @Override
747
    public List<String> getDnetCountries() {
748
        LOGGER.debug("Getting dnet-countries!");
749
        return Converter.readFile("countries.txt");
750
    }
751

    
752
    @Override
753
    public List<String> getTypologies() {
754
        return Converter.readFile("typologies.txt");
755
    }
756

    
757
    @Override
758
    public List<Timezone> getTimezones() {
759
        List<String> timezones = Converter.readFile("timezones.txt");
760
        return Converter.toTimezones(timezones);
761
    }
762

    
763
    @Override
764
    public List<String> getUrlsOfUserRepos(String userEmail,
765
                                           String page,
766
                                           String size) {
767
        UriComponents uriComponents = UriComponentsBuilder
768
                .fromHttpUrl(baseAddress + "/api/baseurl/")
769
                .path("/{page}/{size}")
770
                .build().expand(page, size).encode();
771

    
772
        try {
773
            RequestFilter requestFilter = new RequestFilter();
774
            requestFilter.setRegisteredby(userEmail);
775
            return Arrays.asList(restTemplate.postForObject(uriComponents.toUri(), requestFilter, String[].class));
776
        } catch (Exception e) {
777
            LOGGER.debug("Exception on addRepositoryInterface", e);
778
            emailUtils.reportException(e);
779
            throw e;
780
        }
781
    }
782

    
783
    @Override
784
    public List<String> getDatasourceVocabularies(String mode) {
785

    
786
        List<String> resultSet = new ArrayList<>();
787
        for (Map.Entry<String, String> entry : this.getVocabulary("dnet:datasource_typologies").getAsMap().entrySet()) {
788
            if (mode.equalsIgnoreCase("aggregator")) {
789
                if (entry.getKey().contains("aggregator"))
790
                    resultSet.add(entry.getValue());
791
            } else if (mode.equalsIgnoreCase("journal")) {
792
                if (entry.getKey().contains("journal"))
793
                    resultSet.add(entry.getValue());
794
            } else if (mode.equalsIgnoreCase("opendoar")) {
795
                if (entry.getKey().contains("pubsrepository"))
796
                    resultSet.add(entry.getValue());
797
            } else if (mode.equalsIgnoreCase("re3data")) {
798
                if (entry.getKey().contains("datarepository"))
799
                    resultSet.add(entry.getValue());
800
            }
801
        }
802

    
803

    
804
        return resultSet;
805
    }
806

    
807
    private Vocabulary getVocabulary(String vocName) {
808

    
809
        if (!vocabularyMap.containsKey(vocName)) {
810
            vocabularyMap.put(vocName, vocabularyLoader.getVocabulary(vocName, Locale.ENGLISH, Locale.ROOT));
811
        }
812
        return vocabularyMap.get(vocName);
813
    }
814

    
815

    
816
    @Override
817
    public Map<String, String> getCompatibilityClasses(String mode) {
818

    
819
        LOGGER.debug("Getting compatibility classes for mode: " + mode);
820
        Map<String, String> retMap = new HashMap<String, String>();
821

    
822
        Map<String, String> compatibilityClasses = this.getVocabulary("dnet:compatibilityLevel").getAsMap();
823
        boolean foundData = false;
824
        for (Map.Entry<String, String> entry : compatibilityClasses.entrySet()) {
825
            if (mode.equalsIgnoreCase(Constants.REPOSITORY_MODE_ALL))
826
                return compatibilityClasses;
827
            else if (mode.equalsIgnoreCase(Constants.REPOSITORY_MODE_RE3DATA)) {
828
                if (entry.getKey().matches("^openaire[1-9].0_data$")) {
829
                    retMap.put(entry.getKey(), entry.getValue());
830
                    foundData = true;
831
                }
832
            } else {
833
                if (entry.getKey().matches("^openaire[1-9].0$") || entry.getKey().equals("driver"))
834
                    retMap.put(entry.getKey(), entry.getValue());
835
            }
836
        }
837

    
838
        //TODO TO BE REMOVED WHEN VOCABULARIES ARE UPDATED
839
        if (mode.equalsIgnoreCase(Constants.REPOSITORY_MODE_RE3DATA) && !foundData)
840
            retMap.put("openaire2.0_data", "OpenAIRE Data (funded, referenced datasets)");
841

    
842
        return retMap;
843
    }
844

    
845
    @Override
846
    public Map<String, String> getDatasourceClasses(String mode) {
847

    
848
        LOGGER.debug("Getting datasource classes for mode: " + mode);
849

    
850
        Map<String, String> retMap = new HashMap<String, String>();
851

    
852
        for (Map.Entry<String, String> entry : this.getVocabulary("dnet:datasource_typologies").getAsMap().entrySet()) {
853
            if (mode.equalsIgnoreCase("aggregator")) {
854
                if (entry.getKey().contains("aggregator"))
855
                    retMap.put(entry.getKey(), entry.getValue());
856
            } else if (mode.equalsIgnoreCase("journal")) {
857
                if (entry.getKey().contains("journal"))
858
                    retMap.put(entry.getKey(), entry.getValue());
859
            } else if (mode.equalsIgnoreCase("opendoar")) {
860
                if (entry.getKey().contains("pubsrepository"))
861
                    retMap.put(entry.getKey(), entry.getValue());
862
            } else if (mode.equalsIgnoreCase("re3data")) {
863
                if (entry.getKey().contains("datarepository"))
864
                    retMap.put(entry.getKey(), entry.getValue());
865
            }
866
        }
867
        return filterResults(retMap, mode);
868

    
869
    }
870

    
871
    private Map<String, String> filterResults(Map<String, String> map, String mode) {
872

    
873
        HashMap<String, String> filteredMap = new HashMap<>();
874
        for (String key : map.keySet())
875
            if (dataSourceClass.get(mode).contains(key))
876
                filteredMap.put(key, map.get(key));
877

    
878
        return filteredMap;
879
    }
880

    
881
    @Override
882
    public String getCountryName(String countryCode) {
883
        return inverseCountriesMap.get(countryCode);
884
    }
885

    
886
    @Override
887
    public MetricsInfo getMetricsInfoForRepository(String repoId) throws RepositoryServiceException {
888
        try {
889

    
890
            MetricsInfo metricsInfo = new MetricsInfo();
891
            metricsInfo.setDiagramsBaseURL(this.usageStatisticsDiagramsBaseURL);
892
            metricsInfo.setMetricsNumbers(getMetricsNumbers(getOpenAIREId(repoId)));
893
            return metricsInfo;
894

    
895
        } catch (Exception e) {
896
            LOGGER.error("Error while getting metrics info for repository: ", e);
897
            emailUtils.reportException(e);
898
            throw new RepositoryServiceException("General error", RepositoryServiceException.ErrorCode.GENERAL_ERROR);
899
        }
900
    }
901

    
902
    @Override
903
    public Map<String, String> getListLatestUpdate(String mode) throws JSONException {
904
        if (mode.equals("opendoar"))
905
            return Collections.singletonMap("lastCollectionDate", getRepositoryInterface("openaire____::" + mode).get(0).getLastCollectionDate());
906
        else
907
            /*
908
             * first api of re3data has null value on collection date
909
             * */
910
            return Collections.singletonMap("lastCollectionDate", getRepositoryInterface("openaire____::" + mode).get(1).getLastCollectionDate());
911
    }
912

    
913
    private void updateValidationSet(String repositoryId, String repositoryInterfaceId, String validationSet) throws Exception {
914
        UriComponents uriComponents = UriComponentsBuilder
915
                .fromHttpUrl(baseAddress + "/ds/api/oaiset")
916
                .queryParam("dsId", repositoryId)
917
                .queryParam("apiId", repositoryInterfaceId)
918
                .queryParam("oaiSet", validationSet)
919
                .build().encode();
920
        restTemplate.exchange(uriComponents.toUri(), HttpMethod.POST, null, ResponseEntity.class);
921

    
922
    }
923

    
924

    
925
    private void updateBaseUrl(String repositoryId, String repositoryInterfaceId, String baseUrl) {
926
        UriComponents uriComponents = UriComponentsBuilder
927
                .fromHttpUrl(baseAddress + "/ds/api/baseurl")
928
                .queryParam("dsId", repositoryId)
929
                .queryParam("apiId", repositoryInterfaceId)
930
                .queryParam("baseUrl", baseUrl)
931
                .build().encode();
932
        restTemplate.postForObject(uriComponents.toUri(), null, String.class);
933
    }
934

    
935
    private void updateCompliance(String repositoryId, String repositoryInterfaceId, String compliance) {
936
        UriComponents uriComponents = UriComponentsBuilder
937
                .fromHttpUrl(baseAddress + "/ds/api/compliance")
938
                .queryParam("dsId", repositoryId)
939
                .queryParam("apiId", repositoryInterfaceId)
940
                .queryParam("compliance", compliance)
941
                .build().encode();
942
        restTemplate.postForObject(uriComponents.toUri(), null, String.class);
943
    }
944

    
945
    private MetricsNumbers getMetricsNumbers(String openAIREID) throws BrokerException {
946

    
947
        //build the uri params
948
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(this.usageStatisticsNumbersBaseURL + openAIREID + "/clicks");
949

    
950
        //create new template engine
951
        RestTemplate template = new RestTemplate();
952
        template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
953
        ResponseEntity<MetricsNumbers> resp;
954
        try {
955
            //communicate with endpoint
956
            resp = template.exchange(
957
                    builder.build().encode().toUri(),
958
                    HttpMethod.GET,
959
                    null,
960
                    new ParameterizedTypeReference<MetricsNumbers>() {
961
                    });
962
        } catch (RestClientException e) {
963
            LOGGER.debug("Exception on getMetricsNumbers", e);
964
            emailUtils.reportException(e);
965
            throw e;
966
        }
967

    
968
        return resp.getBody();
969
    }
970

    
971
    private String getOpenAIREId(String repoId) {
972

    
973
        if (repoId != null && repoId.contains("::")) {
974
            return repoId.split("::")[0] + "::" + DigestUtils.md5Hex(repoId.split("::")[1]);
975
        }
976

    
977
        return null;
978
    }
979

    
980
    private UriComponents searchDatasource(String page, String size) {
981

    
982
        return UriComponentsBuilder
983
                .fromHttpUrl(baseAddress + "/ds/search/")
984
                .path("/{page}/{size}/")
985
                .queryParam("requestSortBy", "officialname")
986
                .queryParam("order", "ASCENDING")
987
                .build().expand(page, size).encode();
988
    }
989

    
990
    private UriComponents searchSnipperDatasource(String page, String size) {
991

    
992
        return UriComponentsBuilder
993
                .fromHttpUrl(baseAddress + "/ds/searchsnippet/")
994
                .path("/{page}/{size}/")
995
                .queryParam("requestSortBy", "officialname")
996
                .queryParam("order", "ASCENDING")
997
                .build().expand(page, size).encode();
998
    }
999

    
1000
    private UriComponents searchRegisteredDatasource(String requestSortBy, String order, String page, String size) {
1001

    
1002
        return UriComponentsBuilder
1003
                .fromHttpUrl(baseAddress + "/ds/searchregistered/")
1004
                .path("/{page}/{size}/")
1005
                .queryParam("requestSortBy", requestSortBy)
1006
                .queryParam("order", order)
1007
                .build().expand(page, size).encode();
1008
    }
1009

    
1010
    private String getRepositoryType(String typology) {
1011
        return invertedDataSourceClass.get(typology);
1012
    }
1013

    
1014
    private List<String> getRoleIdsFromUserRoles(String userEmail) {
1015
        Integer coPersonId = registryCalls.getCoPersonIdByEmail(userEmail);
1016
        JsonArray roles;
1017
        ArrayList<String> roleIds = new ArrayList<>();
1018
        ArrayList<Integer> couIds = new ArrayList<>();
1019
        if (coPersonId != null) {
1020
            roles = registryCalls.getRoles(coPersonId);
1021
            for (JsonElement role : roles) {
1022
                JsonObject object = role.getAsJsonObject();
1023
                if (object.get("CouId") == null) {
1024
                    continue;
1025
                }
1026
                couIds.add(object.get("CouId").getAsInt());
1027
            }
1028

    
1029
            roleIds.addAll(registryCalls.getCouNames(couIds).values());
1030

    
1031
        }
1032
        return roleIds;
1033
    }
1034

    
1035
    private List<String> getRepoIdsFromUserRoles(String userEmail) {
1036
        List<String> roleIds = getRoleIdsFromUserRoles(userEmail);
1037
        List<String> repoIds = new ArrayList<>();
1038
        for (String role : roleIds) {
1039
            if (role.contains("datasource")) {
1040
                // TODO: ask if checking for BETA prefix is required
1041
                repoIds.add(role.replaceFirst(".*datasource\\.", "").replace("$", ":"));
1042
            }
1043
        }
1044
        return repoIds;
1045
    }
1046
}
(12-12/20)