Project

General

Profile

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

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

    
31
import javax.annotation.PostConstruct;
32
import java.io.IOException;
33
import java.sql.Timestamp;
34
import java.util.*;
35
import java.util.concurrent.ConcurrentHashMap;
36
import java.util.stream.Collectors;
37

    
38
@Service("repositoryService")
39
public class RepositoryServiceImpl implements RepositoryService {
40

    
41
    @Value("${api.baseAddress}")
42
    private String baseAddress;
43

    
44
    @Value("${services.repo-manager.adminEmail}")
45
    private String adminEmail;
46

    
47
    @Autowired
48
    RestTemplate restTemplate;
49

    
50
    private HttpHeaders httpHeaders;
51

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

    
54
    private static final Logger LOGGER = Logger.getLogger(RepositoryServiceImpl.class);
55

    
56
    @Value("${services.repomanager.usageStatisticsDiagramsBaseURL}")
57
    private String usageStatisticsDiagramsBaseURL;
58

    
59
    @Value("${services.repomanager.usageStatisticsNumbersBaseURL}")
60
    private String usageStatisticsNumbersBaseURL;
61

    
62
    @Autowired
63
    private VocabularyLoader vocabularyLoader;
64

    
65
    @Autowired
66
    private PiWikService piWikService;
67

    
68
    @Autowired
69
    private EmailUtils emailUtils;
70

    
71
    @Autowired
72
    ValidatorService validatorService;
73

    
74

    
75
    private Map<String, Vocabulary> vocabularyMap = new ConcurrentHashMap<>();
76

    
77
    private Map<String, String> countriesMap = new HashMap<>();
78
    private Map<String, String> inverseCountriesMap = new HashMap<>();
79

    
80
    private static Map<String,List<String>> dataSourceClass = new HashMap<>();
81

    
82
    private static Map<String,String> invertedDataSourceClass = new HashMap<>();
83

    
84

    
85

    
86
    @PostConstruct
87
    private void init() {
88
        LOGGER.debug("Initialization method of repository api!");
89
        LOGGER.debug("Updated version!");
90

    
91
        dataSourceClass.put("opendoar",Arrays.asList("pubsrepository::institutional","pubsrepository::thematic","pubsrepository::unknown","pubsrepository::mock"));
92
        dataSourceClass.put("re3data", Collections.singletonList("datarepository::unknown"));
93
        dataSourceClass.put("journal", Collections.singletonList("pubsrepository::journal"));
94
        dataSourceClass.put("aggregator",Arrays.asList("aggregator::pubsrepository::institutional","aggregator::pubsrepository::journals","aggregator::datarepository", "aggregator::pubsrepository::unknown"));
95

    
96
        invertedDataSourceClass.put("pubsrepository::institutional","opendoar");
97
        invertedDataSourceClass.put("pubsrepository::thematic","opendoar");
98
        invertedDataSourceClass.put("pubsrepository::unknown","opendoar");
99
        invertedDataSourceClass.put("pubsrepository::mock","opendoar");
100
        invertedDataSourceClass.put("datarepository::unknown","re3data");
101
        invertedDataSourceClass.put("pubsrepository::journal","journal");
102
        invertedDataSourceClass.put("aggregator::pubsrepository::institutional","aggregator");
103
        invertedDataSourceClass.put("aggregator::pubsrepository::journals","aggregator");
104
        invertedDataSourceClass.put("aggregator::datarepository","aggregator");
105
        invertedDataSourceClass.put("aggregator::pubsrepository::unknown","aggregator");
106

    
107

    
108
        httpHeaders = new HttpHeaders();
109
        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
110

    
111
        for (String vocName : vocabularyNames) {
112
            vocabularyMap.put(vocName, vocabularyLoader.getVocabulary(vocName, Locale.ENGLISH, Locale.ROOT));
113
        }
114

    
115
        Country[] countries = getCountries();
116
        for (Country c : countries) {
117
            countriesMap.put(c.getName(), c.getCode());
118
            inverseCountriesMap.put(c.getCode(), c.getName());
119
        }
120

    
121

    
122
    }
123

    
124
    @Override
125
    public Country[] getCountries() {
126
        UriComponents uriComponents = UriComponentsBuilder
127
                .fromHttpUrl(baseAddress + "/ds/countries")
128
                .build().encode();
129
        return restTemplate.getForObject(uriComponents.toUri(), Country[].class);
130
    }
131

    
132

    
133
    @Override
134
    public List<RepositorySnippet> getRepositoriesByCountry(String country,
135
                                                            String mode,
136
                                                            Boolean managed) throws JSONException, IOException {
137

    
138
        LOGGER.debug("Getting repositories by country!");
139
        int page = 0;
140
        int size = 100;
141
        List<RepositorySnippet> resultSet = new ArrayList<>();
142
        ObjectMapper mapper = new ObjectMapper();
143

    
144
        String filterKey = "UNKNOWN";
145
        if (mode.equalsIgnoreCase("opendoar"))
146
            filterKey = "openaire____::opendoar";
147
        else if (mode.equalsIgnoreCase("re3data"))
148
            filterKey = "openaire____::re3data";
149

    
150

    
151
        LOGGER.debug("Country code equals : " + country);
152
        LOGGER.debug("Filter mode equals : " + filterKey);
153

    
154
        UriComponents uriComponents = searchSnipperDatasource(String.valueOf(page),String.valueOf(size));
155
        RequestFilter requestFilter = new RequestFilter();
156
        requestFilter.setCountry(country);
157
        requestFilter.setCollectedfrom(filterKey);
158

    
159
        try{
160
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
161
            JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
162
            while (jsonArray.length() > 0 ) {
163
                resultSet.addAll(mapper.readValue(String.valueOf(jsonArray),
164
                        mapper.getTypeFactory().constructCollectionType(List.class, RepositorySnippet.class)));
165
                page += 1;
166
                uriComponents = searchSnipperDatasource(String.valueOf(page),String.valueOf(size));
167
                rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
168
                jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
169
            }
170
            return resultSet;
171
        }catch (Exception e){
172
            LOGGER.debug("Exception on getRepositoriesByCountry" , e);
173
//            emailUtils.reportException(e);
174
            throw e;
175
        }
176
    }
177

    
178
    public List<RepositorySnippet> searchRegisteredRepositories(String country, String typology, String englishName,
179
            String officialName, String requestSortBy, String order, int page, int pageSize) throws Exception {
180

    
181
        LOGGER.debug("Searching registered repositories");
182

    
183
        List<RepositorySnippet> resultSet = new ArrayList<>();
184
        ObjectMapper mapper = new ObjectMapper();
185

    
186
        UriComponents uriComponents = searchRegisteredDatasource(requestSortBy, order, Integer.toString(page), Integer.toString(pageSize));
187

    
188
        RequestFilter requestFilter = new RequestFilter();
189
        requestFilter.setCountry(country);
190
        requestFilter.setTypology(typology);
191
        requestFilter.setOfficialname(officialName);
192
        requestFilter.setEnglishname(englishName);
193

    
194
        try {
195
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
196
            JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
197

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

    
200
             return resultSet;
201
        }catch (Exception e){
202
            LOGGER.error("Error searching registered datasources" , e);
203
            throw e;
204
        }
205
    }
206

    
207
    private Repository updateRepositoryInfo(Repository r) throws JSONException {
208

    
209
        /*
210
        * from datasource class
211
        * we get the datasource type form the inverted map
212
        * */
213
        r.setDatasourceType(getRepositoryType(r.getDatasourceClass()));
214
        r.setInterfaces(this.getRepositoryInterface(r.getId()));
215
        r.setPiwikInfo(piWikService.getPiwikSiteForRepo(r.getId()));
216
        r.setCountryName(getCountryName(r.getCountryCode()));
217
        return r;
218
    }
219

    
220

    
221
    private Collection<Repository> getRepositoriesByMode(String mode, List<Repository> rs) {
222

    
223
        List<Repository> reps = new ArrayList<>();
224
        for (Repository r : rs) {
225
            if (r.getCollectedFrom() != null && r.getCollectedFrom().equals(mode))
226
                reps.add(r);
227

    
228
        }
229
        return reps;
230
    }
231

    
232
    @Override
233
    public List<Repository> getRepositoriesOfUser(String userEmail,
234
                                                  String page,
235
                                                  String size) throws JSONException {
236

    
237
        LOGGER.debug("Retreiving repositories of user : " + userEmail );
238
        UriComponents uriComponents = searchDatasource(page,size);
239
        RequestFilter requestFilter = new RequestFilter();
240
        requestFilter.setRegisteredby(userEmail);
241

    
242
        try{
243
            long start = System.currentTimeMillis();
244
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
245
            long end = System.currentTimeMillis();
246

    
247
            System.out.println("POST request finished in " + (end-start)+"ms");
248
            start=System.currentTimeMillis();
249
            List<Repository> repos = Converter.jsonToRepositoryList(new JSONObject(rs));
250
            end=System.currentTimeMillis();
251
            System.out.println("Converting json to repo list finished in " + (end-start)+"ms");
252
            start=System.currentTimeMillis();
253
            for (Repository r : repos)
254
                r.setPiwikInfo(piWikService.getPiwikSiteForRepo(r.getId()));
255

    
256
            end=System.currentTimeMillis();
257
            System.out.println("Updating "+repos.size()+" repository infos in " + (end-start)+"ms");
258
            return repos;
259
        }catch (Exception e){
260
            LOGGER.debug("Exception on getRepositoriesOfUser" , e);
261
            emailUtils.reportException(e);
262
            throw e;
263
        }
264
    }
265

    
266
    @Override
267
    public Repository getRepositoryById(String id) throws JSONException,ResourceNotFoundException {
268

    
269
        LOGGER.debug("Retreiving repositories with id : " + id );
270
        Repository repo = null;
271
        UriComponents uriComponents = searchDatasource("0","100");
272
        RequestFilter requestFilter = new RequestFilter();
273
        requestFilter.setId(id);
274

    
275
        try{
276
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
277
            JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
278

    
279
            if(jsonArray.length() == 0)
280
                throw new ResourceNotFoundException();
281

    
282
            repo = Converter.jsonToRepositoryObject(jsonArray.getJSONObject(0));
283
            return updateRepositoryInfo(repo);
284
        }catch (JSONException e){
285
            LOGGER.debug("Exception on getRepositoryById" , e);
286
            emailUtils.reportException(e);
287
            throw e;
288
        }
289

    
290
    }
291

    
292

    
293
    @Override
294
    public List<AggregationDetails> getRepositoryAggregations(String id, int from, int size) throws JSONException {
295

    
296
        LOGGER.debug("Retreiving aggregations for repository with id : " + id );
297
        UriComponents uriComponents = searchDatasource(from+"",size+"");
298
        RequestFilter requestFilter = new RequestFilter();
299
        requestFilter.setId(id);
300

    
301
        List<AggregationDetails> aggregationHistory = new ArrayList<>();
302

    
303
        try {
304
            long start = System.currentTimeMillis();
305
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
306
            long end = System.currentTimeMillis();
307

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

    
311
            if(repository.getJSONArray("datasourceInfo").length() == 0)
312
                return aggregationHistory;
313

    
314
            start = System.currentTimeMillis();
315
            aggregationHistory.addAll(Converter.getAggregationHistoryFromJson(repository.getJSONArray("datasourceInfo").getJSONObject(0)));
316
            end = System.currentTimeMillis();
317

    
318
            System.out.println("Getting aggregations history from json " + (end-start)+"ms");
319
            return aggregationHistory.size() == 0? aggregationHistory : aggregationHistory.stream()
320
                                                    .sorted(Comparator.comparing(AggregationDetails::getDate).reversed())
321
                                                    .limit(size)
322
                                                    .collect(Collectors.toList());
323
        } catch (JSONException e) {
324
            LOGGER.debug("Exception on getRepositoryAggregations" , e);
325
            emailUtils.reportException(e);
326
            throw e;
327
        }
328

    
329
    }
330

    
331
    @Override
332
    public Map<String, List<AggregationDetails>> getRepositoryAggregationsByYear(String id) throws JSONException {
333
        LOGGER.debug("Retreiving aggregations (by year) for repository with id : " + id );
334
        UriComponents uriComponents = searchDatasource("0","100");
335
        RequestFilter requestFilter = new RequestFilter();
336
        requestFilter.setId(id);
337

    
338
        List<AggregationDetails> aggregationHistory = new ArrayList<>();
339
        Map<String, List<AggregationDetails>> aggregationByYear = new HashMap<>();
340
        try {
341
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
342
            JSONObject repository = new JSONObject(rs);
343

    
344
            if(repository.getJSONArray("datasourceInfo").length() == 0)
345
                return aggregationByYear;
346

    
347
            aggregationHistory.addAll(Converter.getAggregationHistoryFromJson(repository.getJSONArray("datasourceInfo").getJSONObject(0)));
348
            return aggregationHistory.size() == 0? aggregationByYear:createYearMap(aggregationHistory);
349

    
350
        } catch (JSONException e) {
351
            LOGGER.debug("Exception on getRepositoryAggregations" , e);
352
            emailUtils.reportException(e);
353
            throw e;
354
        }
355
    }
356

    
357
    private Map<String,List<AggregationDetails>> createYearMap(List<AggregationDetails> aggregationHistory) {
358
        Map<String, List<AggregationDetails>> aggregationByYear;
359
        aggregationHistory = aggregationHistory.stream()
360
                            .sorted(Comparator.comparing(AggregationDetails::getDate).reversed())
361
                            .collect(Collectors.toList());
362

    
363
       return aggregationHistory.stream()
364
                            .collect(Collectors.groupingBy(AggregationDetails::getYear));
365
    }
366

    
367

    
368
    @Override
369
    public List<Repository> getRepositoriesByName(String name,
370
                                                  String page,
371
                                                  String size) throws JSONException {
372

    
373
        LOGGER.debug("Retreiving  repositories with official name : " + name );
374
        UriComponents uriComponents = searchDatasource("0","100");
375
        RequestFilter requestFilter = new RequestFilter();
376
        requestFilter.setOfficialname(name);
377

    
378
        try{
379
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
380
            List<Repository> repos = Converter.jsonToRepositoryList(new JSONObject(rs));
381
            for (Repository r : repos)
382
                updateRepositoryInfo(r);
383
            return repos;
384
        }catch (Exception e){
385
            LOGGER.debug("Exception on getRepositoriesByName" , e);
386
            emailUtils.reportException(e);
387
            throw e;
388
        }
389

    
390
    }
391

    
392
    @Override
393
    public List<RepositoryInterface> getRepositoryInterface(String id) throws JSONException {
394

    
395
        UriComponents uriComponents = UriComponentsBuilder
396
                .fromHttpUrl(baseAddress + "/ds/api/")
397
                .path("/{id}")
398
                .build().expand(id).encode();
399

    
400
        try{
401
            String rs = restTemplate.getForObject(uriComponents.toUri(), String.class);
402
            return Converter.jsonToRepositoryInterfaceList(new JSONObject(rs));
403
        }catch (Exception e ){
404
            LOGGER.debug("Exception on getRepositoryInterface" , e);
405
            emailUtils.reportException(e);
406
            throw e;
407
        }
408

    
409
    }
410

    
411
    @Override
412
    public Repository addRepository(String datatype,
413
                                    Repository repository) throws Exception {
414

    
415
        LOGGER.debug("storing " + datatype + " repository with id: " + repository.getId());
416

    
417
        repository.setCountryCode(countriesMap.get(repository.getCountryName()));
418
        repository.setActivationId(UUID.randomUUID().toString());
419
        repository.setCollectedFrom("infrastruct_::openaire");
420

    
421
        if (datatype.equals("journal")) {
422
            repository.setId("openaire____::issn" + repository.getIssn());
423
            repository.setNamespacePrefix("issn" + repository.getIssn());
424
            this.storeRepository(repository, SecurityContextHolder.getContext().getAuthentication());
425
        }else if (datatype.equals("aggregator")) {
426
            repository.setId("openaire____::" + com.unboundid.util.Base64.encode(repository.getOfficialName()));
427
            repository.setNamespacePrefix(DigestUtils.md5Hex(repository.getOfficialName()).substring(0,12));
428
            this.storeRepository(repository, SecurityContextHolder.getContext().getAuthentication());
429
        }else {
430
            this.latentUpdate(repository, SecurityContextHolder.getContext().getAuthentication());
431
        }
432

    
433
        return repository;
434
    }
435

    
436
    /* update method acting as add -> send email with registration topic/body*/
437
    private Repository latentUpdate(Repository repository, Authentication authentication) throws Exception {
438
        UriComponents uriComponents = UriComponentsBuilder
439
                .fromHttpUrl(baseAddress + "/ds/update/")
440
                .build()
441
                .encode();
442

    
443
        try {
444
            String json_repository = Converter.repositoryObjectToJson(repository);
445
            LOGGER.debug("JSON to add(update) -> " + json_repository);
446

    
447
            HttpEntity<String> httpEntity = new HttpEntity<String>(json_repository, httpHeaders);
448
            ResponseEntity responseEntity = restTemplate.exchange(uriComponents.toUri(),HttpMethod.POST, httpEntity, ResponseEntity.class);
449

    
450
            if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
451
                emailUtils.sendUserRegistrationEmail(repository, authentication);
452
                emailUtils.sendAdminRegistrationEmail(repository, authentication);
453
            } else
454
                LOGGER.debug(responseEntity.getBody().toString());
455

    
456
            return repository;
457
        } catch (Exception e) {
458
            LOGGER.debug("Exception on updateRepository" , e);
459
            emailUtils.reportException(e);
460
            throw e;
461
        }
462

    
463

    
464
    }
