package eu.dnetlib.repo.manager.service; import eu.dnetlib.api.functionality.ValidatorServiceException; import eu.dnetlib.domain.data.Repository; import eu.dnetlib.domain.data.RepositoryInterface; import eu.dnetlib.domain.functionality.validator.*; import eu.dnetlib.repo.manager.exception.ResourceNotFoundException; import eu.dnetlib.repo.manager.shared.Constants; import eu.dnetlib.repo.manager.shared.InterfaceInformation; import eu.dnetlib.repo.manager.shared.ValidationServiceException; import eu.dnetlib.repo.manager.utils.OaiTools; import gr.uoa.di.driver.util.ServiceLocator; import org.apache.log4j.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.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 = Logger .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; 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); } } @Override @PreAuthorize("hasRole('ROLE_USER') and #jobForValidation.userEmail == authentication.userInfo.email") public JobForValidation submitJobForValidation(JobForValidation jobForValidation) throws ValidatorServiceException { LOGGER.debug("Submit job for validation with id : " + jobForValidation.getDatasourceId()); try { emailUtils.sendSubmitJobForValidationEmail(SecurityContextHolder.getContext().getAuthentication(),jobForValidation); ///////////////////////////////////////////////////////////////////////////////////////// // FIXME: this is a hack for CRIS Jan Dvorak Validator, should be implemented properly // ///////////////////////////////////////////////////////////////////////////////////////// if (jobForValidation.getSelectedContentRules().size() == 1 && jobForValidation.getSelectedContentRules().contains(-1000)) { crisValidatorExecutor.submit(jobForValidation.getBaseUrl(), jobForValidation.getUserEmail()); } else { this.getValidationService().submitValidationJob(jobForValidation); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// // this.getValidationService().submitValidationJob(jobForValidation); } catch (ValidatorServiceException e) { LOGGER.debug("Exception on submitJobForValidation" , e); emailUtils.reportException(e); throw e; } catch (Exception e) { LOGGER.error(e); } return jobForValidation; } @Override @PreAuthorize("hasRole('ROLE_USER') and #email == authentication.userInfo.email") 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.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); try { return OaiTools.getSetsOfRepo(url); } catch (Exception e) { LOGGER.debug("Exception on getSetsOfRepository" , e); emailUtils.reportException(e); } return null; } @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); emailUtils.reportException(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); emailUtils.reportException(e); return null; } } @Override @PreAuthorize("hasRole('ROLE_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) { StoredJob sj = new StoredJob(); if (job.getDateFinished() != null) { sj.setEnded(job.getDateFinished().toString()); sj.setDuration(Long.toString(job.getDateFinished().getTime() - job.getDateStarted().getTime()) + " seconds"); } else { sj.setEnded("-"); sj.setDuration("-"); } sj.setStarted(job.getDateStarted().toString()); sj.setUserEmail(job.getUser()); sj.setCris(true); sj.setBaseUrl(job.getUrl()); sj.setJobType("CRIS Validation"); // TODO: status sj.setValidationStatus(job.getStatus()); sj.setUsageJobStatus(job.getStatus()); sj.setContentJobStatus(job.getStatus()); // TODO: scores // sj.setFilteredScores(); sj.setContentJobScore(job.getScore()); sj.setUsageJobScore(job.getScore()); jobs.add(sj); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// 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); emailUtils.reportException(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); } }