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.utils.AuthorizationService;
16
import eu.dnetlib.repo.manager.utils.Converter;
17
import gr.uoa.di.driver.enabling.vocabulary.VocabularyLoader;
18
import org.apache.commons.codec.digest.DigestUtils;
19
import org.apache.log4j.Logger;
20
import org.json.JSONArray;
21
import org.json.JSONException;
22
import org.json.JSONObject;
23
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
24
import org.springframework.beans.factory.annotation.Autowired;
25
import org.springframework.beans.factory.annotation.Value;
26
import org.springframework.core.ParameterizedTypeReference;
27
import org.springframework.http.*;
28
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
29
import org.springframework.security.core.Authentication;
30
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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 javax.ws.rs.core.Response;
40
import java.io.IOException;
41
import java.sql.Timestamp;
42
import java.util.*;
43
import java.util.concurrent.ConcurrentHashMap;
44
import java.util.stream.Collectors;
45

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

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

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

    
55
    @Autowired
56
    RestTemplate restTemplate;
57

    
58
    private HttpHeaders httpHeaders;
59

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

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

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

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

    
70
    @Autowired
71
    private VocabularyLoader vocabularyLoader;
72

    
73
    @Autowired
74
    private PiWikService piWikService;
75

    
76
    @Autowired
77
    private EmailUtils emailUtils;
78

    
79
    @Autowired
80
    ValidatorService validatorService;
81

    
82
    @Autowired
83
    private AaiUserRoleService calls;
84

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

    
89
    @Autowired
90
    private AuthorizationService authorizationService;
91

    
92

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

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

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

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

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

    
107

    
108

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

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

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

    
130

    
131
        httpHeaders = new HttpHeaders();
132
        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
133

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

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

    
144

    
145
    }
146

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

    
155

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

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

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

    
173

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

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

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

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

    
204
        LOGGER.debug("Searching registered repositories");
205

    
206
        List<RepositorySnippet> resultSet = new ArrayList<>();
207
        ObjectMapper mapper = new ObjectMapper();
208

    
209
        UriComponents uriComponents = searchRegisteredDatasource(requestSortBy, order, Integer.toString(page), Integer.toString(pageSize));
210

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

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

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

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

    
230
    private Repository updateRepositoryInfo(Repository r) throws JSONException {
231

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

    
243

    
244
    private Collection<Repository> getRepositoriesByMode(String mode, List<Repository> rs) {
245

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

    
251
        }
252
        return reps;
253
    }
254

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

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

    
265
        try{
266
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
267

    
268
            List<Repository> repos = Converter.jsonToRepositoryList(new JSONObject(rs));
269
            for (Repository r : repos)
270
                r.setPiwikInfo(piWikService.getPiwikSiteForRepo(r.getId()));
271
            return repos;
272
        }catch (Exception e){
273
            LOGGER.debug("Exception on getRepositoriesOfUser" , e);
274
            emailUtils.reportException(e);
275
            throw e;
276
        }
277
    }
278

    
279
    @Override
280
    public List<RepositorySnippet> getRepositoriesSnippetOfUser(String userEmail, String page, String size) throws IOException, JSONException {
281

    
282
        // TODO: Antonis K. - Change the below content. get repos of User by his roles
283
        // TODO: Step 1 - Get all roles (cous) of the user
284
        // TODO: From the result replace $$ with ::
285
        // TODO: Step 2 - For each role call getRepositoryById to get the repositoryId
286
        // TODO: Step 3 - For each repo from the previous step call findByRepositoryId piwik_site to get the full info of repo
287
        Integer coPersonId = calls.getCoPersonIdByEmail(userEmail);
288
        JsonArray roles;
289
        ArrayList<String> rolesId = new ArrayList<>();
290
        if (coPersonId != null ) {
291
            roles = calls.getRoles(coPersonId);
292
            for (JsonElement role : roles) {
293
                JsonObject object = role.getAsJsonObject();
294
                String roleStr = object.get("Name").getAsString().replaceAll(":", "$");
295
                String repoBareId = calls.getRepoNameWithoutType(roleStr, "datasource.");
296
                rolesId.add(roleStr);
297
            }
298
        }
299

    
300
        List<RepositorySnippet> resultSet = new ArrayList<>();
301
        ObjectMapper mapper = new ObjectMapper();
302

    
303
        // here page should be 0
304
        UriComponents uriComponents = searchSnipperDatasource(page,size);
305
        RequestFilter requestFilter = new RequestFilter();
306

    
307
        for ( int i = 0; i < rolesId.size(); i++ ) {
308
            if ( rolesId.get(i) != "ROLE_ADMIN" && rolesId.get(i) != "ROLE_PROVIDE_ADMIN" && rolesId.get(i) != "ROLE_USER" )
309
            requestFilter.setId(rolesId.get(i));
310

    
311
            try{
312
                String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
313
                JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
314
                resultSet.addAll(mapper.readValue(String.valueOf(jsonArray),
315
                        mapper.getTypeFactory().constructCollectionType(List.class, RepositorySnippet.class)));
316
            }catch (Exception e){
317
                LOGGER.debug("Exception on getRepositoriesByCountry" , e);
318
                throw e;
319
            }
320
        }
321
        System.out.println("resultSet:" + resultSet);
322
        resultSet.parallelStream().forEach(repositorySnippet -> {
323
            repositorySnippet.setPiwikInfo(piWikService.getPiwikSiteForRepo(repositorySnippet.getId()));
324
        });
325
        return resultSet;
326
    }
