All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cdc.impex.core.ExporterImpl Maven / Gradle / Ivy

There is a newer version: 0.54.0
Show newest version
package cdc.impex.core;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import cdc.impex.ImpExFactory;
import cdc.impex.ImpExFactoryFeatures;
import cdc.impex.ImpExFormat;
import cdc.impex.exports.ExportIssueType;
import cdc.impex.exports.ExportIssues;
import cdc.impex.exports.Exporter;
import cdc.impex.exports.StreamExporter;
import cdc.impex.exports.WorkbookExporter;
import cdc.impex.templates.SheetTemplateInstance;
import cdc.issues.Issue;
import cdc.issues.IssueSeverity;
import cdc.issues.IssuesHandler;
import cdc.issues.locations.WorkbookLocation;
import cdc.util.events.ProgressController;
import cdc.util.events.ProgressSupplier;
import cdc.util.lang.Checks;
import cdc.util.lang.Procedure;
import cdc.util.time.Chronometer;

public class ExporterImpl implements Exporter {
    private final ImpExFactory factory;
    private IssuesHandler issuesHandler;
    private String systemId;
    private String sheetName;

    public ExporterImpl(ImpExFactoryFeatures features) {
        this.factory = new ImpExFactory(features);
    }

    public ExporterImpl(ImpExFactory factory) {
        this(factory.getFeatures());
    }

    private void issue(ExportIssueType type,
                       IssueSeverity severity,
                       String description) {
        issuesHandler.issue(ExportIssues.builder()
                                        .name(type)
                                        .severity(severity)
                                        .description(description)
                                        .addLocation(WorkbookLocation.builder()
                                                                     .systemId(systemId)
                                                                     .sheetName(sheetName)
                                                                     .build())
                                        .build());
    }

    private void issue(ExportIssueType type,
                       String description) {
        issue(type, type.getSeverity(), description);
    }

    private void wrap(Procedure procedure) {
        try {
            procedure.invoke();
        } catch (final RuntimeException e) {
            // Generate a valid (non null) description
            final String description = e.getMessage() == null
                    ? e.getClass().getSimpleName()
                    : e.getMessage();
            issue(ExportIssueType.APP_FAILURE,
                  IssueSeverity.BLOCKER,
                  description);
            throw e;
        }
    }