465

    
466
    @Override
467
    public Repository updateRepository(Repository repository,Authentication authentication) throws Exception {
468
        UriComponents uriComponents = UriComponentsBuilder
469
                .fromHttpUrl(baseAddress + "/ds/update/")
470
                .build()
471
                .encode();
472

    
473
        try {
474
            String json_repository = Converter.repositoryObjectToJson(repository);
475

    
476
            LOGGER.debug("JSON to update -> " + json_repository);
477

    
478
            HttpEntity<String> httpEntity = new HttpEntity<String>(json_repository, httpHeaders);
479
            ResponseEntity responseEntity = restTemplate.exchange(uriComponents.toUri(),HttpMethod.POST, httpEntity
480
                    , ResponseEntity.class);
481

    
482
            if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
483
                emailUtils.sendUserUpdateRepositoryEmail(repository, authentication);
484
                emailUtils.sendAdminUpdateRepositoryEmail(repository, authentication);
485
            } else
486
                LOGGER.debug(responseEntity.getBody().toString());
487

    
488
            return repository;
489
        } catch (Exception e) {
490
            LOGGER.debug("Exception on updateRepository" , e);
491
            emailUtils.reportException(e);
492
            throw e;
493
        }
494
    }
495

    
496
    private void storeRepository(Repository repository, Authentication authentication) throws Exception {
497

    
498
        Date utilDate = new Date();
499
        Timestamp date = new Timestamp(utilDate.getTime());
500
        repository.setDateOfCollection(date);
501
        repository.setAggregator("OPENAIRE");
502
        repository.setCountryCode(countriesMap.get(repository.getCountryName()));
503

    
504
        UriComponents uriComponents = UriComponentsBuilder
505
                .fromHttpUrl(baseAddress + "/ds/add/")
506
                .build()
507
                .encode();
508
        String json_repository = Converter.repositoryObjectToJson(repository);
509
        HttpEntity<String> httpEntity = new HttpEntity <String> (json_repository,httpHeaders);
510
        ResponseEntity responseEntity = restTemplate.exchange(uriComponents.toUri(),HttpMethod.POST, httpEntity, ResponseEntity.class);
511

    
512
        if(responseEntity.getStatusCode().equals(HttpStatus.OK)) {
513
            emailUtils.sendUserRegistrationEmail(repository, authentication);
514
            emailUtils.sendAdminRegistrationEmail(repository, authentication);
515
        } else {
516
            LOGGER.debug(responseEntity.getBody().toString());
517
        }
518
    }