327

    
328
    @Override
329
    public RepositorySnippet getRepositorySnippetById(String id) throws JSONException,ResourceNotFoundException {
330

    
331
        LOGGER.debug("Retreiving repositories with id : " + id );
332
        RepositorySnippet repo = null;
333
        UriComponents uriComponents = searchSnipperDatasource("0","100");
334
        RequestFilter requestFilter = new RequestFilter();
335
        requestFilter.setId(id);
336

    
337
        try{
338
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
339
            JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
340

    
341
            if(jsonArray.length() == 0)
342
                throw new ResourceNotFoundException();
343

    
344
            repo = Converter.jsonToRepositorySnippetObject(jsonArray.getJSONObject(0));
345
            return repo;
346
        }catch (JSONException e){
347
            LOGGER.debug("Exception on getRepositoryById" , e);
348
            emailUtils.reportException(e);
349
            throw e;
350
        }
351

    
352
    }
353

    
354
    @Override
355
    public Repository getRepositoryById(String id) throws JSONException,ResourceNotFoundException {
356

    
357
        LOGGER.debug("Retreiving repositories with id : " + id );
358
        Repository repo = null;
359
        UriComponents uriComponents = searchDatasource("0","100");
360
        RequestFilter requestFilter = new RequestFilter();
361
        requestFilter.setId(id);
362

    
363
        try{
364
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
365
            JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
366

    
367
            if(jsonArray.length() == 0)
368
                throw new ResourceNotFoundException();
369

    
370
            repo = Converter.jsonToRepositoryObject(jsonArray.getJSONObject(0));
371
            return updateRepositoryInfo(repo);
372
        }catch (JSONException e){
373
            LOGGER.debug("Exception on getRepositoryById" , e);
374
            emailUtils.reportException(e);
375
            throw e;
376
        }
377

    
378
    }
379

    
380

    
381
    @Override
382
    public List<AggregationDetails> getRepositoryAggregations(String id, int from, int size) throws JSONException {
383

    
384
        LOGGER.debug("Retreiving aggregations for repository with id : " + id );
385
        UriComponents uriComponents = searchDatasource(from+"",size+"");
386
        RequestFilter requestFilter = new RequestFilter();
387
        requestFilter.setId(id);
388

    
389
        List<AggregationDetails> aggregationHistory = new ArrayList<>();
390

    
391
        try {
392
            long start = System.currentTimeMillis();
393
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
394
            long end = System.currentTimeMillis();
395

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

    
399
            if(repository.getJSONArray("datasourceInfo").length() == 0)
400
                return aggregationHistory;
401

    
402
            start = System.currentTimeMillis();
403
            aggregationHistory.addAll(Converter.getAggregationHistoryFromJson(repository.getJSONArray("datasourceInfo").getJSONObject(0)));
404
            end = System.currentTimeMillis();
405

    
406
            System.out.println("Getting aggregations history from json " + (end-start)+"ms");
407
            return aggregationHistory.size() == 0? aggregationHistory : aggregationHistory.stream()
408
                                                    .sorted(Comparator.comparing(AggregationDetails::getDate).reversed())
409
                                                    .limit(size)
410
                                                    .collect(Collectors.toList());
411
        } catch (JSONException e) {
412
            LOGGER.debug("Exception on getRepositoryAggregations" , e);
413
            emailUtils.reportException(e);
414
            throw e;
415
        }
416

    
417
    }
418

    
419
    @Override
420
    public Map<String, List<AggregationDetails>> getRepositoryAggregationsByYear(String id) throws JSONException {
421
        LOGGER.debug("Retreiving aggregations (by year) for repository with id : " + id );
422
        UriComponents uriComponents = searchDatasource("0","100");
423
        RequestFilter requestFilter = new RequestFilter();
424
        requestFilter.setId(id);
425

    
426
        List<AggregationDetails> aggregationHistory = new ArrayList<>();
427
        Map<String, List<AggregationDetails>> aggregationByYear = new HashMap<>();
428
        try {
429
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
430
            JSONObject repository = new JSONObject(rs);
431

    
432
            if(repository.getJSONArray("datasourceInfo").length() == 0)
433
                return aggregationByYear;
434

    
435
            aggregationHistory.addAll(Converter.getAggregationHistoryFromJson(repository.getJSONArray("datasourceInfo").getJSONObject(0)));
436
            return aggregationHistory.size() == 0? aggregationByYear:createYearMap(aggregationHistory);
437

    
438
        } catch (JSONException e) {
439
            LOGGER.debug("Exception on getRepositoryAggregations" , e);
440
            emailUtils.reportException(e);
441
            throw e;
442
        }
443
    }
444

    
445
    private Map<String,List<AggregationDetails>> createYearMap(List<AggregationDetails> aggregationHistory) {
446
        Map<String, List<AggregationDetails>> aggregationByYear;
447
        aggregationHistory = aggregationHistory.stream()
448
                            .sorted(Comparator.comparing(AggregationDetails::getDate).reversed())
449
                            .collect(Collectors.toList());
450

    
451
       return aggregationHistory.stream()
452
                            .collect(Collectors.groupingBy(AggregationDetails::getYear));
453
    }
454

    
455

    
456
    @Override
457
    public List<Repository> getRepositoriesByName(String name,
458
                                                  String page,
459
                                                  String size) throws JSONException {
460

    
461
        LOGGER.debug("Retreiving  repositories with official name : " + name );
462
        UriComponents uriComponents = searchDatasource("0","100");
463
        RequestFilter requestFilter = new RequestFilter();
464
        requestFilter.setOfficialname(name);
465

    
466
        try{
467
            String rs = restTemplate.postForObject(uriComponents.toUri(),requestFilter, String.class);
468
            List<Repository> repos = Converter.jsonToRepositoryList(new JSONObject(rs));
469
            for (Repository r : repos)
470
                updateRepositoryInfo(r);
471
            return repos;
472
        }catch (Exception e){
473
            LOGGER.debug("Exception on getRepositoriesByName" , e);
474
            emailUtils.reportException(e);
475
            throw e;
476
        }
477

    
478
    }
479

    
480
    @Override
481
    public List<RepositoryInterface> getRepositoryInterface(String id) throws JSONException {
482

    
483
        UriComponents uriComponents = UriComponentsBuilder
484
                .fromHttpUrl(baseAddress + "/ds/api/")
485
                .path("/{id}")
486
                .build().expand(id).encode();
487

    
488
        try{
489
            String rs = restTemplate.getForObject(uriComponents.toUri(), String.class);
490
            return Converter.jsonToRepositoryInterfaceList(new JSONObject(rs));
491
        }catch (Exception e ){
492
            LOGGER.debug("Exception on getRepositoryInterface" , e);
493
            emailUtils.reportException(e);
494
            throw e;
495
        }
496

    
497
    }
498

    
499
    @Override
