package de.uni_goettingen.sub.commons.ocr.abbyy.server; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import de.uni_goettingen.sub.commons.ocr.api.OcrFormat; import de.unigoettingen.sub.commons.ocr.util.BeanProvider; import de.unigoettingen.sub.commons.ocr.util.FileAccess; import de.unigoettingen.sub.commons.ocr.util.merge.Merger; import de.unigoettingen.sub.commons.ocr.util.merge.MergerProvider; public class ProcessMergingObserver { private final static Logger logger = LoggerFactory.getLogger(ProcessMergingObserver.class); private AbbyyProcess parentProcess; private List<AbbyyProcess> subProcesses = new ArrayList<AbbyyProcess>(); private MergerProvider mergerProvider = new MergerProvider(); private BeanProvider beanProvider = new BeanProvider(); private FileAccess fileAccess; // for unit tests void setBeanProvider(BeanProvider newProvider) { beanProvider = newProvider; } void setMergerProvider(MergerProvider newProvider) { mergerProvider = newProvider; } public void setParentProcess(AbbyyProcess process) { parentProcess = process; } public void addSubProcess(AbbyyProcess subProcess) { subProcesses.add(subProcess); } public synchronized void update(AbbyyProcess finishedSubProcess) { finishedSubProcess.setFinished(); for (AbbyyProcess sub : subProcesses) { boolean currentFinished = sub.hasFinished(); if (!currentFinished) { return; } } // only get here when all subprocesses are finished for (AbbyyProcess sub : subProcesses) { if(sub.hasFailed()) { logger.error("Could not merge process: " + parentProcess.getName()); throw new IllegalStateException("Subprocess failed: " + sub.getName()); } } fileAccess = beanProvider.getFileAccess(); mergeAllFormats(); } private void mergeAllFormats() { try { for (OcrFormat format : parentProcess.getAllOutputFormats()) { Merger merger = mergerProvider.createMerger(format); OutputStream mergedStream = null; List<InputStream> streamsToMerge = new ArrayList<InputStream>(); try { List<File> filesToMerge = new ArrayList<File>(); for(AbbyyProcess subProcess : subProcesses) { File file = new File(subProcess.getOutputUriForFormat(format)); filesToMerge.add(file); InputStream is = fileAccess.inputStreamForFile(file); streamsToMerge.add(is); } File mergedFile = new File(parentProcess.getOutputUriForFormat(format)); mergedStream = fileAccess.outputStreamForFile(mergedFile); logger.debug("Trying to merge into " + mergedFile + " (" + parentProcess.getName() + ")"); merger.mergeBuffered(streamsToMerge, mergedStream); logger.debug(mergedFile + " merged successfully (" + parentProcess.getName() + ")"); removeSubProcessResults(filesToMerge); } finally { closeStreams(streamsToMerge, mergedStream); } } } catch (IOException e) { logger.error("Failed to merge all files correctly. (" + parentProcess.getName() + ")", e); } } private void removeSubProcessResults(List<File> resultFiles) throws IOException{ for(File file : resultFiles) { fileAccess.deleteFile(file); } } private void closeStreams(List<InputStream> streamsToMerge, OutputStream mergedStream) throws IOException { for (InputStream is : streamsToMerge) { if (is != null) is.close(); } if (mergedStream != null) mergedStream.close(); } }