519

    
520
    @Override
521
    public void deleteRepositoryInterface(String id ,
522
                                          String registeredBy){
523
        UriComponents uriComponents = UriComponentsBuilder
524
                .fromHttpUrl(baseAddress + "/ds/api/")
525
                .path("/{id}")
526
                .build().expand(id).encode();
527
        LOGGER.debug(uriComponents.toUri());
528
        restTemplate.delete(uriComponents.toUri());
529
    }
530

    
531
    @Override
532
    public RepositoryInterface addRepositoryInterface(String datatype,
533
                                                      String repoId,
534
                                                      String registeredBy,
535
                                                      RepositoryInterface repositoryInterface) throws JSONException, ResourceNotFoundException, ValidatorServiceException {
536
        try {
537
            Repository e = this.getRepositoryById(repoId);
538
            repositoryInterface = createRepositoryInterface(e,repositoryInterface,datatype);
539
            String json_interface = Converter.repositoryInterfaceObjectToJson(e,repositoryInterface);
540

    
541
            UriComponents uriComponents = UriComponentsBuilder
542
                    .fromHttpUrl(baseAddress + "/ds/api/add/")
543
                    .build()
544
                    .encode();
545

    
546
            HttpEntity<String> httpEntity = new HttpEntity <> (json_interface,httpHeaders);
547
            restTemplate.postForObject(uriComponents.toUri(),httpEntity,String.class);
548
            submitInterfaceValidation(e, registeredBy, repositoryInterface, false);
549

    
550
            return repositoryInterface;
551

    
552
        } catch (JSONException | ValidatorServiceException e) {
553
            LOGGER.debug("Exception on addRepositoryInterface" , e);
554
            emailUtils.reportException(e);
555
            throw e;
556
        }
557
    }
558

    
559
    @Override
560
    public RepositoryInterface updateRepositoryInterface(String repoId,
561
                                                         String registeredBy,
562
                                                         RepositoryInterface repositoryInterface) throws Exception {
563

    
564
        this.updateBaseUrl(repoId,repositoryInterface.getId(),repositoryInterface.getBaseUrl());
565
        this.updateCompliance(repoId,repositoryInterface.getId(),repositoryInterface.getCompliance());
566
        this.updateValidationSet(repoId,repositoryInterface.getId(),repositoryInterface.getAccessSet());
567
        submitInterfaceValidation(getRepositoryById(repoId),registeredBy,repositoryInterface,true);
568
        return repositoryInterface;
569
    }
570

    
571
    private void submitInterfaceValidation(Repository repo, String userEmail, RepositoryInterface iFace, boolean updateExisting) throws ValidatorServiceException {
572
        JobForValidation job = new JobForValidation();
573

    
574
        job.setActivationId(UUID.randomUUID().toString());
575
        job.setAdminEmails(Collections.singletonList(this.adminEmail));
576
        job.setBaseUrl(iFace.getBaseUrl());
577
        job.setDatasourceId(repo.getId());
578
        job.setDesiredCompatibilityLevel(iFace.getDesiredCompatibilityLevel());
579
        job.setInterfaceId(iFace.getId());
580
        job.setOfficialName(repo.getOfficialName());
581
        job.setRepoType(repo.getDatasourceType());
582
        job.setUserEmail(userEmail);
583
        job.setValidationSet((iFace.getAccessSet().isEmpty() ? "none" : iFace.getAccessSet()));
584
        job.setRecords(-1);
585
        job.setRegistration(!updateExisting);
586
        job.setUpdateExisting(updateExisting);
587

    
588
        this.validatorService.submitJobForValidation(job);
589
    }