500
    public Repository addRepository(String datatype,
501
                                    Repository repository) throws Exception {
502

    
503
        LOGGER.debug("storing " + datatype + " repository with id: " + repository.getId());
504

    
505
        repository.setCountryCode(countriesMap.get(repository.getCountryName()));
506
        repository.setActivationId(UUID.randomUUID().toString());
507
        repository.setCollectedFrom("infrastruct_::openaire");
508

    
509
        if (datatype.equals("journal")) {
510
            repository.setId("openaire____::issn" + repository.getIssn());
511
            repository.setNamespacePrefix("issn" + repository.getIssn());
512
            this.storeRepository(repository, SecurityContextHolder.getContext().getAuthentication());
513
        }else if (datatype.equals("aggregator")) {
514
            repository.setId("openaire____::" + com.unboundid.util.Base64.encode(repository.getOfficialName()));
515
            repository.setNamespacePrefix(DigestUtils.md5Hex(repository.getOfficialName()).substring(0,12));
516
            this.storeRepository(repository, SecurityContextHolder.getContext().getAuthentication());
517
        }else {
518
            this.latentUpdate(repository, SecurityContextHolder.getContext().getAuthentication());
519
        }
520

    
521
        // TODO: Antonis K. - Create new role ROLE_(datasource.datasourceId) and assign it to the user that created the folder (+ replace :: with $$)
522
        // Create new role ( careful ... replace :: with $$ )
523
        String newRoleName = repository.getId().replaceAll(":", "\\$");
524
        String newRoleDescr = repository.getId().replaceAll(":", "\\$");
525
        Role newRole = new Role(newRoleName, newRoleDescr);
526
        try {
527
            calls.createRole(newRole);
528
        } catch (Exception e) {
529
            LOGGER.debug("Exception on create role during add repository" , e);
530
            throw e;
531
        }
532

    
533
        // Assign new role to the user that created it
534
        Integer coPersonId = calls.getCoPersonIdByIdentifier();
535
        Integer couId = calls.getCouId("datasource", newRoleName);
536
        if (couId != null) {
537
            Integer role = calls.getRoleId(coPersonId, couId);
538
            try{
539
                calls.assignMemberRole(coPersonId, couId, role);
540
                // TODO: Antonis K. This should be uncommented to make a role DATASOURCE.OP... for every new repo
541
//                authoritiesUpdater.update(sendEmail(), old -> {
542
//                    HashSet<SimpleGrantedAuthority> authorities = new HashSet<>((Collection<? extends SimpleGrantedAuthority>) old);
543
//                    authorities.add(new SimpleGrantedAuthority(authorizationService.member("datasource", newRoleName)));
544
//                    return authorities;
545
//                });
546
            } catch (Exception e) {
547
                LOGGER.debug("Exception on assign role to user during add repository" , e);
548
                throw e;
549
            }
550

    
551
        }
552

    
553

    
554
        return repository;
555
    }
556

    
557
    /* update method acting as add -> send email with registration topic/body*/
558
    private Repository latentUpdate(Repository repository, Authentication authentication) throws Exception {
559
        UriComponents uriComponents = UriComponentsBuilder
560
                .fromHttpUrl(baseAddress + "/ds/update/")
561
                .build()
562
                .encode();
563

    
564
        try {
565
            String json_repository = Converter.repositoryObjectToJson(repository);
566
            LOGGER.debug("JSON to add(update) -> " + json_repository);
567

    
568
            HttpEntity<String> httpEntity = new HttpEntity<String>(json_repository, httpHeaders);
569
            ResponseEntity responseEntity = restTemplate.exchange(uriComponents.toUri(),HttpMethod.POST, httpEntity, ResponseEntity.class);
570

    
571
            if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
572
//                emailUtils.sendUserRegistrationEmail(repository, authentication);
573
//                emailUtils.sendAdminRegistrationEmail(repository, authentication);
574
            } else
575
                LOGGER.debug(responseEntity.getBody().toString());
576

    
577
            return repository;
578
        } catch (Exception e) {
579
            LOGGER.debug("Exception on updateRepository" , e);
580
            emailUtils.reportException(e);
581
            throw e;
582
        }
583

    
584

    
585
    }
586

    
587
    @Override
588
    public Repository updateRepository(Repository repository,Authentication authentication) throws Exception {
589
        UriComponents uriComponents = UriComponentsBuilder
590
                .fromHttpUrl(baseAddress + "/ds/update/")
591
                .build()
592
                .encode();
593

    
594
        try {
595
            String json_repository = Converter.repositoryObjectToJson(repository);
596

    
597
            LOGGER.debug("JSON to update -> " + json_repository);
598

    
599
            HttpEntity<String> httpEntity = new HttpEntity<String>(json_repository, httpHeaders);
600
            ResponseEntity responseEntity = restTemplate.exchange(uriComponents.toUri(),HttpMethod.POST, httpEntity
601
                    , ResponseEntity.class);
602

    
603
            if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
604
                emailUtils.sendUserUpdateRepositoryInfoEmail(repository, authentication);
605
                emailUtils.sendAdminUpdateRepositoryInfoEmail(repository, authentication);
606
            } else
607
                LOGGER.debug(responseEntity.getBody().toString());
608

    
609
            return repository;
610
        } catch (Exception e) {
611
            LOGGER.debug("Exception on updateRepository" , e);
612
            emailUtils.reportException(e);
613
            throw e;
614
        }