    private void exportDataInt(File file,
                               OutputStream out,
                               String systemId,
                               ImpExFormat format,
                               List templateInstances,
                               WorkbookExporter workbookExporter,
                               IssuesHandler issuesHandler,
                               ProgressController controller) throws IOException {
        Checks.isNotNull(format, "format");
        Checks.isNotNull(templateInstances, "templates");
        Checks.isNotNull(workbookExporter, "workbookExporter");
        Checks.isNotNull(issuesHandler, "issuesHandler");
        Checks.isNotNull(controller, "controller");

        final Chronometer chrono = new Chronometer();
        chrono.start();
        final ProgressSupplier progress = new ProgressSupplier(controller);

        final Set tmp = new HashSet<>(templateInstances);
        if (tmp.size() != templateInstances.size()) {
            throw new IllegalArgumentException("Duplicate templates");
        }

        this.issuesHandler = issuesHandler;
        this.systemId = systemId;
        sheetName = null;

        issue(ExportIssueType.GENERATE_WORKBOOK,
              "Generate '" + systemId + "' workbook.");
        try (final StreamExporter streamExporter = factory.createStreamExporter(format, issuesHandler)) {
            if (file == null) {
                streamExporter.beginExport(out, format);
            } else {
                streamExporter.beginExport(file);
            }
            wrap(() -> workbookExporter.beginExport(issuesHandler));

            if (factory.getFeatures().isEnabled(ImpExFactoryFeatures.Hint.ADD_README)) {
                streamExporter.addReadme(templateInstances);
            }

            final int maxRowsPerSheet = format.getMaxRows();

            for (final SheetTemplateInstance templateInstance : templateInstances) {
                wrap(() -> workbookExporter.beginSheetExport(templateInstance, issuesHandler));

                final int totalNumberOfRows = workbookExporter.getNumberOfRemainingRows();
                if (totalNumberOfRows != 0) {
                    int sheetNumber = 0;

                    // Write extracted sheet into N generated sheets that each
                    // have at most maxRowsPerSheet
                    while (workbookExporter.hasMore()) {
                        final Chronometer sheetChrono = new Chronometer();
                        sheetChrono.start();

                        final int remaining = workbookExporter.getNumberOfRemainingRows();
                        final int partialTotal;
                        if (remaining < 0) {
                            partialTotal = -1;
                        } else if (maxRowsPerSheet < 0) {
                            // Add 1 to remaining to take into account header
                            // One sheet will do the job
                            partialTotal = remaining + 1;
                        } else {
                            // Add 1 to remaining to take into account header
                            partialTotal = Math.min(maxRowsPerSheet, remaining + 1);
                        }

                        sheetNumber++;
                        sheetName = templateInstance.getTemplate().getName() + "#" + sheetNumber;
                        progress.reset(partialTotal, "Generate sheet " + sheetName);
                        issue(ExportIssueType.GENERATE_SHEET,
                              "Generate '" + sheetName + "' sheet with '" + templateInstance.getTemplate().getQName()
                                      + "' template.");
                        streamExporter.beginSheet(templateInstance, sheetName, partialTotal);
                        final ExportRowImpl row = new ExportRowImpl(templateInstance, sheetName, systemId);
                        row.setNumber(1); // Count header
                        progress.incrementValue();

                        // Number of rows in current generated sheet.
                        // Initialize to 1 to count header row
                        int numberOfRowsInSheet = 1;
                        while ((maxRowsPerSheet < 0 || numberOfRowsInSheet < maxRowsPerSheet) && workbookExporter.hasMore()) {
                            numberOfRowsInSheet++;
                            row.clear();
                            row.incrementNumber();
                            wrap(() -> workbookExporter.exportRow(row, issuesHandler));
                            streamExporter.addRow(row);
                            progress.incrementValue();
                        }
                        streamExporter.endSheet();
                        sheetChrono.suspend();
                        issue(ExportIssueType.GENERATED_SHEET,
                              "Generated '" + sheetName + "' sheet with '" + templateInstance.getTemplate().getQName()
                                      + "' template in " + sheetChrono + ".");
                    }
                    wrap(() -> workbookExporter.endSheetExport(templateInstance, issuesHandler));
                } else {
                    wrap(() -> workbookExporter.endSheetExport(templateInstance, issuesHandler));
                    issue(ExportIssueType.IGNORED_SHEET,
                          "Ignored '" + sheetName + "' sheet as there is no data.");
                }
            }

            wrap(() -> workbookExporter.endExport(issuesHandler));
            streamExporter.endExport();
        }
        chrono.suspend();
        issue(ExportIssueType.GENERATED_WORKBOOK,
              "Generated '" + systemId + "' workbook in " + chrono + ".");
    }

    @Override
    public void exportData(File file,
                           List templateInstances,
                           WorkbookExporter workbookExporter,
                           IssuesHandler issuesHandler,
                           ProgressController controller) throws IOException {
        Checks.isNotNull(file, "file");
        final ImpExFormat format = ImpExFormat.from(file);
        Checks.isNotNull(format, "Can not recognize file format");

        exportDataInt(file,
                      null,
                      file.getPath(),
                      format,
                      templateInstances,
                      workbookExporter,
                      issuesHandler,
                      controller);
    }

    @Override
    public void exportData(OutputStream out,
                           String systemId,
                           ImpExFormat format,
                           List templateInstances,
                           WorkbookExporter workbookExporter,
                           IssuesHandler issuesHandler,
                           ProgressController controller) throws IOException {
        Checks.isNotNull(out, "out");
        Checks.isNotNull(format, "format");

        exportDataInt(null,
                      out,
                      systemId,
                      format,
                      templateInstances,
                      workbookExporter,
                      issuesHandler,
                      controller);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy