package eu.dnetlib.repo.manager.service; import eu.dnetlib.api.functionality.ValidatorServiceException; import eu.dnetlib.domain.functionality.validator.JobForValidation; import eu.dnetlib.domain.functionality.validator.Rule; import eu.dnetlib.domain.functionality.validator.RuleSet; import eu.dnetlib.domain.functionality.validator.StoredJob; import eu.dnetlib.repo.manager.domain.Constants; import eu.dnetlib.repo.manager.domain.InterfaceInformation; import eu.dnetlib.repo.manager.domain.RepositoryInterface; import eu.dnetlib.repo.manager.exception.ValidationServiceException; import eu.dnetlib.repo.manager.utils.CrisValidatorUtils; import eu.dnetlib.repo.manager.utils.OaiTools; import gr.uoa.di.driver.util.ServiceLocator; import org.slf4j.Logger; import org.eurocris.openaire.cris.validator.model.Job; import org.eurocris.openaire.cris.validator.service.JobExecutor; import org.eurocris.openaire.cris.validator.service.MapJobDao; import org.json.JSONException; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @Service("validatorService") public class ValidatorServiceImpl implements ValidatorService { @Autowired private MonitorServiceImpl monitorApi; @Autowired private RepositoryService repositoryService; @Resource(name = "validatorServiceLocator") private ServiceLocator validatorServiceLocator; private eu.dnetlib.api.functionality.ValidatorService getValidationService() { return this.validatorServiceLocator.getService(); } public ServiceLocator getValidatorServiceLocator() { return validatorServiceLocator; } public void setValidatorServiceLocator(ServiceLocator validatorServiceLocator) { this.validatorServiceLocator = validatorServiceLocator; } private Map> rulesetMap = new ConcurrentHashMap>(); private static final Logger logger = LoggerFactory.getLogger(ValidatorServiceImpl.class); @Autowired private EmailUtils emailUtils; @Autowired private JobExecutor crisValidatorExecutor; @Autowired private MapJobDao crisJobs; @PostConstruct private void loadRules(){ logger.debug("PostConstruct method! Load rules!"); try { for (RuleSet ruleSet : getValidationService().getRuleSets()) { if (ruleSet.getVisibility() != null && ruleSet.getVisibility().contains("development")) { String key = ""; if (ruleSet.getGuidelinesAcronym().matches("^openaire[1-9].0_data$")) key = Constants.VALIDATION_MODE_DATA; else if (ruleSet.getGuidelinesAcronym().matches("^openaire[1-9].0$") || ruleSet.getGuidelinesAcronym().equals("driver")) key = Constants.VALIDATION_MODE_LITERATURE; else if (ruleSet.getGuidelinesAcronym().matches("^openaire[1-9].0_cris$")) key = Constants.VALIDATION_MODE_CRIS; else if (ruleSet.getGuidelinesAcronym().matches(".*fair$")) key = Constants.VALIDATION_MODE_FAIR; if (rulesetMap.containsKey(key)) rulesetMap.get(key).add(ruleSet); else { List ruleSets = new ArrayList(); ruleSets.add(ruleSet); rulesetMap.put(key, ruleSets); } } } ///////////////////////////////////////////////////////////////////////////////////////// // FIXME: this is a hack for CRIS Jan Dvorak Validator, should be implemented properly // ///////////////////////////////////////////////////////////////////////////////////////// int ruleId = -1000; Rule rule = new Rule(); rule.setType("cris"); rule.setName("CRIS Rules"); rule.setId(ruleId); rule.setMandatory(true); RuleSet crisRuleSet = new RuleSet(); crisRuleSet.setContentRulesIds(Collections.singleton(ruleId)); crisRuleSet.setContentRules(Collections.singletonList(rule)); crisRuleSet.setUsageRulesIds(Collections.singleton(ruleId)); crisRuleSet.setUsageRules(Collections.singletonList(rule)); crisRuleSet.setId(-1); crisRuleSet.setDescription("Validates using the CRIS Validator implementation"); crisRuleSet.setName("CRIS Validation"); String crisKey = Constants.VALIDATION_MODE_CRIS; if (rulesetMap.containsKey(crisKey)) rulesetMap.get(crisKey).add(crisRuleSet); else { List ruleSets = new ArrayList(); ruleSets.add(crisRuleSet); rulesetMap.put(crisKey, ruleSets); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// } catch (ValidatorServiceException e) { logger.error(e.getMessage(), e); } } @Override @PreAuthorize("hasAuthority('REGISTERED_USER')") public JobForValidation submitJobForValidation(JobForValidation jobForValidation) throws ValidatorServiceException { logger.debug("Submit job for validation with id : " + jobForValidation.getDatasourceId()); try { try { emailUtils.sendSubmitJobForValidationEmail(SecurityContextHolder.getContext().getAuthentication(), jobForValidation); } catch (Exception e) { logger.error("Error sending email ", e); } ///////////////////////////////////////////////////////////////////////////////////////// // FIXME: this is a hack for CRIS Jan Dvorak Validator, should be implemented properly // ///////////////////////////////////////////////////////////////////////////////////////// if (jobForValidation.getSelectedContentRules()!=null && jobForValidation.getSelectedContentRules().size() == 1 && jobForValidation.getSelectedContentRules().contains(-1000) || jobForValidation.getDesiredCompatibilityLevel().matches("openaire-cris_1.1")) { crisValidatorExecutor.submit(jobForValidation.getBaseUrl(), jobForValidation.getUserEmail()); } else { this.getValidationService().submitValidationJob(jobForValidation); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// // this.getValidationService().submitValidationJob(jobForValidation); } catch (Exception e) { // FIXME: replaced exception with log // throw new ValidatorServiceException(e); logger.error(e.getMessage(), e); } return jobForValidation; } @Override public ResponseEntity reSubmitJobForValidation(String email, String jobId) throws JSONException, ValidatorServiceException { logger.debug("Resubmit validation job with id : " + jobId); StoredJob job = monitorApi.getJobSummary(jobId, "all"); Set contentRules = new HashSet(); Set usageRules = new HashSet(); RuleSet ruleSet = null; for (List ruleSets : this.rulesetMap.values()) { for (RuleSet rSet : ruleSets) { if (rSet.getName().equalsIgnoreCase("CRIS Validation")) { crisValidatorExecutor.submit(job.getBaseUrl(), job.getUserEmail()); return new ResponseEntity<>("OK",HttpStatus.OK); } else if(rSet.getGuidelinesAcronym().equals(job.getDesiredCompatibilityLevel())){ ruleSet = rSet; break; } } } if (ruleSet != null){ for (int ruleId : job.getRules()) { if (ruleSet.getContentRulesIds().contains(ruleId)) contentRules.add(ruleId); else if (ruleSet.getUsageRulesIds().contains(ruleId)) usageRules.add(ruleId); } } if (!contentRules.isEmpty()) job.setSelectedContentRules(contentRules); if (!usageRules.isEmpty()) job.setSelectedUsageRules(usageRules); this.submitJobForValidation(job); return new ResponseEntity<>("OK",HttpStatus.OK); } @Override public List getRuleSets(String mode) { logger.info("Getting rulesets for mode: " + mode); return rulesetMap.get(mode); } @Override public List getSetsOfRepository(String url) { logger.debug("Getting sets of repository with url : " + url); List sets = null; try { sets = OaiTools.getSetsOfRepo(url); } catch (Exception e) { logger.error("Exception on getSetsOfRepository" , e); } return sets; } @Override public boolean identifyRepo(String url) { logger.debug("Identify repository with url : " + url); try { return OaiTools.identifyRepository(url); } catch (Exception e) { logger.error("Error while identifying repository with url: " + url, e); return false; } } @Override public RuleSet getRuleSet(String acronym) { logger.debug("Getting ruleset with acronym : " + acronym); RuleSet ruleSet = null; try { for (List ruleSets : this.rulesetMap.values()) { for (RuleSet rSet : ruleSets) if (rSet.getGuidelinesAcronym().equals(acronym)) { ruleSet = rSet; break; } } return ruleSet; } catch (Exception e) { logger.error("Error getting ruleset", e); return null; } } @Override @PreAuthorize("hasAuthority('REGISTERED_USER')") public List getStoredJobsNew(String user, String jobType, String offset, String limit, String dateFrom, String dateTo, String validationStatus ) throws ValidatorServiceException { // return getValidationService().getStoredJobsNew(user, jobType, Integer.parseInt(offset), Integer.parseInt(limit), dateFrom, dateTo, validationStatus); List jobs = getValidationService().getStoredJobsNew(user, jobType, Integer.parseInt(offset), Integer.parseInt(limit), dateFrom, dateTo, validationStatus); ///////////////////////////////////////////////////////////////////////////////////////// // FIXME: this is a hack for CRIS Jan Dvorak Validator, should be implemented properly // ///////////////////////////////////////////////////////////////////////////////////////// if (jobs == null) { jobs = new ArrayList<>(); } List cj = crisJobs.getJobs(user); for (Job job : cj) { jobs.add(CrisValidatorUtils.convertJobToStoredJob(job)); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// return jobs; } @Override public int getStoredJobsTotalNumberNew(String user, String jobType, String validationStatus) throws ValidatorServiceException { return getValidationService().getStoredJobsTotalNumberNew(user, jobType, validationStatus); } @Override public InterfaceInformation getInterfaceInformation(String baseUrl) throws ValidationServiceException { try { logger.debug("Getting interface information with url: " + baseUrl); InterfaceInformation interfaceInformation = new InterfaceInformation(); interfaceInformation.setIdentified(this.identifyRepo(baseUrl)); if (interfaceInformation.isIdentified()) interfaceInformation.setSets(this.getSetsOfRepository(baseUrl)); return interfaceInformation; } catch (Exception e) { logger.error("Error getting interface information with url: " + baseUrl, e); throw new ValidationServiceException("login.generalError", ValidationServiceException.ErrorCode.GENERAL_ERROR); } } @Override public List getJobsSummary(String repoId, int limit) throws JSONException, ValidatorServiceException { return getValidationService().getJobSummary( repositoryService.getRepositoryInterface(repoId) .stream() .map(RepositoryInterface::getBaseurl) .collect(Collectors.toList()), limit); } }