package org.molgenis.dataexplorer.controller;
import com.google.common.collect.Lists;
import org.molgenis.data.DataService;
import org.molgenis.data.Entity;
import org.molgenis.data.Repository;
import org.molgenis.data.annotation.core.RepositoryAnnotator;
import org.molgenis.data.annotation.core.utils.AnnotatorDependencyOrderResolver;
import org.molgenis.data.annotation.web.AnnotationService;
import org.molgenis.data.annotation.web.CrudRepositoryAnnotator;
import org.molgenis.data.annotation.web.meta.AnnotationJobExecution;
import org.molgenis.data.jobs.JobExecutionUpdater;
import org.molgenis.data.jobs.ProgressImpl;
import org.molgenis.data.meta.model.EntityTypeFactory;
import org.molgenis.security.core.runas.RunAsSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.security.access.intercept.RunAsUserToken;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.Arrays;
import java.util.List;
import static java.util.stream.Collectors.toList;
import static org.molgenis.data.annotation.web.meta.AnnotationJobExecutionMetaData.ANNOTATION_JOB_EXECUTION;
/**
* Creates AnnotationJob based on its {@link AnnotationJobExecution}. Is a bean so that it can use {@link Autowired}
* services needed to rehydrate the primitive data types. Runs at execution time.
*/
@Component
public class AnnotationJobFactory
{
private static final Logger LOG = LoggerFactory.getLogger(AnnotationJobFactory.class);
@Autowired
CrudRepositoryAnnotator crudRepositoryAnnotator;
@Autowired
DataService dataService;
@Autowired
private AnnotationService annotationService;
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JobExecutionUpdater jobExecutionUpdater;
@Autowired
private MailSender mailSender;
@Autowired
private EntityTypeFactory entityTypeFactory;
@RunAsSystem
public AnnotationJob createJob(AnnotationJobExecution metaData)
{
dataService.add(ANNOTATION_JOB_EXECUTION, metaData);
String annotatorNames = metaData.getAnnotators();
String targetName = metaData.getTargetName();
String username = metaData.getUser();
// create an authentication to run as the user that is listed as the owner of the job
RunAsUserToken runAsAuthentication = new RunAsUserToken("Job Execution", username, null,
userDetailsService.loadUserByUsername(username).getAuthorities(), null);
Repository<Entity> repository = dataService.getRepository(targetName);
List<RepositoryAnnotator> availableAnnotators = annotationService.getAllAnnotators().stream()
.filter(RepositoryAnnotator::annotationDataExists).collect(toList());
List<RepositoryAnnotator> requestedAnnotators = Arrays.stream(annotatorNames.split(","))
.map(annotationService::getAnnotatorByName).collect(toList());
AnnotatorDependencyOrderResolver resolver = new AnnotatorDependencyOrderResolver();
List<RepositoryAnnotator> annotators = Lists.newArrayList(
resolver.getAnnotatorSelectionDependencyList(availableAnnotators, requestedAnnotators, repository,
entityTypeFactory));
return new AnnotationJob(crudRepositoryAnnotator, username, annotators, repository,
new ProgressImpl(metaData, jobExecutionUpdater, mailSender), runAsAuthentication,
new TransactionTemplate(transactionManager));
}
}