615
    }
616

    
617
    private void storeRepository(Repository repository, Authentication authentication) throws Exception {
618

    
619
        Date utilDate = new Date();
620
        Timestamp date = new Timestamp(utilDate.getTime());
621
        repository.setDateOfCollection(date);
622
        repository.setAggregator("OPENAIRE");
623
        repository.setCountryCode(countriesMap.get(repository.getCountryName()));
624

    
625
        UriComponents uriComponents = UriComponentsBuilder
626
                .fromHttpUrl(baseAddress + "/ds/add/")
627
                .build()
628
                .encode();
629
        String json_repository = Converter.repositoryObjectToJson(repository);
630
        HttpEntity<String> httpEntity = new HttpEntity <String> (json_repository,httpHeaders);
631
        ResponseEntity responseEntity = restTemplate.exchange(uriComponents.toUri(),HttpMethod.POST, httpEntity, ResponseEntity.class);
632

    
633
        if(responseEntity.getStatusCode().equals(HttpStatus.OK)) {
634
            emailUtils.sendUserRegistrationEmail(repository, authentication);
635
            emailUtils.sendAdminRegistrationEmail(repository, authentication);
636
        } else {
637
            LOGGER.debug(responseEntity.getBody().toString());
638
        }
639
    }
640

    
641
    @Override
642
    public void deleteRepositoryInterface(String id ,
643
                                          String registeredBy){
644
        UriComponents uriComponents = UriComponentsBuilder
645
                .fromHttpUrl(baseAddress + "/ds/api/")
646
                .path("/{id}")
647
                .build().expand(id).encode();
648
        LOGGER.debug(uriComponents.toUri());
649
        restTemplate.delete(uriComponents.toUri());
650
    }
651

    
652
    @Override
653
    public RepositoryInterface addRepositoryInterface(String datatype,
654
                                                      String repoId,
655
                                                      String registeredBy,
656
                                                      String comment, RepositoryInterface repositoryInterface) throws Exception {
657
        try {
658
            Repository e = this.getRepositoryById(repoId);
659
            repositoryInterface = createRepositoryInterface(e,repositoryInterface,datatype);
660
            String json_interface = Converter.repositoryInterfaceObjectToJson(e,repositoryInterface);
661

    
662
            UriComponents uriComponents = UriComponentsBuilder
663
                    .fromHttpUrl(baseAddress + "/ds/api/add/")
664
                    .build()
665
                    .encode();
666

    
667
            HttpEntity<String> httpEntity = new HttpEntity <> (json_interface,httpHeaders);
668

    
669
            restTemplate.postForObject(uriComponents.toUri(),httpEntity, String.class);
670

    
671
            emailUtils.sendAdminRegisterInterfaceEmail(e, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
672
            emailUtils.sendUserRegisterInterfaceEmail(e, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
673

    
674
            submitInterfaceValidation(e, registeredBy, repositoryInterface, false);
675

    
676
            return repositoryInterface;
677

    
678
        } catch (Exception e) {
679
            LOGGER.error("Exception on addRepositoryInterface" , e);
680
            emailUtils.reportException(e);
681
            throw e;
682
        }
683
    }
684

    
685
    @Override
686
    public RepositoryInterface updateRepositoryInterface(String repoId,
687
                                                         String registeredBy,
688
                                                         String comment, RepositoryInterface repositoryInterface) throws Exception {
689

    
690
        this.updateBaseUrl(repoId,repositoryInterface.getId(),repositoryInterface.getBaseUrl());
691
        this.updateCompliance(repoId,repositoryInterface.getId(),repositoryInterface.getCompliance());
692
        this.updateValidationSet(repoId,repositoryInterface.getId(),repositoryInterface.getAccessSet());
693

    
694
        Repository e = this.getRepositoryById(repoId);
695
        emailUtils.sendAdminUpdateInterfaceEmail(e, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
696
        emailUtils.sendUserUpdateInterfaceEmail(e, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
697
        submitInterfaceValidation(getRepositoryById(repoId),registeredBy,repositoryInterface,true);
698

    
699
        return repositoryInterface;
700
    }
701

    
702
    private void submitInterfaceValidation(Repository repo, String userEmail, RepositoryInterface iFace, boolean updateExisting) throws ValidatorServiceException {
703
        JobForValidation job = new JobForValidation();
704

    
705
        job.setActivationId(UUID.randomUUID().toString());
706
        job.setAdminEmails(Collections.singletonList(this.adminEmail));
707
        job.setBaseUrl(iFace.getBaseUrl());
708
        job.setDatasourceId(repo.getId());
709
        job.setDesiredCompatibilityLevel(iFace.getDesiredCompatibilityLevel());
710
        job.setInterfaceId(iFace.getId());
711
        job.setOfficialName(repo.getOfficialName());
712
        job.setRepoType(repo.getDatasourceType());
713
        job.setUserEmail(userEmail);
714
        job.setValidationSet((iFace.getAccessSet().isEmpty() ? "none" : iFace.getAccessSet()));
715
        job.setRecords(-1);
716
        job.setRegistration(!updateExisting);
717
        job.setUpdateExisting(updateExisting);
718

    
719
        this.validatorService.submitJobForValidation(job);
720
    }
721

    
722
    private RepositoryInterface createRepositoryInterface(Repository repo, RepositoryInterface iFace, String datatype) {
723

    
724
        iFace.setContentDescription("metadata");
725
        iFace.setCompliance("UNKNOWN");
726

    
727
        if (datatype.equals("re3data"))
728
            iFace.setAccessFormat("oai_datacite");
729
        else
730
            iFace.setAccessFormat("oai_dc");
731

    
732

    
733
        if (repo.getDatasourceClass() != null && !repo.getDatasourceClass().isEmpty())
734
            iFace.setTypology(repo.getDatasourceClass());
735
        else if (datatype.equalsIgnoreCase("journal"))
736
            iFace.setTypology("pubsrepository::journal");
737
        else if (datatype.equalsIgnoreCase("aggregator"))
738
            iFace.setTypology("aggregator::pubsrepository::unknown");
739
        else if (datatype.equalsIgnoreCase("opendoar"))
740
            iFace.setTypology("pubsrepository::unknown");
741
        else if (datatype.equalsIgnoreCase("re3data"))
742
            iFace.setTypology("datarepository::unknown");
743

    
744
        iFace.setRemovable(true);
745
        iFace.setAccessProtocol("oai");
746
        iFace.setMetadataIdentifierPath("//*[local-name()='header']/*[local-name()='identifier']");
747
        iFace.setId("api_________::" + repo.getId() + "::" + UUID.randomUUID().toString().substring(0, 8));
748
        if (iFace.getAccessSet() == null || iFace.getAccessSet().isEmpty()) {
749
            LOGGER.debug("set is empty: " + iFace.getAccessSet());
750
            iFace.removeAccessSet();
751
            iFace.setAccessSet("none");
752
        }
753
        return iFace;
754
    }
755

    
756
    @Override
757
    public List<String> getDnetCountries() {
758
        LOGGER.debug("Getting dnet-countries!");
759
        return Converter.readFile("countries.txt");
760
    }
761

    
762
    @Override
763
    public List<String> getTypologies() {
764
        return Converter.readFile("typologies.txt");
765
    }
766

    
767
    @Override
768
    public List<Timezone> getTimezones() {
769
        List<String> timezones =  Converter.readFile("timezones.txt");
770
        return Converter.toTimezones(timezones);
771
    }
772

    
773
    @Override
774
    public List<String> getUrlsOfUserRepos(String userEmail,
775
                                           String page,
776
                                           String size){
777
        UriComponents uriComponents = UriComponentsBuilder
778
                .fromHttpUrl(baseAddress + "/api/baseurl/")
779
                .path("/{page}/{size}")
780
                .build().expand(page,size).encode();
781

    
782
        try{
783
            RequestFilter requestFilter = new RequestFilter();
784
            requestFilter.setRegisteredby(userEmail);
785
            return Arrays.asList(restTemplate.postForObject(uriComponents.toUri(),requestFilter, String[].class));
786
        }catch (Exception e){
787
            LOGGER.debug("Exception on addRepositoryInterface" , e);
788
            emailUtils.reportException(e);
789
            throw e;
790
        }
791
    }
792

    
793
    @Override
794
    public List<String> getDatasourceVocabularies(String mode) {
795

    
796
        List<String> resultSet = new ArrayList<>();
797
        for (Map.Entry<String, String> entry : this.getVocabulary("dnet:datasource_typologies").getAsMap().entrySet()) {
798
            if (mode.equalsIgnoreCase("aggregator")) {
799
                if (entry.getKey().contains("aggregator"))
800
                    resultSet.add(entry.getValue());
801
            } else if (mode.equalsIgnoreCase("journal")) {
802
                if (entry.getKey().contains("journal"))
803
                    resultSet.add(entry.getValue());
804
            } else if (mode.equalsIgnoreCase("opendoar")) {
805
                if (entry.getKey().contains("pubsrepository"))
806
                    resultSet.add(entry.getValue());
807
            } else if (mode.equalsIgnoreCase("re3data")) {
808
                if (entry.getKey().contains("datarepository"))
809
                    resultSet.add(entry.getValue());
810
            }
811
        }
812

    
813

    
814
        return resultSet;
815
    }
816

    
817
    private Vocabulary getVocabulary(String vocName) {
818

    
819
        if (!vocabularyMap.containsKey(vocName)) {
820
            vocabularyMap.put(vocName, vocabularyLoader.getVocabulary(vocName, Locale.ENGLISH, Locale.ROOT));
821
        }
822
        return vocabularyMap.get(vocName);
823
    }
824

    
825

    
826
    @Override
827
    public Map<String, String> getCompatibilityClasses(String mode)  {
828

    
829
        LOGGER.debug("Getting compatibility classes for mode: " + mode);
830
        Map<String, String> retMap = new HashMap<String, String>();
831

    
832
        Map<String, String> compatibilityClasses = this.getVocabulary("dnet:compatibilityLevel").getAsMap();
833
        boolean foundData = false;
834
        for (Map.Entry<String, String> entry : compatibilityClasses.entrySet()) {
835
            if (mode.equalsIgnoreCase(Constants.REPOSITORY_MODE_ALL))
836
                return compatibilityClasses;
837
            else if (mode.equalsIgnoreCase(Constants.REPOSITORY_MODE_RE3DATA)) {
838
                if (entry.getKey().matches("^openaire[1-9].0_data$")) {
839
                    retMap.put(entry.getKey(), entry.getValue());
840
                    foundData = true;
841
                }
842
            } else {
843
                if (entry.getKey().matches("^openaire[1-9].0$") || entry.getKey().equals("driver"))
844
                    retMap.put(entry.getKey(), entry.getValue());
845
            }
846
        }
847

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

    
852
        return retMap;
853
    }
854

    
855
    @Override
856
    public Map<String, String> getDatasourceClasses(String mode)  {
857

    
858
        LOGGER.debug("Getting datasource classes for mode: " + mode);
859

    
860
        Map<String, String> retMap = new HashMap<String, String>();
861

    
862
        for (Map.Entry<String, String> entry : this.getVocabulary("dnet:datasource_typologies").getAsMap().entrySet()) {
863
            if (mode.equalsIgnoreCase("aggregator")) {
864
                if (entry.getKey().contains("aggregator"))
865
                    retMap.put(entry.getKey(), entry.getValue());
866
            } else if (mode.equalsIgnoreCase("journal")) {
867
                if (entry.getKey().contains("journal"))
868
                    retMap.put(entry.getKey(), entry.getValue());
869
            } else if (mode.equalsIgnoreCase("opendoar")) {
870
                if (entry.getKey().contains("pubsrepository"))
871
                    retMap.put(entry.getKey(), entry.getValue());
872
            } else if (mode.equalsIgnoreCase("re3data")) {
873
                if (entry.getKey().contains("datarepository"))
874
                    retMap.put(entry.getKey(), entry.getValue());
875
            }
876
        }
877
        return filterResults(retMap,mode);
878

    
879
    }
880

    
881
    private Map<String,String> filterResults(Map<String, String> map,String mode) {
882

    
883
        HashMap<String,String> filteredMap = new HashMap<>();
884
        for(String key:map.keySet())
885
            if(dataSourceClass.get(mode).contains(key))
886
                filteredMap.put(key,map.get(key));
887

    
888
        return filteredMap;
889
    }
890

    
891
    @Override
892
    public String getCountryName(String countryCode) {
893
        return inverseCountriesMap.get(countryCode);
894
    }
895

    
896
    @Override
897
    public MetricsInfo getMetricsInfoForRepository(String repoId) throws RepositoryServiceException {
898
        try {
899

    
900
            MetricsInfo metricsInfo = new MetricsInfo();
901
            metricsInfo.setDiagramsBaseURL(this.usageStatisticsDiagramsBaseURL);
902
            metricsInfo.setMetricsNumbers(getMetricsNumbers(getOpenAIREId(repoId)));
903
            return metricsInfo;
904

    
905
        } catch (Exception e) {
906
            LOGGER.error("Error while getting metrics info for repository: ", e);
907
            emailUtils.reportException(e);
908
            throw new RepositoryServiceException("General error", RepositoryServiceException.ErrorCode.GENERAL_ERROR);
909
        }
910
    }
911

    
912
    @Override
913
    public Map<String, String> getListLatestUpdate(String mode) throws JSONException {
914
        if(mode.equals("opendoar"))
915
            return Collections.singletonMap("lastCollectionDate", getRepositoryInterface("openaire____::"+mode).get(0).getLastCollectionDate());
916
        else
917
            /*
918
            * first api of re3data has null value on collection date
919
            * */
920
            return Collections.singletonMap("lastCollectionDate", getRepositoryInterface("openaire____::"+mode).get(1).getLastCollectionDate());
921
    }
922

    
923
    private void updateValidationSet(String repositoryId, String repositoryInterfaceId, String validationSet) throws Exception {
924
        UriComponents uriComponents = UriComponentsBuilder
925
                .fromHttpUrl(baseAddress + "/ds/api/oaiset")
926
                .queryParam("dsId",repositoryId)
927
                .queryParam("apiId",repositoryInterfaceId)
928
                .queryParam("oaiSet",validationSet)
929
                .build().encode();
930
       restTemplate.exchange(uriComponents.toUri(),HttpMethod.POST, null, ResponseEntity.class);
931

    
932
    }
933

    
934

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

    
945
    private void updateCompliance(String repositoryId, String repositoryInterfaceId,String compliance) {
946
        UriComponents uriComponents = UriComponentsBuilder
947
                .fromHttpUrl(baseAddress + "/ds/api/compliance")
948
                .queryParam("dsId",repositoryId)
949
                .queryParam("apiId",repositoryInterfaceId)
950
                .queryParam("compliance",compliance)
951
                .build().encode();
952
        restTemplate.postForObject(uriComponents.toUri(),null,String.class);
953
    }
954

    
955
    private MetricsNumbers getMetricsNumbers(String openAIREID) throws BrokerException {
956

    
957
        //build the uri params
958
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(this.usageStatisticsNumbersBaseURL + openAIREID + "/clicks");
959

    
960
        //create new template engine
961
        RestTemplate template = new RestTemplate();
962
        template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
963
        ResponseEntity<MetricsNumbers> resp;
964
        try {
965
            //communicate with endpoint
966
            resp = template.exchange(
967
                    builder.build().encode().toUri(),
968
                    HttpMethod.GET,
969
                    null,
970
                    new ParameterizedTypeReference<MetricsNumbers>() {
971
                    });
972
        } catch (RestClientException e) {
973
            LOGGER.debug("Exception on getMetricsNumbers" , e);
974
            emailUtils.reportException(e);
975
            throw e;
976
        }
977

    
978
        return resp.getBody();
979
    }
980

    
981
    private String getOpenAIREId(String repoId) {
982

    
983
        if (repoId != null && repoId.contains("::")) {
984
            return repoId.split("::")[0] + "::" + DigestUtils.md5Hex(repoId.split("::")[1]);
985
        }
986

    
987
        return null;
988
    }
989

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

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

    
1000
    private UriComponents searchSnipperDatasource(String page,String size){
1001

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

    
1010
    private UriComponents searchRegisteredDatasource(String requestSortBy, String order, String page,String size){
1011

    
1012
        return UriComponentsBuilder
1013
                .fromHttpUrl(baseAddress + "/ds/searchregistered/")
1014
                .path("/{page}/{size}/")
1015
                .queryParam("requestSortBy",requestSortBy)
1016
                .queryParam("order",order)
1017
                .build().expand(page, size).encode();
1018
    }
1019

    
1020
    private String getRepositoryType(String typology){
1021
        return invertedDataSourceClass.get(typology);
1022
    }
1023

    
1024

    
1025
}
(12-12/20)