590

    
591
    private RepositoryInterface createRepositoryInterface(Repository repo, RepositoryInterface iFace, String datatype) {
592

    
593
        iFace.setContentDescription("metadata");
594
        iFace.setCompliance("UNKNOWN");
595

    
596
        if (datatype.equals("re3data"))
597
            iFace.setAccessFormat("oai_datacite");
598
        else
599
            iFace.setAccessFormat("oai_dc");
600

    
601

    
602
        if (repo.getDatasourceClass() != null && !repo.getDatasourceClass().isEmpty())
603
            iFace.setTypology(repo.getDatasourceClass());
604
        else if (datatype.equalsIgnoreCase("journal"))
605
            iFace.setTypology("pubsrepository::journal");
606
        else if (datatype.equalsIgnoreCase("aggregator"))
607
            iFace.setTypology("aggregator::pubsrepository::unknown");
608
        else if (datatype.equalsIgnoreCase("opendoar"))
609
            iFace.setTypology("pubsrepository::unknown");
610
        else if (datatype.equalsIgnoreCase("re3data"))
611
            iFace.setTypology("datarepository::unknown");
612

    
613
        iFace.setRemovable(true);
614
        iFace.setAccessProtocol("oai");
615
        iFace.setMetadataIdentifierPath("//*[local-name()='header']/*[local-name()='identifier']");
616
        iFace.setId("api_________::" + repo.getId() + "::" + UUID.randomUUID().toString().substring(0, 8));
617
        if (iFace.getAccessSet() == null || iFace.getAccessSet().isEmpty()) {
618
            LOGGER.debug("set is empty: " + iFace.getAccessSet());
619
            iFace.removeAccessSet();
620
            iFace.setAccessSet("none");
621
        }
622
        return iFace;
623
    }
