001package com.credibledoc.substitution.reporting.reportdocument;
002
003import com.credibledoc.combiner.node.file.NodeFile;
004import com.credibledoc.combiner.node.file.NodeFileTreeSet;
005import com.credibledoc.substitution.core.exception.SubstitutionRuntimeException;
006import com.credibledoc.substitution.reporting.context.ReportingContext;
007import com.credibledoc.substitution.reporting.report.Report;
008
009import java.util.Collection;
010import java.util.ConcurrentModificationException;
011import java.util.List;
012import java.util.Set;
013
014/**
015 * The stateless service for working with {@link ReportDocument}s.
016 *
017 * @author Kyrylo Semenko
018 */
019public class ReportDocumentService {
020
021    /**
022     * Singleton.
023     */
024    private static final ReportDocumentService instance = new ReportDocumentService();
025
026    /**
027     * @return The {@link ReportDocumentService} singleton.
028     */
029    public static ReportDocumentService getInstance() {
030        return instance;
031    }
032
033    /**
034     * Validate and append the {@link ReportDocument} to the
035     * {@link ReportDocumentRepository#getReportDocuments()} list.
036     *
037     * @param reportDocument will be appended if it contains the {@link ReportDocument#getReport()} field,
038     *                       else an exception will be thrown.
039     * @param reportingContext the current state
040     */
041    public void addReportDocument(ReportDocument reportDocument, ReportingContext reportingContext) {
042        if (reportDocument.getReport() == null) {
043            throw new SubstitutionRuntimeException("Report cannot be empty in ReportDocument. " +
044                "ReportDocument: " + reportDocument);
045        }
046        reportingContext.getReportDocumentRepository().getReportDocuments().add(reportDocument);
047    }
048
049    /**
050     * Validate and append the {@link ReportDocument} to the
051     * {@link ReportDocumentRepository#getReportDocuments()} list.
052     *
053     * @param reportDocuments will be appended if all items contain the {@link ReportDocument#getReport()} field,
054     *                       else an exception will be thrown.
055     * @param reportingContext the current state
056     */
057    public void addAll(Collection<ReportDocument> reportDocuments, ReportingContext reportingContext) {
058        for (ReportDocument reportDocument : reportDocuments) {
059            addReportDocument(reportDocument, reportingContext);
060        }
061    }
062
063    /**
064     * Validate and append the {@link ReportDocument} to the
065     * {@link ReportDocumentRepository#getReportDocumentsForAddition()} list.
066     *
067     * @param reportDocument will be appended if it contains the {@link ReportDocument#getReport()} field,
068     *                       else an exception will be thrown.
069     * @param reportingContext the current state
070     */
071    public void addReportDocumentForAddition(ReportDocument reportDocument, ReportingContext reportingContext) {
072        if (reportDocument.getReport() == null) {
073            throw new SubstitutionRuntimeException("Report is mandatory for ReportDocument: " + reportDocument);
074        }
075        reportingContext.getReportDocumentRepository().getReportDocumentsForAddition().add(reportDocument);
076    }
077
078    /**
079     * For avoiding {@link ConcurrentModificationException} a newly created {@link ReportDocument} is
080     * appended to the {@link ReportDocumentRepository#getReportDocumentsForAddition()} collection.
081     * The current method will move all {@link ReportDocument}s from {@link ReportDocumentRepository#getReportDocumentsForAddition()}
082     * to {@link ReportDocumentRepository#getReportDocuments()}.
083     * @param reportingContext the current state
084     */
085    public void mergeReportDocumentsForAddition(ReportingContext reportingContext) {
086        List<ReportDocument> reportDocuments = reportingContext.getReportDocumentRepository().getReportDocuments();
087        List<ReportDocument> reportDocumentsForAddition =
088            reportingContext.getReportDocumentRepository().getReportDocumentsForAddition();
089        reportDocuments.addAll(reportDocumentsForAddition);
090        reportDocumentsForAddition.clear();
091    }
092
093    /**
094     * Find all {@link ReportDocument}s with report from parameter.
095     * @param report the {@link ReportDocument#getReport()} value
096     * @param reportingContext the current state
097     * @return 'null' if not found
098     */
099    public List<ReportDocument> getReportDocuments(Report report, ReportingContext reportingContext) {
100        ReportDocumentList<ReportDocument> reportDocuments =
101            reportingContext.getReportDocumentRepository().getReportDocuments();
102        return reportDocuments.get(report);
103    }
104
105    /**
106     * Collect {@link NodeFile}s which belong to the {@link ReportDocument}
107     * @param reportDocuments that contains {@link NodeFile}s
108     * @return List of unordered unique {@link NodeFile}s
109     */
110    public Set<NodeFile> getNodeFiles(List<ReportDocument> reportDocuments) {
111        Set<NodeFile> nodeFiles = new NodeFileTreeSet<>();
112        for (ReportDocument reportDocument : reportDocuments) {
113            Set<NodeFile> nodeFilesSet = reportDocument.getNodeFiles();
114            nodeFiles.addAll(nodeFilesSet);
115        }
116        return nodeFiles;
117    }
118}