/*
* Copyright 2016 EMBL-EBI.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.ac.ebi.ep.xml.config;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManagerFactory;
import org.springframework.batch.core.ChunkListener;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JpaPagingItemReader;
import org.springframework.batch.item.xml.StaxWriterCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import uk.ac.ebi.ep.data.domain.UniprotEntry;
import uk.ac.ebi.ep.data.service.EnzymePortalXmlService;
import uk.ac.ebi.ep.xml.generator.protein.ProteinXmlFooterCallback;
import uk.ac.ebi.ep.xml.generator.protein.ProteinXmlHeaderCallback;
import uk.ac.ebi.ep.xml.generator.protein.UniProtEntryToEntryConverter;
import uk.ac.ebi.ep.xml.model.Entry;
import uk.ac.ebi.ep.xml.util.LogChunkListener;
import uk.ac.ebi.ep.xml.util.LogJobListener;
import uk.ac.ebi.ep.xml.util.PrettyPrintStaxEventItemWriter;
/**
*
* @author Joseph <joseph@ebi.ac.uk>
*/
@Configuration
@EnableBatchProcessing
@Import({MockXmlConfig.class})
public class MockProteinBatchConfig extends DefaultBatchConfigurer {
public static final String PROTEIN_CENTRIC_JOB = "PROTEIN_CENTRIC_JOB";
public static final String PROTEIN_CENTRIC_DB_TO_XML_STEP = "readFromDbWriteToXMLStep";
@Autowired
private JobBuilderFactory jobBuilders;
@Autowired
private StepBuilderFactory stepBuilders;
@Autowired
private EntityManagerFactory entityManagerFactory;
@Autowired
private EnzymePortalXmlService xmlService;
@Autowired
private XmlConfigParams mockXmlConfigParams;
@Bean
public Resource proteinCentricXmlDir() {
return new FileSystemResource(mockXmlConfigParams.getProteinCentricXmlDir());
}
@Bean
public JobLauncher jobLauncher() {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(this.getJobRepository());
return jobLauncher;
}
@Bean
public Job proteinCentricJob() {
return jobBuilders.get(PROTEIN_CENTRIC_JOB)
.start(readFromDbWriteToXMLStep())
.listener(logJobListener(PROTEIN_CENTRIC_JOB))
.build();
}
@Bean
public Step readFromDbWriteToXMLStep() {
return stepBuilders.get(PROTEIN_CENTRIC_DB_TO_XML_STEP)
.<UniprotEntry, Entry>chunk(mockXmlConfigParams.getChunkSize())
.<UniprotEntry>reader(uniProtEntryReader())
.processor(uniProtEntryToEntryConverter())
.writer(entryToXmlWriter())
.listener(logChunkListener())
.build();
}
@Bean
public ItemReader<UniprotEntry> uniProtEntryReader() {
JpaPagingItemReader<UniprotEntry> databaseReader = new JpaPagingItemReader<>();
databaseReader.setEntityManagerFactory(entityManagerFactory);
databaseReader.setQueryString("select u from UniprotEntry u");
databaseReader.setPageSize(mockXmlConfigParams.getChunkSize());
return databaseReader;
}
@Bean
public ItemProcessor<UniprotEntry, Entry> uniProtEntryToEntryConverter() {
return new UniProtEntryToEntryConverter(mockXmlConfigParams);
}
@Bean
public ItemWriter<Entry> entryToXmlWriter() {
PrettyPrintStaxEventItemWriter<Entry> xmlWriter = new PrettyPrintStaxEventItemWriter<>();
xmlWriter.setResource(proteinCentricXmlDir());
xmlWriter.setRootTagName("database");
xmlWriter.setMarshaller(entryMarshaller());
xmlWriter.setHeaderCallback(xmlHeaderCallback());
xmlWriter.setFooterCallback(new ProteinXmlFooterCallback());
return xmlWriter;
}
private StaxWriterCallback xmlHeaderCallback() {
return new ProteinXmlHeaderCallback(mockXmlConfigParams.getReleaseNumber(), xmlService);
}
private JobExecutionListener logJobListener(String jobName) {
return new LogJobListener(jobName);
}
private ChunkListener logChunkListener() {
return new LogChunkListener(mockXmlConfigParams.getChunkSize());
}
/**
* Creates a job repository that uses an in memory map to register the job's
* progress. This should be changed to use a real data source in the
* following cases: - If you want to be able to resume a failed job - If you
* want more than one of the same job (with the same parameters) to be
* launched simultaneously - If you want to multi thread the job - If you
* have a locally partitioned step.
*
* @return a JobRepository
* @throws Exception if an error is encountered whilst creating the job repo
*/
@Override
protected JobRepository createJobRepository() throws Exception {
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean();
factory.afterPropertiesSet();
return factory.getObject();
}
private Marshaller entryMarshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(Entry.class);
Map<String, Object> jaxbProps = new HashMap<>();
jaxbProps.put(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setMarshallerProperties(jaxbProps);
return marshaller;
}
}