624

    
625
    @Override
626
    public List<String> getDnetCountries() {
627
        LOGGER.debug("Getting dnet-countries!");
628
        return Converter.readFile("countries.txt");
629
    }
630

    
631
    @Override
632
    public List<String> getTypologies() {
633
        return Converter.readFile("typologies.txt");
634
    }
635

    
636
    @Override
637
    public List<Timezone> getTimezones() {
638
        List<String> timezones =  Converter.readFile("timezones.txt");
639
        return Converter.toTimezones(timezones);
640
    }
641

    
642
    @Override
643
    public List<String> getUrlsOfUserRepos(String userEmail,
644
                                           String page,
645
                                           String size){
646
        UriComponents uriComponents = UriComponentsBuilder
647
                .fromHttpUrl(baseAddress + "/api/baseurl/")
648
                .path("/{page}/{size}")
649
                .build().expand(page,size).encode();
650

    
651
        try{
652
            RequestFilter requestFilter = new RequestFilter();
653
            requestFilter.setRegisteredby(userEmail);
654
            return Arrays.asList(restTemplate.postForObject(uriComponents.toUri(),requestFilter, String[].class));
655
        }catch (Exception e){
656
            LOGGER.debug("Exception on addRepositoryInterface" , e);
657
            emailUtils.reportException(e);
658
            throw e;
659
        }
660
    }
661

    
662
    @Override
663
    public List<String> getDatasourceVocabularies(String mode) {
664

    
665
        List<String> resultSet = new ArrayList<>();
666
        for (Map.Entry<String, String> entry : this.getVocabulary("dnet:datasource_typologies").getAsMap().entrySet()) {
667
            if (mode.equalsIgnoreCase("aggregator")) {
668
                if (entry.getKey().contains("aggregator"))
669
                    resultSet.add(entry.getValue());
670
            } else if (mode.equalsIgnoreCase("journal")) {
671
                if (entry.getKey().contains("journal"))
672
                    resultSet.add(entry.getValue());
673
            } else if (mode.equalsIgnoreCase("opendoar")) {
674
                if (entry.getKey().contains("pubsrepository"))
675
                    resultSet.add(entry.getValue());
676
            } else if (mode.equalsIgnoreCase("re3data")) {
677
                if (entry.getKey().contains("datarepository"))
678
                    resultSet.add(entry.getValue());
679
            }
680
        }
681

    
682

    
683
        return resultSet;
684
    }
685

    
686
    private Vocabulary getVocabulary(String vocName) {
687

    
688
        if (!vocabularyMap.containsKey(vocName)) {
689
            vocabularyMap.put(vocName, vocabularyLoader.getVocabulary(vocName, Locale.ENGLISH, Locale.ROOT));
690
        }
691
        return vocabularyMap.get(vocName);
692
    }
693

    
694

    
695
    @Override
696
    public Map<String, String> getCompatibilityClasses(String mode)  {
697

    
698
        LOGGER.debug("Getting compatibility classes for mode: " + mode);
699
        Map<String, String> retMap = new HashMap<String, String>();
700

    
701
        Map<String, String> compatibilityClasses = this.getVocabulary("dnet:compatibilityLevel").getAsMap();
702
        boolean foundData = false;
703
        for (Map.Entry<String, String> entry : compatibilityClasses.entrySet()) {
704
            if (mode.equalsIgnoreCase(Constants.REPOSITORY_MODE_ALL))
705
                return compatibilityClasses;
706
            else if (mode.equalsIgnoreCase(Constants.REPOSITORY_MODE_RE3DATA)) {
707
                if (entry.getKey().matches("^openaire[1-9].0_data$")) {
708
                    retMap.put(entry.getKey(), entry.getValue());
709
                    foundData = true;
710
                }
711
            } else {
712
                if (entry.getKey().matches("^openaire[1-9].0$") || entry.getKey().equals("driver"))
713
                    retMap.put(entry.getKey(), entry.getValue());
714
            }
715
        }
716

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

    
721
        return retMap;
722
    }
723

    
724
    @Override
725
    public Map<String, String> getDatasourceClasses(String mode)  {
726

    
727
        LOGGER.debug("Getting datasource classes for mode: " + mode);
728

    
729
        Map<String, String> retMap = new HashMap<String, String>();
730

    
731
        for (Map.Entry<String, String> entry : this.getVocabulary("dnet:datasource_typologies").getAsMap().entrySet()) {
732
            if (mode.equalsIgnoreCase("aggregator")) {
733
                if (entry.getKey().contains("aggregator"))
734
                    retMap.put(entry.getKey(), entry.getValue());
735
            } else if (mode.equalsIgnoreCase("journal")) {
736
                if (entry.getKey().contains("journal"))
737
                    retMap.put(entry.getKey(), entry.getValue());
738
            } else if (mode.equalsIgnoreCase("opendoar")) {
739
                if (entry.getKey().contains("pubsrepository"))
740
                    retMap.put(entry.getKey(), entry.getValue());
741
            } else if (mode.equalsIgnoreCase("re3data")) {
742
                if (entry.getKey().contains("datarepository"))
743
                    retMap.put(entry.getKey(), entry.getValue());
744
            }
745
        }
746
        return filterResults(retMap,mode);
747

    
748
    }
749

    
750
    private Map<String,String> filterResults(Map<String, String> map,String mode) {
751

    
752
        HashMap<String,String> filteredMap = new HashMap<>();
753
        for(String key:map.keySet())
754
            if(dataSourceClass.get(mode).contains(key))
755
                filteredMap.put(key,map.get(key));
756

    
757
        return filteredMap;
758
    }
759

    
760
    @Override
761
    public String getCountryName(String countryCode) {
762
        return inverseCountriesMap.get(countryCode);
763
    }
764

    
765
    @Override
766
    public MetricsInfo getMetricsInfoForRepository(String repoId) throws RepositoryServiceException {
767
        try {
768

    
769
            MetricsInfo metricsInfo = new MetricsInfo();
770
            metricsInfo.setDiagramsBaseURL(this.usageStatisticsDiagramsBaseURL);
771
            metricsInfo.setMetricsNumbers(getMetricsNumbers(getOpenAIREId(repoId)));
772
            return metricsInfo;
773

    
774
        } catch (Exception e) {
775
            LOGGER.error("Error while getting metrics info for repository: ", e);
776
            emailUtils.reportException(e);
777
            throw new RepositoryServiceException("General error", RepositoryServiceException.ErrorCode.GENERAL_ERROR);
778
        }
779
    }
780

    
781
    @Override
782
    public Map<String, String> getListLatestUpdate(String mode) throws JSONException {
783
        if(mode.equals("opendoar"))
784
            return Collections.singletonMap("lastCollectionDate", getRepositoryInterface("openaire____::"+mode).get(0).getLastCollectionDate());
785
        else
786
            /*
787
            * first api of re3data has null value on collection date
788
            * */
789
            return Collections.singletonMap("lastCollectionDate", getRepositoryInterface("openaire____::"+mode).get(1).getLastCollectionDate());
790
    }
791

    
792
    private void updateValidationSet(String repositoryId, String repositoryInterfaceId, String validationSet) throws Exception {
793
        UriComponents uriComponents = UriComponentsBuilder
794
                .fromHttpUrl(baseAddress + "/ds/api/oaiset")
795
                .queryParam("dsId",repositoryId)
796
                .queryParam("apiId",repositoryInterfaceId)
797
                .queryParam("oaiSet",validationSet)
798
                .build().encode();
799
       restTemplate.exchange(uriComponents.toUri(),HttpMethod.POST, null, ResponseEntity.class);
800

    
801
    }
802

    
803

    
804
    private void updateBaseUrl(String repositoryId, String repositoryInterfaceId, String baseUrl) {
805
        UriComponents uriComponents = UriComponentsBuilder
806
                .fromHttpUrl(baseAddress + "/ds/api/baseurl")
807
                .queryParam("dsId",repositoryId)
808
                .queryParam("apiId",repositoryInterfaceId)
809
                .queryParam("baseUrl",baseUrl)
810
                .build().encode();
811
        restTemplate.postForObject(uriComponents.toUri(),null,String.class);
812
    }
813

    
814
    private void updateCompliance(String repositoryId, String repositoryInterfaceId,String compliance) {
815
        UriComponents uriComponents = UriComponentsBuilder
816
                .fromHttpUrl(baseAddress + "/ds/api/compliance")
817
                .queryParam("dsId",repositoryId)
818
                .queryParam("apiId",repositoryInterfaceId)
819
                .queryParam("compliance",compliance)
820
                .build().encode();
821
        restTemplate.postForObject(uriComponents.toUri(),null,String.class);
822
    }
823

    
824
    private MetricsNumbers getMetricsNumbers(String openAIREID) throws BrokerException {
825

    
826
        //build the uri params
827
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(this.usageStatisticsNumbersBaseURL + openAIREID + "/clicks");
828

    
829
        //create new template engine
830
        RestTemplate template = new RestTemplate();
831
        template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
832
        ResponseEntity<MetricsNumbers> resp;
833
        try {
834
            //communicate with endpoint
835
            resp = template.exchange(
836
                    builder.build().encode().toUri(),
837
                    HttpMethod.GET,
838
                    null,
839
                    new ParameterizedTypeReference<MetricsNumbers>() {
840
                    });
841
        } catch (RestClientException e) {
842
            LOGGER.debug("Exception on getMetricsNumbers" , e);
843
            emailUtils.reportException(e);
844
            throw e;
845
        }
846

    
847
        return resp.getBody();
848
    }
849

    
850
    private String getOpenAIREId(String repoId) {
851

    
852
        if (repoId != null && repoId.contains("::")) {
853
            return repoId.split("::")[0] + "::" + DigestUtils.md5Hex(repoId.split("::")[1]);
854
        }
855

    
856
        return null;
857
    }
858

    
859
    private UriComponents searchDatasource(String page,String size){
860

    
861
        return UriComponentsBuilder
862
                .fromHttpUrl(baseAddress + "/ds/search/")
863
                .path("/{page}/{size}/")
864
                .queryParam("requestSortBy","officialname")
865
                .queryParam("order","ASCENDING")
866
                .build().expand(page, size).encode();
867
    }
868

    
869
    private UriComponents searchSnipperDatasource(String page,String size){
870

    
871
        return UriComponentsBuilder
872
                .fromHttpUrl(baseAddress + "/ds/searchsnippet/")
873
                .path("/{page}/{size}/")
874
                .queryParam("requestSortBy","officialname")
875
                .queryParam("order","ASCENDING")
876
                .build().expand(page, size).encode();
877
    }
878

    
879
    private UriComponents searchRegisteredDatasource(String requestSortBy, String order, String page,String size){
880

    
881
        return UriComponentsBuilder
882
                .fromHttpUrl(baseAddress + "/ds/searchregistered/")
883
                .path("/{page}/{size}/")
884
                .queryParam("requestSortBy",requestSortBy)
885
                .queryParam("order",order)
886
                .build().expand(page, size).encode();
887
    }
888

    
889
    private String getRepositoryType(String typology){
890
        return invertedDataSourceClass.get(typology);
891
    }
892

    
893

    
894
}
(12-12/20)